Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F12242524
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
25 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/.gitignore b/.gitignore
index 7d7f6f5..3af88f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
.gradle
build/
plugins/**/gradle/
+plugins/suhayl/src/main/resources/resourcepack.properties
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
diff --git a/plugins/suhayl/build.gradle.kts b/plugins/suhayl/build.gradle.kts
index c332be5..d30e3f2 100644
--- a/plugins/suhayl/build.gradle.kts
+++ b/plugins/suhayl/build.gradle.kts
@@ -1,75 +1,147 @@
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.Copy
+import java.security.MessageDigest
+import java.util.Properties
+
plugins {
id("java")
}
group = "org.eu.loupsgris.quilvaryn"
version = "0.1-SNAPSHOT"
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
repositories {
mavenCentral()
maven {
name = "papermc"
url = uri("https://repo.papermc.io/repository/maven-public/")
}
}
dependencies {
testImplementation(platform("org.junit:junit-bom:5.10.0"))
testImplementation("org.junit.jupiter:junit-jupiter")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// Paper API (includes Bukkit + Spigot)
compileOnly("io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT")
// Adventure for l10n
compileOnly("net.kyori:adventure-api:4.24.0")
implementation("net.kyori:adventure-text-serializer-plain:4.24.0")
}
val promoteEnglishMessagesAsDefault by tasks.registering(Copy::class) {
from("src/main/resources/l10n/messages_en.properties")
into("src/main/resources/l10n")
rename { "messages.properties" }
}
tasks.processResources {
dependsOn(
promoteEnglishMessagesAsDefault,
)
}
+tasks.named("build") {
+ dependsOn(
+ promoteEnglishMessagesAsDefault,
+ "updateResourcePackProperties",
+ )
+}
+
+val resourcePackSourceDir = layout.projectDirectory.dir("src/main/resources/resourcepack")
+val resourcePackProperties = layout.projectDirectory.file("src/main/resources/resourcepack.properties")
+
+val resourcePackBuildDir = layout.buildDirectory.dir("resourcepack")
+val resourcePackZip = resourcePackBuildDir.get().file("suhayl.zip")
+val resourcePackSha1 = resourcePackBuildDir.get().file("suhayl.sha1")
+
+tasks.register<Zip>("zipResourcePack") {
+ from(resourcePackSourceDir)
+ archiveFileName.set("suhayl.zip")
+ destinationDirectory.set(resourcePackBuildDir)
+}
+
+tasks.register("computeResourcePackSha1") {
+ dependsOn("zipResourcePack")
+ inputs.file(resourcePackZip)
+ outputs.file(resourcePackSha1)
+
+ doLast {
+ val zipFile = resourcePackZip.asFile
+ val sha1 = MessageDigest.getInstance("SHA-1")
+ .digest(zipFile.readBytes())
+ .joinToString("") { "%02x".format(it) }
+
+ resourcePackSha1.asFile.writeText(sha1)
+ println("Resource pack SHA1: $sha1")
+ }
+}
+
+tasks.register("updateResourcePackProperties") {
+ dependsOn("computeResourcePackSha1")
+
+ doLast {
+ val sha1 = resourcePackSha1.asFile.readText().trim()
+ val propsFile = resourcePackProperties.asFile
+
+ val props = Properties().apply {
+ if (propsFile.exists()) {
+ propsFile.inputStream().use { load(it) }
+ }
+ }
+
+ props["resourcepack.url"] = "https://windriver.nasqueron.org/~minecraft/packs/suhayl.zip"
+ props["resourcepack.sha1"] = sha1
+
+ propsFile.outputStream().use { props.store(it, "Updated by Gradle") }
+
+ println("Updated ${propsFile.name} with SHA1=$sha1")
+ }
+}
+
+tasks.register<Exec>("deployResourcePack") {
+ val remoteHost = (findProperty("remoteHost") as String?) ?: "windriver.nasqueron.org"
+ val remoteUser = (findProperty("remoteUser") as String?) ?: System.getenv("USER") ?: "deploy"
+ val remoteDir = (findProperty("remoteResourcePackDir") as String?) ?: "/var/home-wwwroot/minecraft/packs/"
+
+ dependsOn("updateResourcePackProperties")
+ val zipFile = resourcePackZip.asFile
+ commandLine("scp", zipFile.absolutePath, "$remoteUser@$remoteHost:$remoteDir")
+}
+
tasks.register<Exec>("deploy") {
group = "deployment"
description = "SCP the built JAR to windriver.nasqueron.org (configurable via -PremoteUser and -PremoteDir)."
dependsOn(
tasks.named("build"),
tasks.named("jar"),
+ tasks.named("deployResourcePack"),
)
val remoteHost = (findProperty("remoteHost") as String?) ?: "windriver.nasqueron.org"
val remoteUser = (findProperty("remoteUser") as String?) ?: System.getenv("USER") ?: "deploy"
val remoteDir = (findProperty("remoteDir") as String?) ?: ""
// Resolve the jar file produced by the 'jar' task
val jarTask = tasks.named<Jar>("jar").get()
val jarFileProvider = jarTask.archiveFile
doFirst {
val jarFile = jarFileProvider.get().asFile
if (!jarFile.exists()) {
throw GradleException("JAR not found at ${'$'}{jarFile.absolutePath}. Try running './gradlew build' first.")
}
commandLine("scp", jarFile.absolutePath, "$remoteUser@$remoteHost:$remoteDir")
}
}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/SuhaylPlugin.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/SuhaylPlugin.java
index 26c2b33..e87d5c1 100644
--- a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/SuhaylPlugin.java
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/SuhaylPlugin.java
@@ -1,83 +1,88 @@
package org.eu.loupsgris.quilvaryn;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.eu.loupsgris.quilvaryn.config.SuhaylConfig;
import org.eu.loupsgris.quilvaryn.config.SuhaylTranslationRegistry;
import org.eu.loupsgris.quilvaryn.items.CommandmentStick;
-import org.eu.loupsgris.quilvaryn.listeners.HappyGhastBehavior;
-import org.eu.loupsgris.quilvaryn.listeners.OptimizedWeather;
-import org.eu.loupsgris.quilvaryn.listeners.WanderingTraderBehavior;
+import org.eu.loupsgris.quilvaryn.items.Quill;
+import org.eu.loupsgris.quilvaryn.listeners.*;
import org.eu.loupsgris.quilvaryn.services.WanderingTraderService;
import org.eu.loupsgris.quilvaryn.utils.ResourceLoader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
public class SuhaylPlugin extends JavaPlugin {
public SuhaylConfig config;
public static final String NAMESPACE = "suhayl";
@Override
public void onEnable() {
config = loadConfig();
loadTranslationRegistry();
// Register features
Bukkit.getPluginManager().registerEvents(new OptimizedWeather(this), this);
Bukkit.getPluginManager().registerEvents(new HappyGhastBehavior(this), this);
registerCommandmentStick();
+ registerQuill();
}
private SuhaylConfig loadConfig() {
File configFile = new File(getDataFolder(), "config.yml");
if (!configFile.exists()) {
return SuhaylConfig.byDefault();
}
getLogger().info("Loading custom " + configFile.getName());
return SuhaylConfig.Load(this.getConfig());
}
private void loadTranslationRegistry() {
ResourceLoader loader = path -> {
InputStream stream = this.getResource(path);
if (stream == null) {
throw new FileNotFoundException(path);
}
return stream;
};
SuhaylTranslationRegistry registry = new SuhaylTranslationRegistry(
getLogger(),
loader
);
registry.load();
}
private void registerCommandmentStick() {
WanderingTraderService service = new WanderingTraderService(config, getLogger());
WanderingTraderBehavior listener = new WanderingTraderBehavior(service);
Bukkit.getPluginManager().registerEvents(listener, this);
Bukkit.addRecipe(CommandmentStick.getRecipe());
}
+ private void registerQuill() {
+ Bukkit.getPluginManager().registerEvents(new QuillBehavior(), this);
+ Bukkit.addRecipe(Quill.getRecipe());
+ }
+
@Override
public void onDisable() {
getLogger().info("Suhayl quality of life plugin disabled.");
}
}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylMessages.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylMessages.java
index a6b1923..4c3bb84 100644
--- a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylMessages.java
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylMessages.java
@@ -1,21 +1,27 @@
package org.eu.loupsgris.quilvaryn.config;
+import org.bukkit.entity.Player;
+
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
public class SuhaylMessages {
public static final String BUNDLE_BASENAME = "l10n.messages";
public static String get(String key, Locale locale) {
try {
ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_BASENAME, locale);
return bundle.getString(key);
} catch (MissingResourceException e) {
return "#" + key + "#";
}
}
+ public static String get(String key, Player player) {
+ return get(key, player.locale());
+ }
+
}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/items/Quill.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/items/Quill.java
new file mode 100644
index 0000000..8777f39
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/items/Quill.java
@@ -0,0 +1,150 @@
+package org.eu.loupsgris.quilvaryn.items;
+
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+
+import org.bukkit.Material;
+import org.bukkit.NamespacedKey;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.ShapedRecipe;
+import org.bukkit.inventory.meta.ItemMeta;
+import org.bukkit.persistence.PersistentDataContainer;
+import org.bukkit.persistence.PersistentDataType;
+
+import org.eu.loupsgris.quilvaryn.SuhaylPlugin;
+import org.eu.loupsgris.quilvaryn.config.SuhaylMessages;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Random;
+
+public class Quill {
+
+ public static final String ITEM_TAG = "is_quill";
+
+ public static final String DURABILITY_TAG = "durability";
+ public static final int MAX_DURABILITY = 16;
+
+ /**
+ * Create the Quill item.
+ */
+ public static ItemStack getItem() {
+ ItemStack item = new ItemStack(Material.FEATHER, 1);
+
+ item.editMeta(meta -> {
+ meta.displayName(Component.translatable("item.quill.name"));
+
+ meta.lore(List.of(
+ Component.translatable("item.quill.lore1").color(NamedTextColor.GRAY),
+ Component.translatable("item.quill.lore2").color(NamedTextColor.GRAY)
+ ));
+
+ PersistentDataContainer dataContainer = meta.getPersistentDataContainer();
+ NamespacedKey key = new NamespacedKey(SuhaylPlugin.NAMESPACE, ITEM_TAG);
+ dataContainer.set(key, PersistentDataType.BOOLEAN, true);
+
+ meta.setMaxStackSize(1);
+ });
+
+ setDurability(item, MAX_DURABILITY);
+
+ return item;
+ }
+
+ public static boolean isItem(ItemStack item) {
+ if (item.getType() != Material.FEATHER || !item.hasItemMeta()) {
+ return false;
+ }
+
+ ItemMeta meta = item.getItemMeta();
+ PersistentDataContainer pdc = meta.getPersistentDataContainer();
+
+ NamespacedKey key = new NamespacedKey(SuhaylPlugin.NAMESPACE, ITEM_TAG);
+ return
+ pdc.has(key, PersistentDataType.BOOLEAN)
+ &&
+ pdc.get(key, PersistentDataType.BOOLEAN);
+ }
+
+ public static ShapedRecipe getRecipe() {
+ NamespacedKey key = new NamespacedKey(SuhaylPlugin.NAMESPACE, "quill");
+ ItemStack quill = getItem();
+
+ ShapedRecipe recipe = new ShapedRecipe(key, quill);
+ recipe.shape(
+ " F ",
+ " I ",
+ " "
+ );
+ recipe.setIngredient('F', Material.FEATHER);
+ recipe.setIngredient('I', Material.INK_SAC);
+
+ return recipe;
+ }
+
+ ///
+ /// Durability
+ ///
+
+ private static Optional<Integer> getDurability(ItemStack item) {
+ try {
+ PersistentDataContainer dataContainer = item.getItemMeta().getPersistentDataContainer();
+
+ NamespacedKey durabilityKey = new NamespacedKey(SuhaylPlugin.NAMESPACE, DURABILITY_TAG);
+ int durability = dataContainer.get(durabilityKey, PersistentDataType.INTEGER);
+
+ return Optional.of(durability);
+ } catch (NullPointerException ex) {
+ return Optional.empty();
+ }
+ }
+
+ private static void setDurability(ItemStack item, int durability) {
+ item.editMeta(meta -> {
+ PersistentDataContainer dataContainer = meta.getPersistentDataContainer();
+
+ NamespacedKey durabilityKey = new NamespacedKey(SuhaylPlugin.NAMESPACE, DURABILITY_TAG);
+ dataContainer.set(durabilityKey, PersistentDataType.INTEGER, durability);
+ });
+ }
+
+ public static void consumeDurability(ItemStack item, Player player) {
+ var optionalDurability = getDurability(item);
+ if (optionalDurability.isEmpty()) {
+ return;
+ }
+
+ int durability = optionalDurability.get() - 1;
+
+ if (durability > 0) {
+ setDurability(item, durability);
+ } else {
+ // Break item
+ breakItem(player, item);
+ }
+ }
+
+ private static void breakItem(Player player, ItemStack item) {
+ item.setAmount(0);
+
+ player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, 1f, 1f);
+
+ if (canRecycleFeather()) {
+ player.getInventory().addItem(new ItemStack(Material.FEATHER));
+ player.sendMessage(Component.text(SuhaylMessages.get("item.quill.break.recycled", player))
+ .color(NamedTextColor.GRAY));
+ } else {
+ player.sendMessage(Component.text(SuhaylMessages.get("item.quill.break.normal", player))
+ .color(NamedTextColor.GRAY));
+ }
+ }
+
+ private static Boolean canRecycleFeather () {
+ Random random = new Random();
+
+ return random.nextInt(4) == 0;
+ }
+
+}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/listeners/QuillBehavior.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/listeners/QuillBehavior.java
new file mode 100644
index 0000000..5bb5518
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/listeners/QuillBehavior.java
@@ -0,0 +1,143 @@
+package org.eu.loupsgris.quilvaryn.listeners;
+
+import io.papermc.paper.dialog.Dialog;
+import io.papermc.paper.registry.data.dialog.ActionButton;
+import io.papermc.paper.registry.data.dialog.DialogBase;
+import io.papermc.paper.registry.data.dialog.action.DialogAction;
+import io.papermc.paper.registry.data.dialog.action.DialogActionCallback;
+import io.papermc.paper.registry.data.dialog.input.DialogInput;
+import io.papermc.paper.registry.data.dialog.type.DialogType;
+
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.event.ClickCallback;
+import net.kyori.adventure.text.format.NamedTextColor;
+
+import org.bukkit.block.BlockState;
+import org.bukkit.block.Container;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+
+import org.eu.loupsgris.quilvaryn.config.SuhaylMessages;
+import org.eu.loupsgris.quilvaryn.items.Quill;
+
+import java.util.List;
+import java.util.Locale;
+
+public class QuillBehavior implements Listener {
+
+ ///
+ /// Events
+ ///
+
+ @EventHandler
+ public void onQuillUse(PlayerInteractEvent event) {
+ if (!event.getAction().isRightClick() || event.getClickedBlock() == null) {
+ return;
+ }
+
+ if (event.getHand() != EquipmentSlot.HAND) {
+ return;
+ }
+
+ Player player = event.getPlayer();
+ ItemStack item = event.getItem();
+
+ if (item == null || !Quill.isItem(item)) {
+ return;
+ }
+
+ BlockState state = event.getClickedBlock().getState();
+ if (!(state instanceof Container container)) {
+ return;
+ }
+
+ InventoryType containerType = container.getInventory().getType();
+ if (!isValidInventoryType(containerType)) {
+ return;
+ }
+
+ event.setCancelled(true);
+ startQuillDialog(player, item, container);
+ }
+
+ ///
+ /// Dialog API
+ ///
+
+ private void startQuillDialog(Player player, ItemStack item, Container container) {
+ Locale locale = player.locale();
+
+ Component title = Component.text(SuhaylMessages.get("dialog.rename_container.title", locale))
+ .color(NamedTextColor.GOLD);
+
+ Component inputLabel = Component.text(SuhaylMessages.get("dialog.rename_container.input.label", locale))
+ .color(NamedTextColor.GRAY);
+
+ Component confirmButton = Component.text(SuhaylMessages.get("dialog.generic.button.confirm", locale))
+ .color(NamedTextColor.GREEN);
+ Component cancelButton = Component.text(SuhaylMessages.get("dialog.generic.button.cancel", locale))
+ .color(NamedTextColor.GRAY);
+
+ Dialog dialog = Dialog.create(builder -> builder.empty()
+ .base(DialogBase.builder(title)
+ .inputs(List.of(
+ DialogInput.text("label", inputLabel)
+ .build()
+ ))
+ .build()
+ )
+ .type(DialogType.confirmation(
+ ActionButton.create(
+ confirmButton,
+ null,
+ 100,
+ DialogAction.customClick(
+ updateContainerLabel(player, item, container),
+ ClickCallback.Options.builder()
+ .uses(1)
+ .lifetime(ClickCallback.DEFAULT_LIFETIME)
+ .build()
+ )
+ ),
+ ActionButton.create(
+ cancelButton,
+ null,
+ 100,
+ null // closes the dialog
+ )
+ ))
+ );
+
+ player.showDialog(dialog);
+ }
+
+ private static DialogActionCallback updateContainerLabel(Player player, ItemStack item, Container container) {
+ return (view, audience) -> {
+ String label = view.getText("label");
+
+ if (audience instanceof Player && label != null) {
+ container.customName(Component.text(label));
+ container.update();
+
+ Quill.consumeDurability(item, player);
+ }
+ };
+ }
+
+ ///
+ /// Helper methods
+ ///
+
+ private boolean isValidInventoryType(InventoryType type) {
+ return switch (type) {
+ case CHEST, BARREL, SHULKER_BOX -> true;
+ default -> false;
+ };
+ }
+
+}
diff --git a/plugins/suhayl/src/main/resources/l10n/messages.properties b/plugins/suhayl/src/main/resources/l10n/messages.properties
index c4663c6..5ebc097 100644
--- a/plugins/suhayl/src/main/resources/l10n/messages.properties
+++ b/plugins/suhayl/src/main/resources/l10n/messages.properties
@@ -1,13 +1,22 @@
item.commandment_stick.name=Commandment Stick
item.commandment_stick.lore1=Right-click a Wandering Trader
item.commandment_stick.lore2=to give them instructions.
wandering_trader_menu.title=Trader Etiquette
wandering_trader_menu.options.leave=All business is done, you can leave.
wandering_trader_menu.options.banish=Come back later. No more trader this week.
wandering_trader_menu.options.silence=Shhh! Be quiet.
wandering_trader_menu.actions.left=The trader nods and drifts away...
wandering_trader_menu.actions.ban=Wandering traders are discouraged from visiting for a while.
wandering_trader_menu.actions.silenced=The trader goes quiet.
wandering_trader_menu.actions.unsilenced=The trader finds their voice again.
+
+dialog.generic.button.confirm=Confirm
+dialog.generic.button.cancel=Cancel
+
+dialog.rename_container.title=Write a label
+dialog.rename_container.input.label=Label
+
+item.quill.break.recycled=✒ The quill’s ink fades away, leaving only a feather.
+item.quill.break.normal=✒ The quill is torn and can’t be used anymore.
diff --git a/plugins/suhayl/src/main/resources/l10n/messages_en.properties b/plugins/suhayl/src/main/resources/l10n/messages_en.properties
index c4663c6..5ebc097 100644
--- a/plugins/suhayl/src/main/resources/l10n/messages_en.properties
+++ b/plugins/suhayl/src/main/resources/l10n/messages_en.properties
@@ -1,13 +1,22 @@
item.commandment_stick.name=Commandment Stick
item.commandment_stick.lore1=Right-click a Wandering Trader
item.commandment_stick.lore2=to give them instructions.
wandering_trader_menu.title=Trader Etiquette
wandering_trader_menu.options.leave=All business is done, you can leave.
wandering_trader_menu.options.banish=Come back later. No more trader this week.
wandering_trader_menu.options.silence=Shhh! Be quiet.
wandering_trader_menu.actions.left=The trader nods and drifts away...
wandering_trader_menu.actions.ban=Wandering traders are discouraged from visiting for a while.
wandering_trader_menu.actions.silenced=The trader goes quiet.
wandering_trader_menu.actions.unsilenced=The trader finds their voice again.
+
+dialog.generic.button.confirm=Confirm
+dialog.generic.button.cancel=Cancel
+
+dialog.rename_container.title=Write a label
+dialog.rename_container.input.label=Label
+
+item.quill.break.recycled=✒ The quill’s ink fades away, leaving only a feather.
+item.quill.break.normal=✒ The quill is torn and can’t be used anymore.
diff --git a/plugins/suhayl/src/main/resources/l10n/messages_fr.properties b/plugins/suhayl/src/main/resources/l10n/messages_fr.properties
index 29b103b..602ef11 100644
--- a/plugins/suhayl/src/main/resources/l10n/messages_fr.properties
+++ b/plugins/suhayl/src/main/resources/l10n/messages_fr.properties
@@ -1,13 +1,22 @@
item.commandment_stick.name=Bâton de commandement
item.commandment_stick.lore1=Permet de donner des instructions
item.commandment_stick.lore2=aux marchands ambulants
wandering_trader_menu.title=Marchand ambulant
wandering_trader_menu.options.leave=Toutes les affaires sont terminées, vous pouvez partir.
wandering_trader_menu.options.banish=Revenez plus tard, pas de marchand cette semaine.
wandering_trader_menu.options.silence=Chut ... silence !
wandering_trader_menu.actions.left=Le marchand hoche la tête et s'éloigne ...
wandering_trader_menu.actions.ban=Les marchands ambulants sont découragés de nous rendre visite cette semaine.
wandering_trader_menu.actions.silenced=§7Le marchand garde le silence.
wandering_trader_menu.actions.unsilenced=§7Le marchand parle à nouveau.
+
+dialog.generic.button.confirm=Écrire
+dialog.generic.button.cancel=Annuler
+
+dialog.rename_container.title=Inscription
+dialog.rename_container.input.label=Texte
+
+item.quill.break.recycled=✒ L’encre s’estompe doucement, ne subsiste qu’une plume.
+item.quill.break.normal=✒ La plume se brise et ne peut plus être utilisée.
diff --git a/plugins/suhayl/src/main/resources/resourcepack/assets/suhayl/lang/en_us.json b/plugins/suhayl/src/main/resources/resourcepack/assets/suhayl/lang/en_us.json
new file mode 100644
index 0000000..1fcf6d6
--- /dev/null
+++ b/plugins/suhayl/src/main/resources/resourcepack/assets/suhayl/lang/en_us.json
@@ -0,0 +1,5 @@
+{
+ "item.quill.name": "Quill",
+ "item.quill.lore1": "Right-click a container",
+ "item.quill.lore2": "to label it."
+}
diff --git a/plugins/suhayl/src/main/resources/resourcepack/assets/suhayl/lang/fr_fr.json b/plugins/suhayl/src/main/resources/resourcepack/assets/suhayl/lang/fr_fr.json
new file mode 100644
index 0000000..c3d256c
--- /dev/null
+++ b/plugins/suhayl/src/main/resources/resourcepack/assets/suhayl/lang/fr_fr.json
@@ -0,0 +1,5 @@
+{
+ "item.quill.name": "Plume",
+ "item.quill.lore1": "Permet d'écrire sur",
+ "item.quill.lore2": "un coffre ou un tonneau."
+}
diff --git a/plugins/suhayl/src/main/resources/resourcepack/pack.mcmeta b/plugins/suhayl/src/main/resources/resourcepack/pack.mcmeta
new file mode 100644
index 0000000..3032c21
--- /dev/null
+++ b/plugins/suhayl/src/main/resources/resourcepack/pack.mcmeta
@@ -0,0 +1,6 @@
+{
+ "pack": {
+ "pack_format": 64,
+ "description": "Localisation for Quilvaryn server quality of life tweaks."
+ }
+}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Oct 12, 09:15 (8 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3065639
Default Alt Text
(25 KB)
Attached To
Mode
rQVR Quilvaryn
Attached
Detach File
Event Timeline
Log In to Comment