Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F11687352
D3647.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
28 KB
Referenced Files
None
Subscribers
None
D3647.diff
View Options
diff --git a/plugins/suhayl/build.gradle.kts b/plugins/suhayl/build.gradle.kts
--- a/plugins/suhayl/build.gradle.kts
+++ b/plugins/suhayl/build.gradle.kts
@@ -1,3 +1,6 @@
+import org.gradle.api.tasks.bundling.Jar
+import org.gradle.api.tasks.Copy
+
plugins {
id("java")
}
@@ -27,4 +30,46 @@
// 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.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"),
+ )
+
+ 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
--- a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/SuhaylPlugin.java
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/SuhaylPlugin.java
@@ -3,22 +3,76 @@
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
-import org.eu.loupsgris.quilvaryn.config.DefaultSuhaylConfig;
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.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 = new DefaultSuhaylConfig();
+ config = loadConfig();
+
+ loadTranslationRegistry();
// Register features
Bukkit.getPluginManager().registerEvents(new OptimizedWeather(this), this);
Bukkit.getPluginManager().registerEvents(new HappyGhastBehavior(this), this);
+
+ registerCommandmentStick();
+ }
+
+ 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());
}
@Override
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/DefaultSuhaylConfig.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/DefaultSuhaylConfig.java
deleted file mode 100644
--- a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/DefaultSuhaylConfig.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.eu.loupsgris.quilvaryn.config;
-
-public class DefaultSuhaylConfig extends SuhaylConfig {
-
- public DefaultSuhaylConfig() {
- happyGhastSpeedBoost = 2.0;
- rainRate = 0.7;
- }
-
-}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylConfig.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylConfig.java
--- a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylConfig.java
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylConfig.java
@@ -1,10 +1,13 @@
package org.eu.loupsgris.quilvaryn.config;
+import org.bukkit.configuration.file.FileConfiguration;
+
public class SuhaylConfig {
/*
* No-op values:
- * 1.0 for multipliers
+ * 1.0 for multipliers.
+ * 0.0 for cooldown delays.
*
* Actual default values are in Default- class.
*/
@@ -13,4 +16,43 @@
public double rainRate = 1.0;
+ public double commandmentStickBanTime = 0.0;
+
+ public static SuhaylConfig Load (FileConfiguration inFileConfig) {
+ SuhaylConfig loadedConfig = new SuhaylConfig();
+ SuhaylConfig defaultConfig = byDefault();
+
+ loadedConfig.happyGhastSpeedBoost = inFileConfig.getDouble(
+ "happyGhastSpeedBoost",
+ defaultConfig.happyGhastSpeedBoost
+ );
+
+ loadedConfig.rainRate = inFileConfig.getDouble(
+ "rainRate",
+ defaultConfig.rainRate
+ );
+
+ loadedConfig.commandmentStickBanTime = inFileConfig.getDouble(
+ "commandmentStick.banTime",
+ defaultConfig.commandmentStickBanTime
+ );
+
+ return loadedConfig;
+ }
+
+ public static SuhaylConfig byDefault() {
+ SuhaylConfig defaultConfig = new SuhaylConfig();
+ defaultConfig.setDefault();
+
+ return defaultConfig;
+ }
+
+ public void setDefault() {
+ happyGhastSpeedBoost = 2.4;
+
+ rainRate = 0.7;
+
+ commandmentStickBanTime = 120;
+ }
+
}
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
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylMessages.java
@@ -0,0 +1,21 @@
+package org.eu.loupsgris.quilvaryn.config;
+
+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 + "#";
+ }
+ }
+
+}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylTranslationRegistry.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylTranslationRegistry.java
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/config/SuhaylTranslationRegistry.java
@@ -0,0 +1,72 @@
+package org.eu.loupsgris.quilvaryn.config;
+
+import net.kyori.adventure.key.Key;
+import net.kyori.adventure.translation.GlobalTranslator;
+import net.kyori.adventure.translation.TranslationRegistry;
+
+import org.eu.loupsgris.quilvaryn.SuhaylPlugin;
+import org.eu.loupsgris.quilvaryn.utils.ResourceLoader;
+
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.Locale;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class SuhaylTranslationRegistry {
+
+ private final Logger logger;
+
+ private final ResourceLoader loader;
+
+ public SuhaylTranslationRegistry(
+ Logger logger,
+ ResourceLoader loader
+ ) {
+ this.logger = logger;
+ this.loader = loader;
+ }
+
+ public void load() {
+ Key key = Key.key(SuhaylPlugin.NAMESPACE, "translations");
+ TranslationRegistry registry = TranslationRegistry.create(key);
+
+ Locale[] frenchLocales = new Locale[]{
+ Locale.FRENCH,
+ Locale.FRANCE,
+ Locale.CANADA_FRENCH,
+ };
+
+ loadBundle("l10n/messages_en.properties", Locale.ENGLISH, registry);
+ loadBundle("l10n/messages_fr.properties", frenchLocales, registry);
+
+ registry.defaultLocale(Locale.ENGLISH);
+ GlobalTranslator.translator().addSource(registry);
+ }
+
+ private void loadBundle(String path, Locale locale, TranslationRegistry registry) {
+ Locale[] locales = {locale};
+
+ loadBundle(path, locales, registry);
+ }
+
+ private void loadBundle(String path, Locale[] locales, TranslationRegistry registry) {
+ try (var stream = loader.open(path)) {
+ if (stream == null) {
+ logger.warning("Missing translation file: " + path);
+ return;
+ }
+ ResourceBundle bundle = new PropertyResourceBundle(
+ new InputStreamReader(stream, StandardCharsets.UTF_8)
+ );
+
+ for (Locale locale : locales) {
+ registry.registerAll(locale, bundle, true);
+ }
+ } catch (Exception e) {
+ logger.log(Level.SEVERE, "Error loading translations file: " + path, e);
+ }
+ }
+}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/items/CommandmentStick.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/items/CommandmentStick.java
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/items/CommandmentStick.java
@@ -0,0 +1,80 @@
+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.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 java.util.List;
+
+public class CommandmentStick {
+
+ public final static String ITEM_TAG = "is_commandment_stick";
+
+ public static ItemStack getItem() {
+ ItemStack item = new ItemStack(Material.BLAZE_ROD);
+
+ item.editMeta(meta -> {
+ // Gold is uncommon
+ meta.customName(
+ Component.translatable("item.commandment_stick.name", NamedTextColor.GOLD)
+ );
+
+ meta.lore(List.of(
+ Component.translatable("item.commandment_stick.lore1", NamedTextColor.GRAY),
+ Component.translatable("item.commandment_stick.lore2", NamedTextColor.GRAY)
+ ));
+
+ NamespacedKey key = new NamespacedKey(SuhaylPlugin.NAMESPACE, ITEM_TAG);
+ meta.getPersistentDataContainer()
+ .set(key, PersistentDataType.BOOLEAN, true);
+
+ meta.setMaxStackSize(1);
+ });
+
+ return item;
+ }
+
+ public static Boolean isItem(ItemStack item) {
+ if (item.getType() != Material.BLAZE_ROD || !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, "commandment_stick"
+ );
+ ItemStack item = getItem();
+
+ ShapedRecipe recipe = new ShapedRecipe(key, item);
+ recipe.shape(
+ " G ",
+ " P ",
+ " S "
+ );
+ recipe.setIngredient('G', Material.GOLD_NUGGET);
+ recipe.setIngredient('P', Material.PAPER);
+ recipe.setIngredient('S', Material.STICK);
+
+ return recipe;
+ }
+
+}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/listeners/WanderingTraderBehavior.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/listeners/WanderingTraderBehavior.java
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/listeners/WanderingTraderBehavior.java
@@ -0,0 +1,110 @@
+package org.eu.loupsgris.quilvaryn.listeners;
+
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.event.player.PlayerInteractEntityEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+
+import org.eu.loupsgris.quilvaryn.items.CommandmentStick;
+import org.eu.loupsgris.quilvaryn.menus.WanderingTraderMenu;
+import org.eu.loupsgris.quilvaryn.services.WanderingTraderService;
+
+import java.util.Optional;
+import java.util.UUID;
+
+public class WanderingTraderBehavior implements Listener {
+
+ private final WanderingTraderService service;
+
+ public WanderingTraderBehavior(WanderingTraderService service) {
+ this.service = service;
+ }
+
+ @EventHandler
+ public void onTraderSpawn(CreatureSpawnEvent event) {
+ if (event.getEntityType() != EntityType.WANDERING_TRADER) {
+ return;
+ }
+
+ if (!service.canTradersVisit()) {
+ event.setCancelled(true);
+ }
+ }
+
+
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onUseStick(PlayerInteractEntityEvent event) {
+ if (event.getRightClicked().getType() != EntityType.WANDERING_TRADER) {
+ return;
+ }
+
+ if (event.getHand() != EquipmentSlot.HAND) {
+ return;
+ }
+
+ Player player = event.getPlayer();
+ ItemStack item = player.getInventory().getItemInMainHand();
+
+ if (!CommandmentStick.isItem(item)) {
+ return;
+ }
+
+ event.setCancelled(true);
+
+ UUID traderId = event.getRightClicked().getUniqueId();
+ service.openMenuFor(
+ player,
+ traderId
+ );
+ }
+
+ @EventHandler
+ public void onInventoryClick(InventoryClickEvent event) {
+ if (!(event.getWhoClicked() instanceof Player player)) {
+ return;
+ }
+
+ Optional<WanderingTraderMenu> menuOption = service.getMenuFor(player);
+ if (menuOption.isEmpty()) {
+ return;
+ }
+
+ WanderingTraderMenu menu = menuOption.get();
+
+ if (!event.getView().getTitle().equals(menu.getTitle())) {
+ return;
+ }
+
+ event.setCancelled(true);
+
+ ItemStack selectedItem = event.getCurrentItem();
+ menu.handleClick(selectedItem);
+ }
+
+ @EventHandler
+ public void onClose(InventoryCloseEvent e) {
+ if (!(e.getPlayer() instanceof Player player)) {
+ return;
+ }
+
+ Optional<WanderingTraderMenu> menuOption = service.getMenuFor(player);
+ if (menuOption.isEmpty()) {
+ return;
+ }
+
+ WanderingTraderMenu menu = menuOption.get();
+
+ if (e.getView().getTitle().equals(menu.getTitle())) {
+ service.removeMenuFor(player);
+ }
+ }
+
+}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/menus/WanderingTraderMenu.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/menus/WanderingTraderMenu.java
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/menus/WanderingTraderMenu.java
@@ -0,0 +1,96 @@
+package org.eu.loupsgris.quilvaryn.menus;
+
+import net.kyori.adventure.text.Component;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Listener;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+import org.eu.loupsgris.quilvaryn.config.SuhaylMessages;
+import org.eu.loupsgris.quilvaryn.services.WanderingTraderService;
+
+import java.util.Locale;
+import java.util.UUID;
+
+public class WanderingTraderMenu implements Listener {
+
+ private final WanderingTraderService service;
+
+ private final Player player;
+
+ private final UUID traderId;
+
+ private String title;
+
+ private String labelLeave;
+
+ private String labelBanish;
+
+ private String labelSilence;
+
+ public WanderingTraderMenu (
+ WanderingTraderService service,
+ Player player,
+ UUID traderId
+ ) {
+ this.service = service;
+ this.player = player;
+ this.traderId = traderId;
+
+ loadLocalisation(player.locale());
+ }
+
+ private void loadLocalisation(Locale locale) {
+ this.title = SuhaylMessages.get("wandering_trader_menu.title", locale);
+
+ this.labelLeave = SuhaylMessages.get("wandering_trader_menu.options.leave", locale);
+ this.labelBanish = SuhaylMessages.get("wandering_trader_menu.options.banish", locale);
+ this.labelSilence = SuhaylMessages.get("wandering_trader_menu.options.silence", locale);
+ }
+
+ public String getTitle() {
+ return this.title;
+ }
+
+ public void open() {
+ Inventory inventory = Bukkit.createInventory(player, 9, title);
+
+ inventory.setItem(2, buildButton(Material.LIME_DYE, labelLeave));
+ inventory.setItem(4, buildButton(Material.CLOCK, labelBanish));
+ inventory.setItem(6, buildButton(Material.MUSIC_DISC_13, labelSilence));
+
+ player.openInventory(inventory);
+ }
+
+ private ItemStack buildButton(Material material, String name) {
+ ItemStack item = new ItemStack(material);
+
+ item.editMeta(meta -> meta.displayName(
+ Component.text(name)
+ ));
+
+ return item;
+ }
+
+ public void handleClick(ItemStack selectedItem) {
+ if (selectedItem == null || !selectedItem.hasItemMeta()) {
+ return;
+ }
+ String name = selectedItem.getItemMeta().getDisplayName();
+
+ if (name.equals(labelLeave)) {
+ service.askToLeave(player, traderId);
+ player.closeInventory();
+ } else if (name.equals(labelBanish)) {
+ service.banish(player, traderId);
+ player.closeInventory();
+ } else if (name.equals(labelSilence)) {
+ service.toggleSilence(player, traderId);
+ player.closeInventory();
+ }
+ }
+
+}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/services/WanderingTraderService.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/services/WanderingTraderService.java
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/services/WanderingTraderService.java
@@ -0,0 +1,139 @@
+package org.eu.loupsgris.quilvaryn.services;
+
+import org.bukkit.World;
+import org.bukkit.entity.*;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+
+import org.eu.loupsgris.quilvaryn.config.SuhaylConfig;
+import org.eu.loupsgris.quilvaryn.config.SuhaylMessages;
+import org.eu.loupsgris.quilvaryn.menus.WanderingTraderMenu;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+import java.util.logging.Logger;
+
+public class WanderingTraderService {
+
+ private final SuhaylConfig config;
+
+ private final Logger logger;
+
+ private long banishUntil = 0L;
+
+ private final Map<UUID, WanderingTraderMenu> openMenus;
+
+ public WanderingTraderService(SuhaylConfig config, Logger logger) {
+ this.config = config;
+ this.logger = logger;
+ this.openMenus = new HashMap<>();
+ }
+
+ public void openMenuFor(Player player, UUID traderId) {
+ WanderingTraderMenu menu = new WanderingTraderMenu(
+ this,
+ player,
+ traderId
+ );
+
+ openMenus.put(player.getUniqueId(), menu);
+
+ menu.open();
+ }
+
+ public Optional<WanderingTraderMenu> getMenuFor(Player player) {
+ UUID key = player.getUniqueId();
+
+ if (openMenus.containsKey(key)) {
+ return Optional.of(openMenus.get(key));
+ }
+
+ return Optional.empty();
+ }
+
+ public void removeMenuFor(Player player) {
+ openMenus.remove(player.getUniqueId());
+ }
+
+ public void askToLeave(@NotNull Player requester, UUID traderId) {
+ World world = requester.getWorld();
+ Entity entity = world.getEntity(traderId);
+ if (!(entity instanceof WanderingTrader trader)) {
+ logger.info("Potential plugin issue - askToLeave called on non wandering trader");
+ return;
+ }
+
+ sendMessageToPlayer(requester, "left");
+
+ // Brief particles and invisibility before removal
+ // That allows to render the disapproval of the trader of the request
+ trader.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 40, 1, true, false, false));
+
+ removeLeashedTraderLlamas(trader);
+ trader.remove();
+
+ logger.info("Wandering trader removed.");
+ }
+
+ public void banish(Player requester, UUID traderId) {
+ askToLeave(requester, traderId);
+
+ long banTime = (long) (this.config.commandmentStickBanTime * 60_000);
+ banishUntil = System.currentTimeMillis() + banTime;
+
+ sendMessageToPlayer(requester, "ban");
+ }
+
+ public void toggleSilence(Player requester, UUID traderId) {
+ World world = requester.getWorld();
+ Entity entity = world.getEntity(traderId);
+ if (!(entity instanceof WanderingTrader trader)) {
+ logger.info("Potential plugin issue - toggleSilence called on non wandering trader");
+ return;
+ }
+
+ if (trader.isSilent()) {
+ trader.setSilent(false);
+ sendMessageToPlayer(requester, "unsilenced");
+ } else {
+ // Shhh!
+ trader.setSilent(true);
+ sendMessageToPlayer(requester, "silenced");
+ }
+ }
+
+ private void sendMessageToPlayer(Player player, String messageKey) {
+ Locale locale = player.locale();
+ String fullKey = "wandering_trader_menu.actions." + messageKey;
+
+ String message = SuhaylMessages.get(fullKey, locale);
+ player.sendMessage(message);
+ }
+
+ private void removeLeashedTraderLlamas(WanderingTrader trader) {
+ trader
+ .getWorld()
+ .getNearbyEntities(trader.getLocation(), 16, 16, 16)
+ .forEach(this::tryToRemoveLlama);
+ }
+
+ private void tryToRemoveLlama(Entity entity) {
+ if (!(entity instanceof TraderLlama llama)) {
+ return;
+ }
+
+ if (isUnderTraderControl(llama)) {
+ llama.remove();
+ }
+ }
+
+ private boolean isUnderTraderControl(TraderLlama llama) {
+ return llama.isLeashed() && llama.getLeashHolder() instanceof WanderingTrader;
+ }
+
+ public boolean canTradersVisit() {
+ return System.currentTimeMillis() > banishUntil;
+ }
+
+
+}
diff --git a/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/utils/ResourceLoader.java b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/utils/ResourceLoader.java
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/java/org/eu/loupsgris/quilvaryn/utils/ResourceLoader.java
@@ -0,0 +1,11 @@
+package org.eu.loupsgris.quilvaryn.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+@FunctionalInterface
+public interface ResourceLoader {
+
+ InputStream open(String path) throws IOException;
+
+}
diff --git a/plugins/suhayl/src/main/resources/config.yml b/plugins/suhayl/src/main/resources/config.yml
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/resources/config.yml
@@ -0,0 +1,6 @@
+happyGhastSpeedBoost: 2.4
+
+rainRate: 0.7
+
+commandmentStick:
+ banTime: 120
diff --git a/plugins/suhayl/src/main/resources/l10n/messages.properties b/plugins/suhayl/src/main/resources/l10n/messages.properties
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/resources/l10n/messages.properties
@@ -0,0 +1,13 @@
+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.
diff --git a/plugins/suhayl/src/main/resources/l10n/messages_en.properties b/plugins/suhayl/src/main/resources/l10n/messages_en.properties
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/resources/l10n/messages_en.properties
@@ -0,0 +1,13 @@
+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.
diff --git a/plugins/suhayl/src/main/resources/l10n/messages_fr.properties b/plugins/suhayl/src/main/resources/l10n/messages_fr.properties
new file mode 100644
--- /dev/null
+++ b/plugins/suhayl/src/main/resources/l10n/messages_fr.properties
@@ -0,0 +1,13 @@
+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.
diff --git a/plugins/suhayl/src/main/resources/plugin.yml b/plugins/suhayl/src/main/resources/plugin.yml
--- a/plugins/suhayl/src/main/resources/plugin.yml
+++ b/plugins/suhayl/src/main/resources/plugin.yml
@@ -1,4 +1,4 @@
-name: Suhayl
+name: suhayl
version: 0.1.0
main: org.eu.loupsgris.quilvaryn.SuhaylPlugin
api-version: 1.20
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Sep 11, 14:11 (17 h, 18 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2977522
Default Alt Text
D3647.diff (28 KB)
Attached To
Mode
D3647: Add commandment stick
Attached
Detach File
Event Timeline
Log In to Comment