Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow addons to add wiki pages to items #3937

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,14 @@ default boolean hasDependency(@Nonnull String dependency) {
return description.getDepend().contains(dependency) || description.getSoftDepend().contains(dependency);
}

/**
* This method returns the wiki URL template for all the items this {@link SlimefunAddon}.
* The "%item%" placeholder will be replaced with the SlimefunItem's ID by default.
*
* @return The wiki URL template for this {@link SlimefunAddon}.
*/
default @Nonnull String getWikiUrlTemplate() {
return "";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoDisenchanter;
import io.github.thebusybiscuit.slimefun4.implementation.items.electric.machines.enchanting.AutoEnchanter;

import com.google.common.base.Preconditions;

import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker;

/**
Expand Down Expand Up @@ -887,17 +889,44 @@ public void postRegister() {
*
* @param page
* The associated wiki page
*
* @deprecated Use {@link #addWikiPage(String)} instead.
*/
@Deprecated
public final void addOfficialWikipage(@Nonnull String page) {
Validate.notNull(page, "Wiki page cannot be null.");
wikiURL = Optional.of("https://github.com/Slimefun/Slimefun4/wiki/" + page);
addWikiPage(page);
}

/**
* This method assign the given wiki page to this Item.
* The page name will replace %item% placeholder in the URL.
*
* @param page
* The associated wiki page name.
*/
public final void addWikiPage(@Nonnull String page) {
Preconditions.checkArgument(page != null, "Wiki page cannot be null.");
Preconditions.checkState(getState() != ItemState.UNREGISTERED, "Wiki page can only be added after item has been registered.");
addCustomWikiPage(getAddon().getWikiUrlTemplate().replace("%item%", page));
}

/**
* This method assign the given wiki URL to this Item.
*
* @param url
* The associated wiki page URL.
*/
public final void addCustomWikiPage(@Nonnull String url) {
Preconditions.checkArgument(url != null, "Wiki page cannot be null.");
Preconditions.checkState(wikiURL.isEmpty(), "Wiki page cannot be modified after it has been set.");
wikiURL = Optional.of(url);
}

/**
* This method returns the wiki page that has been assigned to this item.
* It will return null, if no wiki page was found.
*
* @see SlimefunItem#addOfficialWikipage(String)
* @see SlimefunItem#addWikiPage(String)
*
* @return This item's wiki page
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,11 @@ public String getBugTrackerURL() {
return "https://github.com/Slimefun/Slimefun4/issues";
}

@Override
public @Nonnull String getWikiUrlTemplate() {
return "https://github.com/Slimefun/Slimefun4/wiki/%item%";
}

/**
* This method gets called when the {@link Plugin} gets disabled.
* Most often it is called when the {@link Server} is shutting down or reloading.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.tasks.AsyncRecipeChoiceTask;
import io.github.thebusybiscuit.slimefun4.utils.ChatUtils;
import io.github.thebusybiscuit.slimefun4.utils.ChestMenuUtils;
import io.github.thebusybiscuit.slimefun4.utils.WikiUtils;
import io.github.thebusybiscuit.slimefun4.utils.compatibility.VersionedItemFlag;
import io.github.thebusybiscuit.slimefun4.utils.itemstack.SlimefunGuideItem;

Expand Down Expand Up @@ -515,9 +516,25 @@ public void displayItem(PlayerProfile profile, SlimefunItem item, boolean addToH
Optional<String> wiki = item.getWikipage();

if (wiki.isPresent()) {
menu.addItem(8, new CustomItemStack(Material.KNOWLEDGE_BOOK, ChatColor.WHITE + Slimefun.getLocalization().getMessage(p, "guide.tooltips.wiki"), "", ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + Slimefun.getLocalization().getMessage(p, "guide.tooltips.open-itemgroup")));
String message = Slimefun.getLocalization().getMessage(p, "guide.tooltips.wiki.third-party");
if (WikiUtils.isSlimefunOfficialWiki(wiki.get())) {
message = Slimefun.getLocalization().getMessage(p, "guide.tooltips.wiki.slimefun");
}

menu.addItem(8, new CustomItemStack(
Material.KNOWLEDGE_BOOK,
ChatColor.WHITE + Slimefun.getLocalization().getMessage(p, "guide.tooltips.wiki.button").replace("%addon%", item.getAddon().getName()),
"",
ChatColor.WHITE + message,
"",
ChatColor.GRAY + "\u21E8 " + ChatColor.GREEN + Slimefun.getLocalization().getMessage(p, "guide.tooltips.open-itemgroup")
));
menu.addMenuClickHandler(8, (pl, slot, itemstack, action) -> {
pl.closeInventory();
if (!WikiUtils.isSlimefunOfficialWiki(wiki.get())) {
Slimefun.getLocalization().sendMessage(pl, "messages.wiki-third-party",
msg -> msg.replace("%addon%", item.getAddon().getName()));
}
ChatUtils.sendURL(pl, wiki.get());
return false;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ protected Talisman(ItemGroup itemGroup, SlimefunItemStack item, ItemStack[] reci
this.suffix = messageSuffix;
this.effects = effects;
this.chance = chance;
addOfficialWikipage(WIKI_PAGE);

if (!(this instanceof EnderTalisman)) {
String name = "&5Ender " + ChatColor.stripColor(getItem().getItemMeta().getDisplayName());
Expand Down Expand Up @@ -128,6 +127,7 @@ private SlimefunItemStack getEnderVariant() {

@Override
public void postRegister() {
addWikiPage(WIKI_PAGE);
EnderTalisman talisman = new EnderTalisman(this, getEnderVariant());
talisman.register(getAddon());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.annotation.Nonnull;
Expand All @@ -21,9 +19,6 @@
import org.bukkit.command.CommandSender;
import org.bukkit.inventory.ItemStack;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import io.github.thebusybiscuit.slimefun4.api.events.SlimefunItemRegistryFinalizedEvent;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;
Expand All @@ -32,7 +27,7 @@
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.MakeshiftSmeltery;
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.OreCrusher;
import io.github.thebusybiscuit.slimefun4.implementation.items.multiblocks.Smeltery;
import io.github.thebusybiscuit.slimefun4.utils.JsonUtils;
import io.github.thebusybiscuit.slimefun4.utils.WikiUtils;

import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.AContainer;
import me.mrCookieSlime.Slimefun.Objects.SlimefunItem.abstractItems.MachineRecipe;
Expand All @@ -44,20 +39,7 @@ private PostSetup() {}
public static void setupWiki() {
Slimefun.logger().log(Level.INFO, "Loading Wiki pages...");

try (BufferedReader reader = new BufferedReader(new InputStreamReader(Slimefun.class.getResourceAsStream("/wiki.json"), StandardCharsets.UTF_8))) {
JsonElement element = JsonUtils.parseString(reader.lines().collect(Collectors.joining("")));
JsonObject json = element.getAsJsonObject();

for (Map.Entry<String, JsonElement> entry : json.entrySet()) {
SlimefunItem item = SlimefunItem.getById(entry.getKey());

if (item != null) {
item.addOfficialWikipage(entry.getValue().getAsString());
}
}
} catch (IOException e) {
Slimefun.logger().log(Level.SEVERE, "Failed to load wiki.json file", e);
}
WikiUtils.setupWiki(Slimefun.instance());
}

public static void loadItems() {
Expand All @@ -79,7 +61,7 @@ public static void loadItems() {
}

Bukkit.getPluginManager().callEvent(new SlimefunItemRegistryFinalizedEvent());

loadOreGrinderRecipes();
loadSmelteryRecipes();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package io.github.thebusybiscuit.slimefun4.utils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.Map;
import java.util.function.UnaryOperator;
import java.util.logging.Level;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import javax.annotation.Nonnull;

import org.bukkit.plugin.Plugin;

import io.github.thebusybiscuit.slimefun4.api.SlimefunAddon;
import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem;
import io.github.thebusybiscuit.slimefun4.implementation.Slimefun;

import com.google.common.base.Preconditions;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

/**
* This utility class provides methods to setup the wiki pages for Slimefun addons.
*
* @author ybw0014
*/
public class WikiUtils {

private static final Pattern SLIMEFUN_WIKI_PATTERN = buildPattern(Slimefun.instance().getWikiUrlTemplate());

private WikiUtils() {}

/**
* This method loads the wiki pages from the wiki.json file in the plugin's resources.
*
* @param plugin
* The plugin to load the wiki pages for.
*/
public static void setupWiki(@Nonnull Plugin plugin) {
setupWiki(plugin, page -> page);
}

/**
* This method loads the wiki pages from the wiki.json file in the plugin's resources.
* The formatter will make changes to the wiki page name before it is added to the item.
*
* @param plugin
* The plugin to load the wiki pages for.
* @param formatter
* The formatter to apply to the wiki page name.
*/
public static void setupWiki(@Nonnull Plugin plugin, @Nonnull UnaryOperator<String> formatter) {
Preconditions.checkArgument(plugin != null, "The plugin cannot be null");
Preconditions.checkArgument(formatter != null, "The formatter cannot be null");
Preconditions.checkArgument(plugin instanceof SlimefunAddon, "The plugin must be a SlimefunAddon");

try (BufferedReader reader = new BufferedReader(new InputStreamReader(plugin.getClass().getResourceAsStream("/wiki.json"), StandardCharsets.UTF_8))) {
JsonElement element = JsonUtils.parseString(reader.lines().collect(Collectors.joining("")));
JsonObject json = element.getAsJsonObject();

int count = 0;

for (Map.Entry<String, JsonElement> entry : json.entrySet()) {
SlimefunItem item = SlimefunItem.getById(entry.getKey());

if (item != null) {
String page = entry.getValue().getAsString();
page = formatter.apply(page);
item.addWikiPage(page);
count++;
}
}

plugin.getLogger().log(Level.INFO, MessageFormat.format("Loaded {0} Wiki pages from {1}", count, plugin.getName()));
} catch (Exception e) {
plugin.getLogger().log(Level.SEVERE, MessageFormat.format("Failed to load wiki.json from {0}", plugin.getName()), e);
}
}

/**
* Checks if the given URL is a Slimefun official wiki URL.
*
* @param url
* The URL to check
*
* @return
* Whether the URL is a Slimefun official wiki URL
*/
public static boolean isSlimefunOfficialWiki(@Nonnull String url) {
Preconditions.checkArgument(url != null, "The URL cannot be null");

return SLIMEFUN_WIKI_PATTERN.matcher(url).matches();
}

@Nonnull
private static Pattern buildPattern(@Nonnull String template) {
Preconditions.checkArgument(template != null, "The template cannot be null");

String regexTemplate = template.replace(".", "\\.")
.replace("/", "\\/")
.replace("%item%", ".+");

String regex = "^" + regexTemplate + "$";

return Pattern.compile(regex);
}
}
7 changes: 6 additions & 1 deletion src/main/resources/languages/en/messages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,11 @@ guide:
tooltips:
open-itemgroup: 'Click to open'
versions-notice: 'These are very important when reporting bugs!'
wiki: 'View this Item on the official Slimefun Wiki'
wiki:
button: 'View this item on the %addon% Wiki'
slimefun: 'Official Slimefun Wiki'
third-party: 'Third-Party Wiki'


recipes:
machine: 'Recipes made in this Machine'
Expand Down Expand Up @@ -194,6 +198,7 @@ messages:
deprecated-item: '&4This item has been deprecated and will be removed from Slimefun soon.'
researching-is-disabled: '&cResearching has been disabled on this server. Everything is unlocked by default!'
await-deletion: '&cYou cannot place a Slimefun block so soon after breaking one. Try again shortly.'
wiki-third-party: '&cThe following wiki link is provided by %addon%. Slimefun is not responsible for the content on the page.'

multi-tool:
mode-change: '&b%device% mode changed to: &9%mode%'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,16 @@ void testWikiPages() {
Assertions.assertFalse(item.getWikipage().isPresent());

// null should not be a valid argument
Assertions.assertThrows(IllegalArgumentException.class, () -> item.addOfficialWikipage(null));
Assertions.assertThrows(IllegalArgumentException.class, () -> item.addWikiPage(null));

item.addOfficialWikipage("Test");
item.addWikiPage("Test");

Optional<String> wiki = item.getWikipage();
Assertions.assertTrue(wiki.isPresent());
Assertions.assertEquals("https://github.com/Slimefun/Slimefun4/wiki/Test", wiki.get());

// wiki page shouldn't be changed if it already exists
Assertions.assertThrows(IllegalStateException.class, () -> item.addWikiPage("Test2"));
}

@Test
Expand Down