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

View File

@ -45,7 +45,12 @@ public enum QuestsTranslatableMessage implements TranslatableMessage {
*
* <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
@ -160,6 +165,104 @@ public enum QuestsTranslatableMessage implements TranslatableMessage {
* <p>Placeholders: {areaName}, {questName}, {mobName}, {mobAmount}</p>
*/
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

View File

@ -4,8 +4,10 @@ import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
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.ScrapperTrait;
import net.knarcraft.dynmapcitizens.DynmapCitizens;
import net.knarcraft.dynmapcitizens.property.Icon;
import net.knarcraft.dynmapcitizens.settings.BlacksmithSettings;
@ -48,6 +50,7 @@ public class BlacksmithHandler extends AbstractTraitHandler {
super.markerSet.getMarkers().forEach(GenericMarker::deleteMarker);
Class<? extends Trait> blacksmithTrait = CitizensAPI.getTraitFactory().getTraitClass("blacksmith");
Class<? extends Trait> scrapperTrait = CitizensAPI.getTraitFactory().getTraitClass("scrapper");
for (NPC npc : CitizensAPI.getNPCRegistry()) {
if (npc.hasTrait(blacksmithTrait)) {
BlacksmithTrait trait = npc.getTraitNullable(BlacksmithTrait.class);
@ -60,10 +63,43 @@ public class BlacksmithHandler extends AbstractTraitHandler {
}
addNPCMarker(npc.getUniqueId(), "Blacksmith NPC: ", description,
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
*
@ -71,7 +107,7 @@ public class BlacksmithHandler extends AbstractTraitHandler {
* @param npcSettings <p>The settings to search for information</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 " +
npcSettings.getBlacksmithTitle() + "</h2>";
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.components.Planner;
import net.knarcraft.dynmapcitizens.DynmapCitizens;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.StringReplacer;
import net.knarcraft.knarlib.formatting.TimeFormatter;
import org.jetbrains.annotations.NotNull;
@ -10,12 +12,21 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
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
*/
public class QuestPlannerInfoGenerator {
private final Quest quest;
private final StringFormatter formatter;
/**
* Instantiates a new quest planner info generator
@ -24,6 +35,7 @@ public class QuestPlannerInfoGenerator {
*/
public QuestPlannerInfoGenerator(@NotNull Quest quest) {
this.quest = quest;
this.formatter = DynmapCitizens.getFormatter();
}
/**
@ -33,40 +45,30 @@ public class QuestPlannerInfoGenerator {
*/
public @NotNull String getQuestPlannerInfo() {
Planner planner = quest.getPlanner();
StringBuilder plannerInfo = new StringBuilder();
plannerInfo.append("<b>Planner:</b><ul>");
StringReplacer replacer = new StringReplacer(formatter.getUnFormattedColoredMessage(QUESTS_PLANNER_DESCRIPTION));
//Quest can be repeated after a cool-down
if (planner.hasCooldown()) {
plannerInfo.append("<li>Quest repeatable after: ");
plannerInfo.append(TimeFormatter.getDurationString(DynmapCitizens.getTranslator(),
planner.getCooldown() / 1000));
plannerInfo.append("</li>");
replacer.add("{questCoolDown}", formatter.replacePlaceholder(QUESTS_PLANNER_COOL_DOWN, "{coolDown}",
TimeFormatter.getDurationString(DynmapCitizens.getTranslator(), planner.getCooldown() / 1000)));
} 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
if (planner.hasStart()) {
plannerInfo.append("<li>Quest available from ");
plannerInfo.append(formatTimestamp(planner.getStartInMillis())).append("</li>");
}
replacer.add("{questFrom}", planner.hasStart() ? formatter.replacePlaceholder(QUESTS_PLANNER_FROM,
"{startDate}", formatTimestamp(planner.getStartInMillis())) : "");
//Quest is only available until the end date
if (planner.hasEnd()) {
plannerInfo.append("<li>Quest available until ");
plannerInfo.append(formatTimestamp(planner.getEndInMillis())).append("</li>");
}
replacer.add("{questUntil}", planner.hasEnd() ? formatter.replacePlaceholder(QUESTS_PLANNER_UNTIL,
"{endDate}", formatTimestamp(planner.getEndInMillis())) : "");
//Quest availability repeats
if (planner.hasRepeat()) {
plannerInfo.append("<li>Quest will become available again after ");
plannerInfo.append(TimeFormatter.getDurationString(DynmapCitizens.getTranslator(),
planner.getRepeat() / 1000)).append("</li>");
}
//Quest availability repeats'
replacer.add("{questRepeat}", planner.hasRepeat() ? formatter.replacePlaceholder(QUESTS_PLANNER_REPEAT,
"{repeatDelay}", TimeFormatter.getDurationString(DynmapCitizens.getTranslator(),
planner.getRepeat() / 1000)) : "");
plannerInfo.append("</ul>");
return plannerInfo.toString();
return replacer.replace();
}
/**
@ -76,7 +78,7 @@ public class QuestPlannerInfoGenerator {
* @return <p>A datetime string</p>
*/
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);
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.components.Rewards;
import net.knarcraft.dynmapcitizens.DynmapCitizens;
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.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
*/
public class QuestRewardsInfoGenerator {
private final Quest quest;
private final StringFormatter formatter;
/**
* Instantiates a new quest reward info generator
@ -20,6 +34,7 @@ public class QuestRewardsInfoGenerator {
*/
public QuestRewardsInfoGenerator(@NotNull Quest quest) {
this.quest = quest;
this.formatter = DynmapCitizens.getFormatter();
}
/**
@ -29,36 +44,39 @@ public class QuestRewardsInfoGenerator {
*/
public @NotNull String getQuestRewardsInfo() {
Rewards reward = quest.getRewards();
StringBuilder rewardInfo = new StringBuilder();
rewardInfo.append("<b>Rewards:</b><ul>");
StringReplacer replacer = new StringReplacer(formatter.getUnFormattedColoredMessage(QUESTS_REWARDS_FORMAT));
if (reward.getMoney() > 0) {
rewardInfo.append("<li>").append(reward.getMoney()).append(" ").append(QuestsHelper.getCurrency(
reward.getMoney())).append("</li>");
}
replacer.add("{money}", reward.getMoney() > 0 ? formatter.replacePlaceholders(QUESTS_REWARDS_MONEY,
List.of("{amount}", "{currency}"), List.of(String.valueOf(reward.getMoney()),
QuestsHelper.getCurrency(reward.getMoney()))) : "");
if (reward.getExp() > 0) {
rewardInfo.append("<li>").append(reward.getExp()).append(" exp").append("</li>");
}
replacer.add("{experience}", reward.getExp() > 0 ? formatter.replacePlaceholder(
QUESTS_REWARDS_EXPERIENCE, "{amount}", String.valueOf(reward.getExp())) : "");
if (reward.getQuestPoints() > 0) {
rewardInfo.append("<li>").append(reward.getQuestPoints()).append(" quest point(s)").append("</li>");
}
replacer.add("{questPoints}", reward.getQuestPoints() > 0 ? formatter.replacePlaceholder(
QUESTS_REWARDS_QUEST_POINTS, "{amount}", String.valueOf(reward.getQuestPoints())) : "");
StringBuilder permissionBuilder = new StringBuilder();
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()) {
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()) {
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 rewardInfo.toString();
return replacer.replace();
}
}

View File

@ -6,11 +6,14 @@ import me.pikamug.quests.quests.components.Stage;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPCRegistry;
import net.knarcraft.dynmapcitizens.DynmapCitizens;
import net.knarcraft.dynmapcitizens.formatting.QuestsTranslatableMessage;
import net.knarcraft.dynmapcitizens.handler.trait.AbstractTraitHandler;
import net.knarcraft.dynmapcitizens.property.Icon;
import net.knarcraft.dynmapcitizens.settings.QuestsSettings;
import net.knarcraft.dynmapcitizens.settings.TraitSettings;
import net.knarcraft.dynmapcitizens.util.QuestsHelper;
import net.knarcraft.knarlib.formatting.StringFormatter;
import net.knarcraft.knarlib.formatting.StringReplacer;
import org.bukkit.Bukkit;
import org.dynmap.DynmapAPI;
import org.dynmap.markers.GenericMarker;
@ -25,6 +28,14 @@ import java.util.List;
import java.util.Map;
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
*/
@ -125,7 +136,8 @@ public class QuestsHandler extends AbstractTraitHandler {
List<Quest> offeredQuests = info.getQuestStarts();
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
if (!offeredQuests.isEmpty()) {
@ -153,25 +165,27 @@ public class QuestsHandler extends AbstractTraitHandler {
* @param offeredQuests <p>The list of quests the NPC offers</p>
*/
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) {
stringBuilder.append("<li><h4><b>").append(quest.getName()).append("</b></h4><h5><b>- ");
stringBuilder.append(quest.getDescription()).append("</b></h5>");
if (settings.displayStageInfo()) {
stringBuilder.append(new QuestStagesInfoGenerator(quest).getQuestStagesInfo());
StringReplacer replacer = new StringReplacer(formatter.getUnFormattedMessage(QUESTS_OFFERED_QUEST_FORMAT));
replacer.add("{name}", quest.getName());
replacer.add("{description}", quest.getDescription());
replacer.add("{stages}", settings.displayStageInfo() ?
new QuestStagesInfoGenerator(quest).getQuestStagesInfo() : "");
replacer.add("{rewards}", settings.displayRewardInfo() ?
new QuestRewardsInfoGenerator(quest).getQuestRewardsInfo() : "");
replacer.add("{requirements}", settings.displayRequirementInfo() ?
new QuestRequirementsInfoGenerator(questsAPI, quest).getQuestRequirementsInfo() : "");
replacer.add("{planner}", settings.displayPlannerInfo() ?
new QuestPlannerInfoGenerator(quest).getQuestPlannerInfo() : "");
questsInfoBuilder.append(replacer.replace());
}
if (settings.displayRewardInfo()) {
stringBuilder.append(new QuestRewardsInfoGenerator(quest).getQuestRewardsInfo());
}
if (settings.displayRequirementInfo()) {
stringBuilder.append(new QuestRequirementsInfoGenerator(questsAPI, quest).getQuestRequirementsInfo());
}
if (settings.displayPlannerInfo()) {
stringBuilder.append(new QuestPlannerInfoGenerator(quest).getQuestPlannerInfo());
}
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>
*/
private String getInvolvedInQuestsString(@NotNull NPCQuestInfo info) {
StringFormatter formatter = DynmapCitizens.getFormatter();
List<Quest> questKills = info.getQuestKills();
List<Quest> questInteractions = info.getQuestInteractions();
List<Quest> questDeliveries = info.getQuestDeliveries();
@ -189,25 +204,28 @@ public class QuestsHandler extends AbstractTraitHandler {
return "";
}
StringBuilder markerDescription = new StringBuilder();
markerDescription.append("<h3>Involved in quests:</h3><ul>");
addInvolvedInString("Killed in", questKills, markerDescription);
addInvolvedInString("Delivery target in", questDeliveries, markerDescription);
addInvolvedInString("Interacted with in quest", questInteractions, markerDescription);
markerDescription.append("</ul>");
return markerDescription.toString();
addInvolvedInString(formatter, QUESTS_INVOLVED_IN_KILL, questKills, markerDescription);
addInvolvedInString(formatter, QUESTS_INVOLVED_IN_DELIVERY_TARGET, questDeliveries, markerDescription);
addInvolvedInString(formatter, QUESTS_INVOLVED_IN_INTERACT, questInteractions, markerDescription);
return formatter.replacePlaceholder(QUESTS_INVOLVED_IN_FORMAT, "{involvedQuests}",
markerDescription.toString());
}
/**
* 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 translatableMessage <p>The translatable message to display</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) {
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,
/**
* An icon representing a scrapper NPC
*/
SCRAPPER,
/**
* An icon representing a minstrel NPC
*/

View File

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

View File

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

View File

@ -29,7 +29,8 @@ en:
QUESTS_PLANNER_UNREPEATABLE: "<li>Quest cannot be repeated!</li>"
QUESTS_PLANNER_FROM: "<li>Quest available from {startDate}</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: |
<b>Requirements: </b><ul>
{requirementQuestPoints}
@ -56,6 +57,29 @@ en:
QUESTS_REACH_AREA_DESCRIPTION_FORMAT: "{areaName}Target location for {questName}"
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_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}"
UNIT_NOW: "imminently"
UNIT_SECOND: "second"