Page MenuHomeDevCentral

D3647.diff
No OneTemporary

D3647.diff

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

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)

Event Timeline