Add multi-language and component message support (Requires Spigot)

Message configs are now selected based on the client's language (can be
 toggled in the config) and will use MineDown formatting to allow
 display of component messages as well as usage of RGB colors in 1.16.
If found the legacy local.yml will be used instead of the per-language
 files. Move your local.yml to the correct lang config to if you want to
 use the per-client language option.
Version was also changed to 3.11 due to the many internal changes that
 have accumulated over time
This commit is contained in:
Phoenix616 2020-06-28 18:00:09 +01:00
parent cbd427f561
commit 6ee7c4759a
No known key found for this signature in database
GPG Key ID: 40E2321E71738EB0
23 changed files with 391 additions and 172 deletions

36
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>com.acrobot.chestshop</groupId>
<artifactId>chestshop</artifactId>
<version>3.10.2-SNAPSHOT</version>
<version>3.11-SNAPSHOT</version>
<description>Chest-and-sign shop plugin for Bukkit</description>
<name>ChestShop</name>
@ -70,6 +70,20 @@
<scope>compile</scope>
</dependency>
<dependency>
<groupId>de.themoep.utils</groupId>
<artifactId>lang-bukkit</artifactId>
<version>1.2-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>de.themoep</groupId>
<artifactId>minedown</artifactId>
<version>1.6.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<!-- Should be kept in sync with Mojang -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
@ -348,6 +362,8 @@
<configuration>
<artifactSet>
<includes>
<include>de.themoep:*</include>
<include>de.themoep.utils:*</include>
<include>org.bstats:*</include>
<include>net.gravitydevelopment.updater</include>
<include>com.j256.ormlite</include>
@ -356,6 +372,14 @@
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>de.themoep.utils.lang</pattern>
<shadedPattern>com.Acrobot.ChestShop.Lang</shadedPattern>
</relocation>
<relocation>
<pattern>de.themoep.minedown</pattern>
<shadedPattern>com.Acrobot.ChestShop.MineDown</shadedPattern>
</relocation>
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>com.Acrobot.ChestShop.Metrics.BStats</shadedPattern>
@ -406,7 +430,7 @@
<id>default</id>
<activation>
<property>
<name>!bukkit</name>
<name>!spigot</name>
</property>
</activation>
<repositories>
@ -426,7 +450,7 @@
</profile>
<profile>
<id>bukkit</id>
<id>spigot</id>
<repositories>
<repository>
<id>spigotmc-repo</id>
@ -435,8 +459,8 @@
</repositories>
<dependencies>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -445,7 +469,7 @@
<bukkit>true</bukkit>
</properties>
<build>
<finalName>${project.name}-Bukkit</finalName>
<finalName>${project.name}-Spigot</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>

View File

@ -2,14 +2,17 @@ package com.Acrobot.Breeze.Utils;
import com.Acrobot.Breeze.Collection.SimpleCache;
import com.Acrobot.ChestShop.ChestShop;
import com.Acrobot.ChestShop.Configuration.Messages;
import com.Acrobot.ChestShop.Configuration.Properties;
import com.Acrobot.ChestShop.Events.ItemParseEvent;
import com.Acrobot.ChestShop.Events.MaterialParseEvent;
import com.google.common.collect.ImmutableMap;
import de.themoep.ShowItem.api.ShowItem;
import de.themoep.minedown.Replacer;
import info.somethingodd.OddItem.OddItem;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConstructor;
import org.bukkit.configuration.file.YamlRepresenter;
@ -25,6 +28,7 @@ import org.yaml.snakeyaml.nodes.Tag;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -520,7 +524,7 @@ public class MaterialUtil {
* @param message The raw message
* @param stock The items in stock
*/
public static boolean sendMessage(Player player, String message, ItemStack[] stock) {
public static boolean sendMessage(Player player, Messages.Message message, ItemStack[] stock, Map<String, String> replacementMap, String... replacements) {
if (showItem == null) {
return false;
}
@ -537,6 +541,15 @@ public class MaterialUtil {
String joinedItemJson = itemJson.stream().collect(Collectors.joining("," + new JSONObject(ImmutableMap.of("text", " ")).toJSONString() + ", "));
Map<String, String> newMap = new LinkedHashMap<>(replacementMap);
newMap.put("material", "item");
BaseComponent[] components = message.getComponents(player, true, newMap, replacements);
player.spigot().sendMessage(new Replacer()
.placeholderSuffix("")
.replace("item", ComponentSerializer.parse("[" + joinedItemJson + "]"))
.replaceIn(components));
/*
String prevColor = "";
List<String> parts = new ArrayList<>();
for (String s : message.split("%item")) {
@ -554,7 +567,7 @@ public class MaterialUtil {
}
showItem.tellRaw(player, messageJsonString);
return true;
*/return true;
}
}
}

View File

@ -167,11 +167,12 @@ public class ChestShop extends JavaPlugin {
public void loadConfig() {
Configuration.pairFileAndClass(loadFile("config.yml"), Properties.class, getBukkitLogger());
Configuration.pairFileAndClass(loadFile("local.yml"), Messages.class, getBukkitLogger());
Messages.load();
NameManager.load();
commands.forEach(c -> c.setPermissionMessage(Messages.prefix(Messages.ACCESS_DENIED)));
commands.forEach(c -> c.setPermissionMessage(Messages.ACCESS_DENIED.getTextWithPrefix(null)));
}
private void turnOffDatabaseLogging() {
@ -517,6 +518,11 @@ public class ChestShop extends JavaPlugin {
Bukkit.getPluginManager().callEvent(event);
}
public static void sendBungeeMessage(String playerName, Messages.Message message, Map<String, String> replacementMap, String... replacements) {
// TODO: Component support for bungee messages?
sendBungeeMessage(playerName, message.getTextWithPrefix(null, replacementMap, replacements));
}
public static void sendBungeeMessage(String playerName, String message) {
if (Properties.BUNGEECORD_MESSAGES && !Bukkit.getOnlinePlayers().isEmpty()) {
ByteArrayDataOutput out = ByteStreams.newDataOutput();

View File

@ -26,9 +26,9 @@ public class AccessToggle implements CommandExecutor {
Player player = (Player) sender;
if (setIgnoring(player, !isIgnoring(player))) {
player.sendMessage(Messages.prefix(Messages.TOGGLE_ACCESS_OFF));
Messages.TOGGLE_ACCESS_OFF.sendWithPrefix(player);
} else {
player.sendMessage(Messages.prefix(Messages.TOGGLE_ACCESS_ON));
Messages.TOGGLE_ACCESS_ON.sendWithPrefix(player);
}
return true;

View File

@ -58,23 +58,21 @@ public class Give implements CommandExecutor {
}
if (receiver == null) {
sender.sendMessage(Messages.prefix(Messages.PLAYER_NOT_FOUND));
Messages.PLAYER_NOT_FOUND.sendWithPrefix(sender);
return true;
}
ItemStack item = getItem(args, disregardedIndexes);
if (MaterialUtil.isEmpty(item)) {
sender.sendMessage(Messages.prefix(Messages.INCORRECT_ITEM_ID));
Messages.INCORRECT_ITEM_ID.sendWithPrefix(sender);
return true;
}
item.setAmount(quantity);
InventoryUtil.add(item, receiver.getInventory());
sender.sendMessage(Messages.prefix(Messages.ITEM_GIVEN
.replace("%item", MaterialUtil.getName(item))
.replace("%player", receiver.getName())));
Messages.ITEM_GIVEN.send(sender, "item", MaterialUtil.getName(item), "player", receiver.getName());
return true;
}

View File

@ -44,9 +44,9 @@ public class ItemInfo implements CommandExecutor {
return false;
}
sender.sendMessage(replace(iteminfo));
iteminfo.send(sender);
try {
sender.sendMessage(replace(iteminfo_fullname, "item", MaterialUtil.getName(item)));
iteminfo_fullname.send(sender, "item", MaterialUtil.getName(item));
} catch (IllegalArgumentException e) {
sender.sendMessage(ChatColor.RED + "Error while generating full name. Please contact an admin or take a look at the console/log!");
ChestShop.getPlugin().getLogger().log(Level.SEVERE, "Error while generating full item name", e);
@ -54,7 +54,7 @@ public class ItemInfo implements CommandExecutor {
}
try {
sender.sendMessage(replace(iteminfo_shopname, "item", MaterialUtil.getSignName(item)));
iteminfo_shopname.send(sender, "item", MaterialUtil.getSignName(item));
} catch (IllegalArgumentException e) {
sender.sendMessage(ChatColor.RED + "Error while generating shop sign name. Please contact an admin or take a look at the console/log!");
ChestShop.getPlugin().getLogger().log(Level.SEVERE, "Error while generating shop sign item name", e);

View File

@ -12,7 +12,7 @@ import org.bukkit.command.CommandSender;
*/
public class Metrics implements CommandExecutor {
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
sender.sendMessage(Messages.replace(Messages.METRICS,
Messages.METRICS.send(sender,
"accounts", String.valueOf(NameManager.getAccountCount()),
"totalTransactions", String.valueOf(MetricsModule.getTotalTransactions()),
"buyTransactions", String.valueOf(MetricsModule.getBuyTransactions()),
@ -20,7 +20,7 @@ public class Metrics implements CommandExecutor {
"totalItems", String.valueOf(MetricsModule.getTotalItemsCount()),
"boughtItems", String.valueOf(MetricsModule.getBoughtItemsCount()),
"soldItems", String.valueOf(MetricsModule.getSoldItemsCount())
));
);
return true;
}
}

View File

@ -32,9 +32,9 @@ public class Toggle implements CommandExecutor {
}
if (setIgnoring(player, !isIgnoring(player))) {
player.sendMessage(Messages.prefix(Messages.TOGGLE_MESSAGES_OFF));
Messages.TOGGLE_MESSAGES_OFF.sendWithPrefix(player);
} else {
player.sendMessage(Messages.prefix(Messages.TOGGLE_MESSAGES_ON));
Messages.TOGGLE_MESSAGES_ON.sendWithPrefix(player);
}
return true;

View File

@ -1,116 +1,194 @@
package com.Acrobot.ChestShop.Configuration;
import com.Acrobot.Breeze.Configuration.Annotations.PrecededBySpace;
import com.Acrobot.Breeze.Configuration.Configuration;
import com.Acrobot.ChestShop.ChestShop;
import de.themoep.minedown.MineDown;
import de.themoep.utils.lang.bukkit.BukkitLanguageConfig;
import de.themoep.utils.lang.bukkit.LanguageManager;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.command.CommandSender;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Map;
import java.util.logging.Level;
/**
* @author Acrobot
*/
public class Messages {
public static String prefix = "&a[Shop] &r";
public static String iteminfo = "&aItem Information: &r";
public static String iteminfo_fullname = "&fFull Name: &7%item";
public static String iteminfo_shopname = "&fShop Sign: &7%item";
public static String iteminfo_repaircost = "&fRepair Cost: &7%cost";
public static String iteminfo_book = "&fBook Title: &7%title\n&fBook Author: &7%author\n&fBook Pages: &7%pages";
public static String iteminfo_book_generatopm = "&fBook Generation: &7%generation";
public static String iteminfo_lore = "&fLore: \n&r%lore";
public static Message prefix;
public static Message iteminfo;
public static Message iteminfo_fullname;
public static Message iteminfo_shopname;
public static Message iteminfo_repaircost;
public static Message iteminfo_book;
public static Message iteminfo_book_generatopm;
public static Message iteminfo_lore;
@PrecededBySpace
public static String METRICS = "&a[Shop] &fMetrics:\n" +
"&fAccounts: &7%accounts\n" +
"&fAverage transactions: &7%totalTransactions &f(buy: &7%buyTransactions &fsell: &7%sellTransactions&f)\n" +
"&fAverage items traded: &7%totalItems &f(bought: &7%boughtItems &fsold: &7%soldItems&f)";
public static Message METRICS;
@PrecededBySpace
public static String ACCESS_DENIED = "You don't have permission to access that shop's storage container!";
public static String TRADE_DENIED = "You don't have permission to trade with that shop!";
public static Message ACCESS_DENIED;
public static Message TRADE_DENIED;
@PrecededBySpace
public static String NOT_ENOUGH_MONEY = "You don't have enough money!";
public static String NOT_ENOUGH_MONEY_SHOP = "Shop owner doesn't have enough money!";
public static Message NOT_ENOUGH_MONEY;
public static Message NOT_ENOUGH_MONEY_SHOP;
@PrecededBySpace
public static String CLIENT_DEPOSIT_FAILED = "Money deposit to your account failed!";
public static String SHOP_DEPOSIT_FAILED = "Money deposit to shop owner failed!";
public static String NO_ECONOMY_ACCOUNT = "Economy account from shop owner doesn't exist!";
public static Message CLIENT_DEPOSIT_FAILED;
public static Message SHOP_DEPOSIT_FAILED;
public static Message NO_ECONOMY_ACCOUNT;
@PrecededBySpace
public static String NO_BUYING_HERE = "You can't buy here!";
public static String NO_SELLING_HERE = "You can't sell here!";
public static Message NO_BUYING_HERE;
public static Message NO_SELLING_HERE;
@PrecededBySpace
public static String NOT_ENOUGH_SPACE_IN_INVENTORY = "You haven't got enough space in inventory!";
public static String NOT_ENOUGH_SPACE_IN_CHEST = "There isn't enough space in chest!";
public static String NOT_ENOUGH_ITEMS_TO_SELL = "You don't have enough items to sell!";
public static String NOT_ENOUGH_SPACE_IN_YOUR_SHOP = "%price %item&7 shop at &r%world/%x/%y/%z&7 is full! (%seller tried to sell)";
public static Message NOT_ENOUGH_SPACE_IN_INVENTORY;
public static Message NOT_ENOUGH_SPACE_IN_CHEST;
public static Message NOT_ENOUGH_ITEMS_TO_SELL;
public static Message NOT_ENOUGH_SPACE_IN_YOUR_SHOP;
@PrecededBySpace
public static String NOT_ENOUGH_STOCK = "This shop is out of stock.";
public static String NOT_ENOUGH_STOCK_IN_YOUR_SHOP = "%price %item&7 shop at &r%world/%x/%y/%z&7 is out of stock! (%buyer tried to buy)";
public static Message NOT_ENOUGH_STOCK;
public static Message NOT_ENOUGH_STOCK_IN_YOUR_SHOP;
@PrecededBySpace
public static String YOU_BOUGHT_FROM_SHOP = "You bought %item from %owner for %price.";
public static String SOMEBODY_BOUGHT_FROM_YOUR_SHOP = "%buyer bought %item for %price from your shop at %world/%x/%y/%z.";
public static Message YOU_BOUGHT_FROM_SHOP;
public static Message SOMEBODY_BOUGHT_FROM_YOUR_SHOP;
@PrecededBySpace
public static String YOU_SOLD_TO_SHOP = "You sold %item to %buyer for %price.";
public static String SOMEBODY_SOLD_TO_YOUR_SHOP = "%seller sold %item for %price to your shop at %world/%x/%y/%z.";
public static Message YOU_SOLD_TO_SHOP;
public static Message SOMEBODY_SOLD_TO_YOUR_SHOP;
@PrecededBySpace
public static String YOU_CANNOT_CREATE_SHOP = "You can't create this type of shop!";
public static String NO_CHEST_DETECTED = "Couldn't find a chest!";
public static String INVALID_SHOP_DETECTED = "The shop cannot be used!";
public static String INVALID_SHOP_PRICE = "The shop has an invalid price!";
public static String INVALID_SHOP_QUANTITY = "The shop has an invalid quantity!";
public static String CANNOT_ACCESS_THE_CHEST = "You don't have permissions to access this chest!";
public static Message YOU_CANNOT_CREATE_SHOP;
public static Message NO_CHEST_DETECTED;
public static Message INVALID_SHOP_DETECTED;
public static Message INVALID_SHOP_PRICE;
public static Message INVALID_SHOP_QUANTITY;
public static Message CANNOT_ACCESS_THE_CHEST;
@PrecededBySpace
public static String SELL_PRICE_ABOVE_MAX = "Sell price is above maximum!";
public static String SELL_PRICE_BELOW_MIN ="Sell price is below minimum!";
public static String BUY_PRICE_ABOVE_MAX = "Buy price is above maximum!";
public static String BUY_PRICE_BELOW_MIN ="Buy price is below minimum!";
public static Message SELL_PRICE_ABOVE_MAX;
public static Message SELL_PRICE_BELOW_MIN;
public static Message BUY_PRICE_ABOVE_MAX;
public static Message BUY_PRICE_BELOW_MIN;
@PrecededBySpace
public static String CLICK_TO_AUTOFILL_ITEM = "Click the sign with the item that this shop is for!";
public static String NO_ITEM_IN_HAND = "You don't have an item in your hand to autofill!";
public static Message CLICK_TO_AUTOFILL_ITEM;
public static Message NO_ITEM_IN_HAND;
@PrecededBySpace
public static String PROTECTED_SHOP = "Successfully protected the shop with LWC!";
public static String PROTECTED_SHOP_SIGN = "Successfully protected the shop sign with LWC!";
public static String SHOP_CREATED = "Shop successfully created!";
public static String SHOP_FEE_PAID = "You have been charged %amount";
public static String SHOP_REFUNDED = "You have been refunded %amount.";
public static String ITEM_GIVEN = "Given %item to %player.";
public static Message PROTECTED_SHOP;
public static Message PROTECTED_SHOP_SIGN;
public static Message SHOP_CREATED;
public static Message SHOP_FEE_PAID;
public static Message SHOP_REFUNDED;
public static Message ITEM_GIVEN;
@PrecededBySpace
public static String RESTRICTED_SIGN_CREATED = "Sign successfully created!";
public static Message RESTRICTED_SIGN_CREATED;
@PrecededBySpace
public static String PLAYER_NOT_FOUND = "Player not found!";
public static String NO_PERMISSION = "You don't have permissions to do that!";
public static String INCORRECT_ITEM_ID = "You have specified an invalid item id!";
public static String NOT_ENOUGH_PROTECTIONS = "Could not create a protection!";
public static Message PLAYER_NOT_FOUND;
public static Message NO_PERMISSION;
public static Message INCORRECT_ITEM_ID;
public static Message NOT_ENOUGH_PROTECTIONS;
@PrecededBySpace
public static String CANNOT_CREATE_SHOP_HERE = "You can't create shop here!";
public static Message CANNOT_CREATE_SHOP_HERE;
@PrecededBySpace
public static String TOGGLE_MESSAGES_OFF = "You will no longer receive messages from your shop(s).";
public static String TOGGLE_MESSAGES_ON = "You will now receive messages from your shop(s).";
public static Message TOGGLE_MESSAGES_OFF;
public static Message TOGGLE_MESSAGES_ON;
@PrecededBySpace
public static String TOGGLE_ACCESS_ON = "You can no longer trade at shops that you have access to";
public static String TOGGLE_ACCESS_OFF = "You can now trade at shops that you have access to";
public static Message TOGGLE_ACCESS_ON;
public static Message TOGGLE_ACCESS_OFF;
@Deprecated
public static String prefix(String message) {
return Configuration.getColoured(prefix + message);
return Configuration.getColoured(prefix.getLang(null) + message);
}
@Deprecated
public static String replace(String message, String... replacements) {
for (int i = 0; i + 1 < replacements.length; i+=2) {
message = message.replace("%" + replacements[i], replacements[i+1]);
}
return Configuration.getColoured(message);
}
private static LanguageManager manager;
public static void load() {
for (Field field : Messages.class.getFields()) {
if (!Modifier.isStatic(field.getModifiers())) {
continue;
}
try {
field.set(null, new Message(field.getName()));
} catch (IllegalAccessException e) {
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while setting Message " + field.getName() + "!", e);
}
}
manager = new LanguageManager(ChestShop.getPlugin(), Properties.DEFAULT_LANGUAGE);
// Legacy locale.yml file
File legacyFile = new File(ChestShop.getPlugin().getDataFolder(), "local.yml");
if (legacyFile.exists()) {
ChestShop.getBukkitLogger().log(Level.INFO, "Found legacy local.yml. Loading it as 'legacy' language and using that for all messages.");
ChestShop.getBukkitLogger().log(Level.INFO, "As long as the legacy file is used automatic language switching based on the client settings will not be supported!");
ChestShop.getBukkitLogger().log(Level.INFO, "Import it into the corresponding language file and remove/rename the file if you don't want it anymore!");
manager.addConfig(new BukkitLanguageConfig(ChestShop.getPlugin(), "", legacyFile, "legacy", false));
Properties.DEFAULT_LANGUAGE = "legacy";
Properties.USE_CLIENT_LOCALE = false;
}
if (!Properties.USE_CLIENT_LOCALE) {
manager.setProvider(sender -> null);
}
}
public static class Message {
private String key;
public Message(String key) {
this.key = key;
}
public void sendWithPrefix(CommandSender sender, Map<String, String> replacementMap, String... replacements) {
sender.spigot().sendMessage(getComponents(sender, true, replacementMap, replacements));
}
public void sendWithPrefix(CommandSender sender, Map<String, String> replacements) {
sender.spigot().sendMessage(getComponents(sender, true, replacements));
}
public void sendWithPrefix(CommandSender sender, String... replacements) {
sender.spigot().sendMessage(getComponents(sender, true, Collections.emptyMap(), replacements));
}
public void send(CommandSender sender, String... replacements) {
sender.spigot().sendMessage(getComponents(sender, false, Collections.emptyMap(), replacements));
}
public BaseComponent[] getComponents(CommandSender sender, boolean prefixSuffix, Map<String, String> replacementMap, String... replacements) {
MineDown mineDown = new MineDown("%prefix" + getLang(sender));
mineDown.placeholderSuffix("");
mineDown.replace("prefix", prefixSuffix ? prefix.getLang(sender) : "");
mineDown.replace(replacementMap);
mineDown.replace(replacements);
return mineDown.toComponent();
}
private String getLang(CommandSender sender) {
return manager.getConfig(sender).get(key);
}
public String getTextWithPrefix(CommandSender sender, Map<String, String> replacementMap, String... replacements) {
return TextComponent.toLegacyText(getComponents(sender, true, replacementMap, replacements));
}
public String getTextWithPrefix(CommandSender sender, String... replacements) {
return getTextWithPrefix(sender, Collections.emptyMap(), replacements);
}
public String getTextWithPrefix(CommandSender sender, Map<String, String> replacements) {
return getTextWithPrefix(sender, replacements, new String[0]);
}
public String getKey() {
return key;
}
}
}

View File

@ -112,6 +112,13 @@ public class Properties {
@ConfigurationComment("How large should the internal caches be?")
public static int CACHE_SIZE = 1000;
@PrecededBySpace
@ConfigurationComment("The default language when the client's language can't be found.")
public static String DEFAULT_LANGUAGE = "en";
@ConfigurationComment("Should the plugin try to use a language file that matches the client's locale setting?")
public static boolean USE_CLIENT_LOCALE = true;
@PrecededBySpace
@ConfigurationComment("What containers are allowed to hold a shop? (Only blocks with inventories work!)")
@Parser("MaterialSet")

View File

@ -37,14 +37,14 @@ public class BlockPlace implements Listener {
}
if (!Security.canAccess(player, placed)) {
event.getPlayer().sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
Messages.ACCESS_DENIED.sendWithPrefix(event.getPlayer());
event.setCancelled(true);
}
Block neighbor = uBlock.findNeighbor(placed);
if (neighbor != null && !Security.canAccess(event.getPlayer(), neighbor)) {
event.getPlayer().sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
Messages.ACCESS_DENIED.sendWithPrefix(event.getPlayer());
event.setCancelled(true);
}
@ -88,7 +88,7 @@ public class BlockPlace implements Listener {
}
if (!Security.canAccess(event.getPlayer(), relative)) {
event.getPlayer().sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
Messages.ACCESS_DENIED.sendWithPrefix(event.getPlayer());
event.setCancelled(true);
return;
}

View File

@ -37,7 +37,7 @@ public class ItemInfoListener implements Listener {
public static void addRepairCost(ItemInfoEvent event) {
ItemMeta meta = event.getItem().getItemMeta();
if (meta instanceof Repairable && ((Repairable) meta).getRepairCost() > 0) {
event.getSender().sendMessage(replace(iteminfo_repaircost, "cost", String.valueOf(((Repairable) meta).getRepairCost())));
iteminfo_repaircost.send(event.getSender(), "cost", String.valueOf(((Repairable) meta).getRepairCost()));
}
}
@ -104,15 +104,15 @@ public class ItemInfoListener implements Listener {
ItemMeta meta = event.getItem().getItemMeta();
if (meta instanceof BookMeta) {
BookMeta book = (BookMeta) meta;
event.getSender().sendMessage(replace(iteminfo_book,
iteminfo_book.send(event.getSender(),
"title", book.getTitle(),
"author", book.getAuthor(),
"pages", String.valueOf(book.getPageCount())
));
);
if (book.hasGeneration()) {
event.getSender().sendMessage(replace(iteminfo_book_generatopm,
iteminfo_book_generatopm.send(event.getSender(),
"generation", StringUtil.capitalizeFirstLetter(book.getGeneration().name(), '_')
));
);
}
}
}
@ -121,7 +121,7 @@ public class ItemInfoListener implements Listener {
public static void addLoreInfo(ItemInfoEvent event) {
ItemMeta meta = event.getItem().getItemMeta();
if (meta.hasLore()) {
event.getSender().sendMessage(replace(iteminfo_lore, "lore", String.join("\n", meta.getLore())));
iteminfo_lore.send(event.getSender(), "lore", String.join("\n", meta.getLore()));
}
}
}

View File

@ -66,7 +66,7 @@ public class PlayerInteract implements Listener {
}
if (!Security.canAccess(player, block)) {
player.sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
Messages.ACCESS_DENIED.sendWithPrefix(player);
event.setCancelled(true);
}
@ -105,10 +105,10 @@ public class PlayerInteract implements Listener {
sign.update();
}
} else {
player.sendMessage(Messages.prefix(Messages.NO_ITEM_IN_HAND));
Messages.NO_ITEM_IN_HAND.sendWithPrefix(player);
}
} else {
player.sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
Messages.ACCESS_DENIED.sendWithPrefix(player);
}
return;
}
@ -136,7 +136,7 @@ public class PlayerInteract implements Listener {
}
if (Properties.CHECK_ACCESS_FOR_SHOP_USE && !Security.canAccess(player, block, true)) {
player.sendMessage(Messages.prefix(Messages.TRADE_DENIED));
Messages.TRADE_DENIED.sendWithPrefix(player);
return;
}
@ -163,7 +163,7 @@ public class PlayerInteract implements Listener {
Bukkit.getPluginManager().callEvent(accountQueryEvent);
Account account = accountQueryEvent.getAccount();
if (account == null) {
player.sendMessage(Messages.prefix(Messages.PLAYER_NOT_FOUND));
Messages.PLAYER_NOT_FOUND.sendWithPrefix(player);
return null;
}
@ -174,7 +174,7 @@ public class PlayerInteract implements Listener {
AccountCheckEvent event = new AccountCheckEvent(account.getUuid(), player.getWorld());
Bukkit.getPluginManager().callEvent(event);
if(!event.hasAccount()) {
player.sendMessage(Messages.prefix(Messages.NO_ECONOMY_ACCOUNT));
Messages.NO_ECONOMY_ACCOUNT.sendWithPrefix(player);
return null;
}
}
@ -189,7 +189,7 @@ public class PlayerInteract implements Listener {
Bukkit.getPluginManager().callEvent(parseEvent);
ItemStack item = parseEvent.getItem();
if (item == null) {
player.sendMessage(Messages.prefix(Messages.INVALID_SHOP_DETECTED));
Messages.INVALID_SHOP_DETECTED.sendWithPrefix(player);
return null;
}
@ -199,7 +199,7 @@ public class PlayerInteract implements Listener {
} catch (NumberFormatException notANumber) {}
if (amount < 1 || amount > Properties.MAX_SHOP_AMOUNT) {
player.sendMessage(Messages.prefix(Messages.INVALID_SHOP_PRICE));
Messages.INVALID_SHOP_PRICE.sendWithPrefix(player);
return null;
}
@ -270,7 +270,7 @@ public class PlayerInteract implements Listener {
Container container = uBlock.findConnectedContainer(sign);
if (container == null) {
player.sendMessage(Messages.prefix(Messages.NO_CHEST_DETECTED));
Messages.NO_CHEST_DETECTED.sendWithPrefix(player);
return;
}

View File

@ -46,7 +46,7 @@ public class PlayerInventory implements Listener {
}
if (!Security.canAccess(player, container)) {
player.sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
Messages.ACCESS_DENIED.sendWithPrefix(player);
event.setCancelled(true);
}
}

View File

@ -13,6 +13,6 @@ public class MessageSender implements Listener {
@EventHandler(priority = EventPriority.MONITOR)
public static void onShopCreation(ShopCreatedEvent event) {
event.getPlayer().sendMessage(Messages.prefix(Messages.SHOP_CREATED));
Messages.SHOP_CREATED.sendWithPrefix(event.getPlayer());
}
}

View File

@ -14,6 +14,9 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author Acrobot
*/
@ -53,26 +56,28 @@ public class TransactionMessageSender implements Listener {
}
}
private static void sendMessage(Player player, String playerName, String rawMessage, TransactionEvent event, String... replacements) {
private static void sendMessage(Player player, String playerName, Messages.Message rawMessage, TransactionEvent event, String... replacements) {
Location loc = event.getSign().getLocation();
String message = Messages.prefix(rawMessage)
.replace("%price", Economy.formatBalance(event.getExactPrice()))
.replace("%world", loc.getWorld().getName())
.replace("%x", String.valueOf(loc.getBlockX()))
.replace("%y", String.valueOf(loc.getBlockY()))
.replace("%z", String.valueOf(loc.getBlockZ()));
Map<String, String> replacementMap = new LinkedHashMap<>();
replacementMap.put("price", Economy.formatBalance(event.getExactPrice()));
replacementMap.put("world", loc.getWorld().getName());
replacementMap.put("x", String.valueOf(loc.getBlockX()));
replacementMap.put("y", String.valueOf(loc.getBlockY()));
replacementMap.put("z", String.valueOf(loc.getBlockZ()));
for (int i = 0; i + 1 < replacements.length; i+=2) {
message = message.replace("%" + replacements[i], replacements[i + 1]);
replacementMap.put(replacements[i], replacements[i + 1]);
}
if (player != null) {
if (Properties.SHOWITEM_MESSAGE && MaterialUtil.Show.sendMessage(player, message, event.getStock())) {
if (Properties.SHOWITEM_MESSAGE && MaterialUtil.Show.sendMessage(player, rawMessage, event.getStock(), replacementMap)) {
return;
}
player.sendMessage(message.replace("%item", MaterialUtil.getItemList(event.getStock())));
replacementMap.put("item", MaterialUtil.getItemList(event.getStock()));
rawMessage.sendWithPrefix(player, replacementMap);
} else if (playerName != null) {
ChestShop.sendBungeeMessage(playerName, message.replace("%item", MaterialUtil.getItemList(event.getStock())));
replacementMap.put("item", MaterialUtil.getItemList(event.getStock()));
ChestShop.sendBungeeMessage(playerName, rawMessage, replacementMap);
}
}

View File

@ -60,6 +60,6 @@ public class CreationFeeGetter implements Listener {
ChestShop.callEvent(currencyAddEvent);
}
player.sendMessage(Messages.prefix(Messages.SHOP_FEE_PAID.replace("%amount", Economy.formatBalance(shopCreationPrice))));
Messages.SHOP_FEE_PAID.sendWithPrefix(player, "amount", Economy.formatBalance(shopCreationPrice));
}
}

View File

@ -17,7 +17,7 @@ public class ErrorMessageSender implements Listener {
return;
}
String message = null;
Messages.Message message = null;
switch (event.getOutcome()) {
case UNKNOWN_PLAYER:
@ -70,7 +70,7 @@ public class ErrorMessageSender implements Listener {
}
if (message != null) {
event.getPlayer().sendMessage(Messages.prefix(message));
message.sendWithPrefix(event.getPlayer());
}
}
}

View File

@ -9,6 +9,7 @@ import com.Acrobot.ChestShop.Database.Account;
import com.Acrobot.ChestShop.Economy.Economy;
import com.Acrobot.ChestShop.Events.PreTransactionEvent;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Table;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@ -19,6 +20,9 @@ import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import static com.Acrobot.ChestShop.Configuration.Messages.CLIENT_DEPOSIT_FAILED;
@ -45,7 +49,7 @@ public class ErrorMessageSender implements Listener {
return;
}
String message = null;
Messages.Message message = null;
switch (event.getTransactionOutcome()) {
case SHOP_DOES_NOT_BUY_THIS_ITEM:
@ -66,14 +70,14 @@ public class ErrorMessageSender implements Listener {
case NOT_ENOUGH_SPACE_IN_CHEST:
if (Properties.SHOW_MESSAGE_FULL_SHOP && !Properties.CSTOGGLE_TOGGLES_FULL_SHOP || !Toggle.isIgnoring(event.getOwnerAccount().getUuid())) {
Location loc = event.getSign().getLocation();
String messageNotEnoughSpace = Messages.prefix(NOT_ENOUGH_SPACE_IN_YOUR_SHOP)
.replace("%price", Economy.formatBalance(event.getExactPrice()))
.replace("%seller", event.getClient().getName())
.replace("%world", loc.getWorld().getName())
.replace("%x", String.valueOf(loc.getBlockX()))
.replace("%y", String.valueOf(loc.getBlockY()))
.replace("%z", String.valueOf(loc.getBlockZ()));
sendMessageToOwner(event.getOwnerAccount(), messageNotEnoughSpace, event.getStock());
sendMessageToOwner(event.getOwnerAccount(), NOT_ENOUGH_SPACE_IN_YOUR_SHOP, new String[]{
"price", Economy.formatBalance(event.getExactPrice()),
"seller", event.getClient().getName(),
"world", loc.getWorld().getName(),
"x", String.valueOf(loc.getBlockX()),
"y", String.valueOf(loc.getBlockY()),
"z", String.valueOf(loc.getBlockZ())
}, event.getStock());
}
message = Messages.NOT_ENOUGH_SPACE_IN_CHEST;
break;
@ -86,14 +90,14 @@ public class ErrorMessageSender implements Listener {
case NOT_ENOUGH_STOCK_IN_CHEST:
if (Properties.SHOW_MESSAGE_OUT_OF_STOCK && !Properties.CSTOGGLE_TOGGLES_OUT_OF_STOCK || !Toggle.isIgnoring(event.getOwnerAccount().getUuid())) {
Location loc = event.getSign().getLocation();
String messageOutOfStock = Messages.prefix(NOT_ENOUGH_STOCK_IN_YOUR_SHOP)
.replace("%price", Economy.formatBalance(event.getExactPrice()))
.replace("%buyer", event.getClient().getName())
.replace("%world", loc.getWorld().getName())
.replace("%x", String.valueOf(loc.getBlockX()))
.replace("%y", String.valueOf(loc.getBlockY()))
.replace("%z", String.valueOf(loc.getBlockZ()));
sendMessageToOwner(event.getOwnerAccount(), messageOutOfStock, event.getStock());
sendMessageToOwner(event.getOwnerAccount(), NOT_ENOUGH_STOCK_IN_YOUR_SHOP, new String[]{
"%price", Economy.formatBalance(event.getExactPrice()),
"%buyer", event.getClient().getName(),
"%world", loc.getWorld().getName(),
"%x", String.valueOf(loc.getBlockX()),
"%y", String.valueOf(loc.getBlockY()),
"%z", String.valueOf(loc.getBlockZ())
}, event.getStock());
}
message = Messages.NOT_ENOUGH_STOCK;
break;
@ -101,8 +105,7 @@ public class ErrorMessageSender implements Listener {
message = Messages.CLIENT_DEPOSIT_FAILED;
break;
case SHOP_DEPOSIT_FAILED:
String messageDepositFailed = Messages.prefix(CLIENT_DEPOSIT_FAILED);
sendMessageToOwner(event.getOwnerAccount(), messageDepositFailed);
sendMessageToOwner(event.getOwnerAccount(), CLIENT_DEPOSIT_FAILED, new String[0]);
message = Messages.SHOP_DEPOSIT_FAILED;
break;
case SHOP_IS_RESTRICTED:
@ -116,31 +119,34 @@ public class ErrorMessageSender implements Listener {
}
if (message != null) {
event.getClient().sendMessage(Messages.prefix(message));
message.sendWithPrefix(event.getClient());
}
}
private static void sendMessageToOwner(Account ownerAccount, String message, ItemStack... stock) {
private static void sendMessageToOwner(Account ownerAccount, Messages.Message message, String[] replacements, ItemStack... stock) {
Player player = Bukkit.getPlayer(ownerAccount.getUuid());
if (player != null || Properties.BUNGEECORD_MESSAGES) {
message = message.replace("%material", "%item");
String replacedMessage = message.replace("%item", MaterialUtil.getItemList(stock));
if (Properties.NOTIFICATION_MESSAGE_COOLDOWN > 0) {
Long last = notificationCooldowns.get(ownerAccount.getUuid(), replacedMessage);
String cacheKey = message.getKey() + "|" + String.join(",", replacements) + "|" + MaterialUtil.getItemList(stock);
Long last = notificationCooldowns.get(ownerAccount.getUuid(), cacheKey);
if (last != null && last + Properties.NOTIFICATION_MESSAGE_COOLDOWN * 1000 > System.currentTimeMillis()) {
return;
}
notificationCooldowns.put(ownerAccount.getUuid(), replacedMessage, System.currentTimeMillis());
notificationCooldowns.put(ownerAccount.getUuid(), cacheKey, System.currentTimeMillis());
}
if (player != null) {
if (Properties.SHOWITEM_MESSAGE && MaterialUtil.Show.sendMessage(player, message, stock)) {
if (Properties.SHOWITEM_MESSAGE && MaterialUtil.Show.sendMessage(player, message, stock, Collections.emptyMap(), replacements)) {
return;
}
player.sendMessage(replacedMessage);
String items = MaterialUtil.getItemList(stock);
message.sendWithPrefix(player,
ImmutableMap.of("material", items, "item", items), replacements);
} else {
ChestShop.sendBungeeMessage(ownerAccount.getName(), replacedMessage);
String items = MaterialUtil.getItemList(stock);
ChestShop.sendBungeeMessage(ownerAccount.getName(), message,
ImmutableMap.of("material", items, "item", items), replacements);
}
}
}

View File

@ -59,7 +59,6 @@ public class ShopRefundListener implements Listener {
ChestShop.callEvent(currencySubtractEvent);
}
String message = Messages.SHOP_REFUNDED.replace("%amount", Economy.formatBalance(refundPrice));
event.getDestroyer().sendMessage(Messages.prefix(message));
Messages.SHOP_REFUNDED.sendWithPrefix(event.getDestroyer(), "amount", Economy.formatBalance(refundPrice));
}
}

View File

@ -82,7 +82,7 @@ public class LightweightChestProtection implements Listener {
Sign sign = event.getSign();
Container connectedContainer = event.getContainer();
String message = null;
Messages.Message message = null;
if (Properties.PROTECT_SIGN_WITH_LWC) {
if (Security.protect(player, sign.getBlock(), event.getOwnerAccount() != null ? event.getOwnerAccount().getUuid() : player.getUniqueId(), Properties.LWC_SIGN_PROTECTION_TYPE)) {
message = Messages.PROTECTED_SHOP_SIGN;
@ -100,7 +100,7 @@ public class LightweightChestProtection implements Listener {
}
if (message != null) {
player.sendMessage(Messages.prefix(message));
message.sendWithPrefix(player);
}
}

View File

@ -45,7 +45,7 @@ public class RestrictedSign implements Listener {
if (isRestricted(lines)) {
if (!hasPermission(player, lines)) {
player.sendMessage(Messages.prefix(Messages.ACCESS_DENIED));
Messages.ACCESS_DENIED.sendWithPrefix(player);
dropSignAndCancelEvent(event);
return;
}
@ -63,7 +63,7 @@ public class RestrictedSign implements Listener {
return;
}
player.sendMessage(Messages.prefix(Messages.RESTRICTED_SIGN_CREATED));
Messages.RESTRICTED_SIGN_CREATED.sendWithPrefix(player);
}
}

View File

@ -0,0 +1,83 @@
prefix: "&a[Shop] &r"
iteminfo: "&aItem Information: &r"
iteminfo_fullname: "&fFull Name: &7%item"
iteminfo_shopname: "&fShop Sign: &7%item"
iteminfo_repaircost: "&fRepair Cost: &7%cost"
iteminfo_book: |-
&fBook Title: &7%title
&fBook Author: &7%author
&fBook Pages: &7%pages
iteminfo_book_generatopm: "&fBook Generation: &7%generation"
iteminfo_lore: |-
&fLore:
&r%lore
METRICS: |-
&a[Shop] &fMetrics:
&fAccounts: &7%accounts
&fAverage transactions: &7%totalTransactions &f(buy: &7%buyTransactions &fsell: &7%sellTransactions&f)
&fAverage items traded: &7%totalItems &f(bought: &7%boughtItems &fsold: &7%soldItems&f)
ACCESS_DENIED: "You don't have permission to access that shop's storage container!"
TRADE_DENIED: "You don't have permission to trade with that shop!"
NOT_ENOUGH_MONEY: "You don't have enough money!"
NOT_ENOUGH_MONEY_SHOP: "Shop owner doesn't have enough money!"
CLIENT_DEPOSIT_FAILED: "Money deposit to your account failed!"
SHOP_DEPOSIT_FAILED: "Money deposit to shop owner failed!"
NO_ECONOMY_ACCOUNT: "Economy account from shop owner doesn't exist!"
NO_BUYING_HERE: "You can't buy here!"
NO_SELLING_HERE: "You can't sell here!"
NOT_ENOUGH_SPACE_IN_INVENTORY: "You haven't got enough space in inventory!"
NOT_ENOUGH_SPACE_IN_CHEST: "There isn't enough space in chest!"
NOT_ENOUGH_ITEMS_TO_SELL: "You don't have enough items to sell!"
NOT_ENOUGH_SPACE_IN_YOUR_SHOP: "[%price %item&7 shop](At world: &f%world\nPosition: &f%x/%y/%z)&7 is full! (%seller tried to sell)"
NOT_ENOUGH_STOCK: "This shop is out of stock."
NOT_ENOUGH_STOCK_IN_YOUR_SHOP: "[%price %item&7 shop](At world: &f%world\nPosition: &f%x/%y/%z)&7 is out of stock! (%buyer tried to buy)"
YOU_BOUGHT_FROM_SHOP: "You bought %item from %owner for %price."
SOMEBODY_BOUGHT_FROM_YOUR_SHOP: "%buyer bought %item for %price from your shop at %world/%x/%y/%z."
YOU_SOLD_TO_SHOP: "You sold %item to %buyer for %price."
SOMEBODY_SOLD_TO_YOUR_SHOP: "%seller sold %item for %price to your shop at %world/%x/%y/%z."
YOU_CANNOT_CREATE_SHOP: "You can't create this type of shop!"
NO_CHEST_DETECTED: "Couldn't find a chest!"
INVALID_SHOP_DETECTED: "The shop cannot be used!"
INVALID_SHOP_PRICE: "The shop has an invalid price!"
INVALID_SHOP_QUANTITY: "The shop has an invalid quantity!"
CANNOT_ACCESS_THE_CHEST: "You don't have permissions to access this chest!"
SELL_PRICE_ABOVE_MAX: "Sell price is above maximum!"
SELL_PRICE_BELOW_MIN: "Sell price is below minimum!"
BUY_PRICE_ABOVE_MAX: "Buy price is above maximum!"
BUY_PRICE_BELOW_MIN: "Buy price is below minimum!"
CLICK_TO_AUTOFILL_ITEM: "Click the sign with the item that this shop is for!"
NO_ITEM_IN_HAND: "You don't have an item in your hand to autofill!"
PROTECTED_SHOP: "Successfully protected the shop with LWC!"
PROTECTED_SHOP_SIGN: "Successfully protected the shop sign with LWC!"
SHOP_CREATED: "Shop successfully created!"
SHOP_FEE_PAID: "You have been charged %amount"
SHOP_REFUNDED: "You have been refunded %amount."
ITEM_GIVEN: "Given %item to %player."
RESTRICTED_SIGN_CREATED: "Sign successfully created!"
PLAYER_NOT_FOUND: "Player not found!"
NO_PERMISSION: "You don't have permissions to do that!"
INCORRECT_ITEM_ID: "You have specified an invalid item id!"
NOT_ENOUGH_PROTECTIONS: "Could not create a protection!"
CANNOT_CREATE_SHOP_HERE: "You can't create shop here!"
TOGGLE_MESSAGES_OFF: "You will no longer receive messages from your shop(s)."
TOGGLE_MESSAGES_ON: "You will now receive messages from your shop(s)."
TOGGLE_ACCESS_ON: "You can no longer trade at shops that you have access to"
TOGGLE_ACCESS_OFF: "You can now trade at shops that you have access to"