Compare commits

...
44 Commits
Author SHA1 Message Date
Josh Roy 6d2a8ffba4 Release 2.20.1 2023-08-05 18:59:32 +01:00
Josh Roy b781c1e924 Add /ess usermap cache sub-command
Allows to view the number of known UUIDs as
well as name to UUID pairs.
2023-08-05 16:48:23 +01:00
Josh Roy 19d6db0b4c Don't cache previously known offline names
This can lead to the potential that a UUID can
be mapped to the improper name. This logic should
be handled the join logic.
2023-08-05 16:48:23 +01:00
Josh Roy 02ced188c8 Always populate last known name into cache
In theory this should never be an issue but
somehow is?
2023-08-05 16:48:23 +01:00
Josh Roy 7f3b62a180 Remove extraneous manual user cache loading
The usermap will already do this on its own,
and we should really avoid doing this outside
the usermap to avoid unforeseen behavior changes.
2023-08-05 16:48:23 +01:00
Josh Roy 908b06570f Remove extraneous offline name update code
This exact code exists in ModernUserMap#getUser(String)
2023-08-05 16:48:23 +01:00
Josh Roy d7e5c10b51 Fix remaining offline visibility checks (#5466)
Purpur added a new self-referencing method that
we don't implement with our stub class. This will
prevent Player#canSee from being called for
offline players (it would be false anyway).
2023-08-05 11:44:40 -04:00
Josh Roy b2ae28b450 Fix discord module console relay not filtering all color codes (#5454) 2023-07-26 14:22:30 -04:00
Josh Roy e558e7365a Fix trade signs not working with currency suffix (#5441) 2023-07-25 21:16:50 +00:00
Josh Roy c32a0f975e Revert duel hand behavior of /book command 2023-07-25 17:10:20 -04:00
Josh Roy ae1f1583c2 Fix enchant not working with offhand 2023-07-25 17:10:20 -04:00
Flask Bot 58eea1724f New Crowdin updates (#5424) 2023-07-23 20:55:40 +00:00
Josh Roy 52c9ca8197 Fix inaccurate online player count for Discord leave message (#5440)
fixes #5256
2023-07-23 15:10:46 +01:00
Josh Roy f26e1b2e29 Fix invalid unlimited items preventing userdata to load
Invalid material names would previously return a null value
when deserializing. This raises an exception from within
Configurate because they use an EnumSet internally during
deserialization which doesn't support null elements.
2023-07-22 22:53:26 +01:00
Josh Roy f84a311c2b Ensure user data deserialization exceptions include file name
More than just a SerializationException can happen I guess
2023-07-22 22:53:26 +01:00
MDandJosh Roy 60129594a6 Rename OfflinePlayer to OfflinePlayerStub (#5417)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2023-07-04 09:45:58 -04:00
Flask BotandJosh Roy 563d3fab4e New Crowdin updates (#5370)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
2023-07-04 09:36:32 -04:00
1022f7a3ab Add KitPreExpandItemsEvent (#5407)
Co-authored-by: YanisBft <yanis.briffaut@gmail.com>
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2023-07-01 17:51:58 -04:00
Josh Roy d57094c0bc Add link module to /ess dump 2023-07-01 17:45:07 -04:00
Josh Roy 863b9cffc5 Add backoff and skip for Discord console relay 2023-07-01 17:45:07 -04:00
Josh Roy 1921abd310 Shorten logger names for Discord module console relay 2023-07-01 17:45:07 -04:00
Josh Roy 803d800bdd Fix Discord module webhook closing incorrectly 2023-07-01 17:45:07 -04:00
Josh Roy 5276204cf2 Increase Discord module console relay message limit 2023-07-01 17:45:07 -04:00
Josh Roy 697128bcf2 Update Discord Module to JDA 5 2023-07-01 17:45:07 -04:00
Josh RoyandMD a1fa1e38f8 Don't do visibility checks for OfflinePlayers (#5375)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com>
2023-07-01 16:41:56 -04:00
Flask Bot ed41790712 Update items.json for 1.20 2023-07-01 20:37:21 +01:00
Josh Roy 834ef4ea57 Update to Minecraft 1.20 2023-07-01 20:37:21 +01:00
Josh Roy 03ed9a5b41 Fix roles/groups not being removed instantly upon unlink 2023-06-18 21:57:27 +01:00
Josh Roy d67dd46cdc Clean up link policy code
Also error when new link policy types are added
so we remember to write out the behavior here
2023-06-18 21:57:27 +01:00
Josh Roy 694ed6e66f Use removeAccount return value for AccountLinkManager#unlinkAccount 2023-06-18 21:57:27 +01:00
Josh Roy 8a0526b1e5 Fix discord link data being rewritten when no data was changed 2023-06-18 21:57:27 +01:00
MD a116e8630d Update Gradle, build plugins and GitHub Actions (#5383) 2023-06-14 19:27:01 -04:00
Josh Roy 8b2c7d7ad1 Fix regression in #5378 (#5379) 2023-06-03 23:13:09 +01:00
Josh Roy 8d07c4bb0f Fix regression w/empty strings with KeywordReplacer (#5378) 2023-06-02 22:54:30 +00:00
Josh Roy fc3dabf8f5 Fix keywords in kit commands not working (#5377)
Don't process b64 item through keyword replacer
and don't replace spaces on command strings
2023-06-01 21:14:41 -04:00
Josh Roy cdd277da92 Fix config BigDecimal parsing returning null on error (#5373)
Also add some more exception logging for parse issues.
2023-05-31 19:46:19 -04:00
Charles DeLancey 0d322e2c6b Fix typo in Discord docs (#5371) 2023-05-30 07:46:09 -04:00
646b60a90b Add ability to get recipe of item in hand (#5346)
Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
Co-authored-by: pop4959 <pop4959@gmail.com>
2023-05-28 18:27:18 +00:00
Flask Bot 357cd6b246 New Crowdin updates (#5357) 2023-05-27 02:00:11 +00:00
Josh Roy a4fb02f3e6 Don't run AntiBuild checks on NPCs (#5365) 2023-05-26 21:54:46 -04:00
Josh Roy 2828901927 Fix variables in kits having underscores replaced with spaces (#5366) 2023-05-27 01:51:11 +00:00
Josh Roy 1e0f7cb984 Fix question and shout prefixes with toggle shout (#5367) 2023-05-26 21:48:10 -04:00
Josh Roy 52a4dd2c60 Fix NPE during first join for LuckPerms contexts (#5364) 2023-05-26 19:29:37 -04:00
Josh Roy 8323b47e40 Prepare for 2.20.1 dev builds (#5355) 2023-05-23 11:32:12 -04:00
116 changed files with 2234 additions and 466 deletions

No files matched your search

+13 -18
View File
@@ -5,6 +5,9 @@ on:
branches:
- 2.x
- dev/*
release:
types:
- published
jobs:
build:
@@ -13,26 +16,18 @@ jobs:
steps:
- name: Checkout Git repo
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Restore Gradle cache
uses: actions/cache@v2
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
distribution: 'temurin'
java-version: 17
- name: Set up JDK 16
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: 16
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Build with Gradle
run: |
@@ -40,7 +35,7 @@ jobs:
./gradlew build --stacktrace
- name: Archive plugin jars on GitHub
uses: actions/upload-artifact@master
uses: actions/upload-artifact@v3
with:
name: EssentialsX plugin jars
path: jars/
@@ -66,7 +61,7 @@ jobs:
cp -r EssentialsXMPP/build/docs/javadoc/ javadocs/EssentialsXMPP/
- name: Archive Javadocs
uses: actions/upload-artifact@master
uses: actions/upload-artifact@v3
with:
name: javadocs
path: javadocs/
@@ -84,7 +79,7 @@ jobs:
node-version: 16
- name: Download Javadocs
uses: actions/download-artifact@master
uses: actions/download-artifact@v3
with:
name: javadocs
path: javadocs/
+8 -16
View File
@@ -18,26 +18,18 @@ jobs:
steps:
- name: Checkout Git repo
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Restore Gradle cache
uses: actions/cache@v2
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
restore-keys: |
${{ runner.os }}-gradle-
distribution: 'temurin'
java-version: 17
- name: Set up JDK 16
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: 16
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Build with Gradle
run: |
@@ -45,7 +37,7 @@ jobs:
./gradlew build --stacktrace
- name: Archive plugin jars on GitHub
uses: actions/upload-artifact@master
uses: actions/upload-artifact@v3
with:
name: EssentialsX plugin jars
path: jars/
@@ -40,7 +40,7 @@ public class BalanceTopImpl implements BalanceTop {
user.updateMoneyCache(userMoney);
newTotal = newTotal.add(userMoney);
final String name;
if (user.getBase() instanceof OfflinePlayer) {
if (user.getBase() instanceof OfflinePlayerStub) {
name = user.getLastAccountName();
} else if (user.isHidden()) {
name = user.getName();
@@ -954,17 +954,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
//This will return null if there is not a match.
@Override
public User getOfflineUser(final String name) {
final User user = userMap.getUser(name);
if (user != null && user.getBase() instanceof OfflinePlayer) {
//This code should attempt to use the last known name of a user, if Bukkit returns name as null.
final String lastName = user.getLastAccountName();
if (lastName != null) {
((OfflinePlayer) user.getBase()).setName(lastName);
} else {
((OfflinePlayer) user.getBase()).setName(name);
}
}
return user;
return userMap.getUser(name);
}
@Override
@@ -1052,7 +1042,7 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return true;
}
return interactor.getBase().canSee(interactee.getBase());
return !interactee.isHiddenFrom(interactor.getBase());
}
//This will create a new user if there is not a match.
@@ -1067,19 +1057,9 @@ public class Essentials extends JavaPlugin implements net.ess3.api.IEssentials {
return null;
}
User user = userMap.getUser(base.getUniqueId());
final User user = userMap.getUser(base);
if (user == null) {
if (getSettings().isDebug()) {
LOGGER.log(Level.INFO, "Constructing new userfile from base player " + base.getName());
}
user = userMap.loadUncachedUser(base);
// The above method will end up creating a new user, but it will not be added to the cache.
// Since we already call UserMap#getUser() above, we are already okay with adding the user to the cache,
// so we need to manually add the user to the cache in order to avoid a memory leak and maintain behavior.
userMap.addCachedUser(user);
} else if (base.getClass() != UUIDPlayer.class || user.getBase() == null) {
if (base.getClass() != UUIDPlayer.class || user.getBase() == null) {
user.update(base);
}
return user;
@@ -963,7 +963,7 @@ public class EssentialsUpgrade {
}
}
uuids.put(uuid, config.getLong("timestamps.logout", 0L));
uuids.put(uuid, time);
nameToUuidMap.put(name, uuid);
}
} catch (IllegalArgumentException | IndexOutOfBoundsException ignored) {
@@ -10,6 +10,7 @@ import com.earth2me.essentials.utils.DateUtil;
import com.earth2me.essentials.utils.NumberUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.events.KitClaimEvent;
import net.essentialsx.api.v2.events.KitPreExpandItemsEvent;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@@ -219,7 +220,11 @@ public class Kit {
final int maxStackSize = user.isAuthorized("essentials.oversizedstacks") ? ess.getSettings().getOversizedStackSize() : 0;
final boolean isDropItemsIfFull = ess.getSettings().isDropItemsIfFull();
final KitPreExpandItemsEvent itemsEvent = new KitPreExpandItemsEvent(user, kitName, itemList);
Bukkit.getPluginManager().callEvent(itemsEvent);
final ItemStack[] itemArray = itemList.toArray(new ItemStack[0]);
if (!isDropItemsIfFull && !Inventories.hasSpace(user.getBase(), maxStackSize, autoEquip, itemArray)) {
user.sendMessage(tl("kitInvFullNoDrop"));
return false;
@@ -194,14 +194,14 @@ public class MetaItemStack {
final Material WRITTEN_BOOK = EnumUtil.getMaterial("WRITTEN_BOOK");
if (split.length > 1 && split[0].equalsIgnoreCase("name") && hasMetaPermission(sender, "name", false, true, ess)) {
final String displayName = FormatUtil.replaceFormat(split[1].replace('_', ' '));
final String displayName = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
final ItemMeta meta = stack.getItemMeta();
meta.setDisplayName(displayName);
stack.setItemMeta(meta);
} else if (split.length > 1 && (split[0].equalsIgnoreCase("lore") || split[0].equalsIgnoreCase("desc")) && hasMetaPermission(sender, "lore", false, true, ess)) {
final List<String> lore = new ArrayList<>();
for (final String line : split[1].split("(?<!\\\\)\\|")) {
lore.add(FormatUtil.replaceFormat(line.replace('_', ' ').replace("\\|", "|")));
lore.add(FormatUtil.replaceFormat(line.replaceAll("(?<!\\\\)_", " ").replace("\\_", "_").replace("\\|", "|")));
}
final ItemMeta meta = stack.getItemMeta();
meta.setLore(lore);
@@ -230,7 +230,7 @@ public class MetaItemStack {
meta.setAuthor(author);
stack.setItemMeta(meta);
} else if (split.length > 1 && split[0].equalsIgnoreCase("title") && stack.getType() == WRITTEN_BOOK && hasMetaPermission(sender, "title", false, true, ess)) {
final String title = FormatUtil.replaceFormat(split[1].replace('_', ' '));
final String title = FormatUtil.replaceFormat(split[1].replaceAll("(?<!\\\\)_", " ").replace("\\_", "_"));
final BookMeta meta = (BookMeta) stack.getItemMeta();
meta.setTitle(title);
stack.setItemMeta(meta);
@@ -240,7 +240,7 @@ public class MetaItemStack {
final List<String> pages = meta.hasPages() ? new ArrayList<>(meta.getPages()) : new ArrayList<>();
final List<String> lines = new ArrayList<>();
for (final String line : split[1].split("(?<!\\\\)\\|")) {
lines.add(FormatUtil.replaceFormat(line.replace('_', ' ').replace("\\|", "|")));
lines.add(FormatUtil.replaceFormat(line.replaceAll("(?<!\\\\)_", " ").replace("\\_", "_").replace("\\|", "|")));
}
final String content = String.join("\n", lines);
if (page >= pages.size()) {
@@ -109,6 +109,8 @@ public enum Mob {
TADPOLE("Tadpole", Enemies.FRIENDLY, "TADPOLE"),
WARDEN("Warden", Enemies.ENEMY, "WARDEN"),
CHEST_BOAT("ChestBoat", Enemies.NEUTRAL, "CHEST_BOAT"),
CAMEL("Camel", Enemies.FRIENDLY, "CAMEL"),
SNIFFER("Sniffer", Enemies.FRIENDLY, "SNIFFER"),
;
private static final Map<String, Mob> hashMap = new HashMap<>();
@@ -3,9 +3,11 @@ package com.earth2me.essentials;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.nms.refl.ReflUtil;
import org.bukkit.Material;
import org.bukkit.TreeSpecies;
import org.bukkit.entity.Axolotl;
import org.bukkit.entity.Boat;
import org.bukkit.entity.Camel;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Fox;
@@ -15,8 +17,10 @@ import org.bukkit.entity.MushroomCow;
import org.bukkit.entity.Ocelot;
import org.bukkit.entity.Panda;
import org.bukkit.entity.Parrot;
import org.bukkit.entity.Player;
import org.bukkit.entity.TropicalFish;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Method;
@@ -41,6 +45,7 @@ public final class MobCompat {
public static final EntityType AXOLOTL = getEntityType("AXOLOTL");
public static final EntityType GOAT = getEntityType("GOAT");
public static final EntityType FROG = getEntityType("FROG");
public static final EntityType CAMEL = getEntityType("CAMEL");
// Constants for mobs that have changed since earlier versions
public static final EntityType CAT = getEntityType("CAT", "OCELOT");
@@ -195,6 +200,19 @@ public final class MobCompat {
}
}
public static void setCamelSaddle(final Entity entity, final Player target) {
if (VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_20_1_R01)) {
return;
}
if (entity instanceof Camel) {
final Camel camel = (Camel) entity;
camel.setTamed(true);
camel.setOwner(target);
camel.getInventory().setSaddle(new ItemStack(Material.SADDLE, 1));
}
}
public enum CatType {
// These are (loosely) Mojang names for the cats
SIAMESE("SIAMESE", "SIAMESE_CAT"),
@@ -209,6 +209,7 @@ public enum MobData {
MANGROVE_BOAT("mangrove", Boat.class, MobCompat.BoatVariant.MANGROVE, true),
OAK_BOAT("oak", Boat.class, MobCompat.BoatVariant.OAK, true),
SPRUCE_BOAT("spruce", Boat.class, MobCompat.BoatVariant.SPRUCE, true),
SADDLE_CAMEL("saddle", MobCompat.CAMEL, Data.CAMELSADDLE, true),
;
final private String nickname;
@@ -387,6 +388,8 @@ public enum MobData {
}
} else if (this.value.equals(Data.GOAT_SCREAMING)) {
((Goat) spawned).setScreaming(true);
} else if (this.value.equals(Data.CAMELSADDLE)) {
MobCompat.setCamelSaddle(spawned, target);
} else if (this.value instanceof MobCompat.BoatVariant) {
MobCompat.setBoatVariant(spawned, (MobCompat.BoatVariant) this.value);
} else if (this.value instanceof String) {
@@ -446,5 +449,6 @@ public enum MobData {
FISH_BODY_COLOR,
FISH_PATTERN_COLOR,
GOAT_SCREAMING,
CAMELSADDLE,
}
}
@@ -55,9 +55,9 @@ public final class PlayerList {
int playerHidden = 0;
int hiddenCount = 0;
for (final User onlinePlayer : ess.getOnlineUsers()) {
if (onlinePlayer.isHidden() || (user != null && !user.getBase().canSee(onlinePlayer.getBase()))) {
if (onlinePlayer.isHidden() || (user != null && onlinePlayer.isHiddenFrom(user.getBase()))) {
playerHidden++;
if (showHidden || user != null && user.getBase().canSee(onlinePlayer.getBase())) {
if (showHidden || user != null && !onlinePlayer.isHiddenFrom(user.getBase())) {
hiddenCount++;
}
}
@@ -75,7 +75,7 @@ public final class PlayerList {
public static Map<String, List<User>> getPlayerLists(final IEssentials ess, final IUser sender, final boolean showHidden) {
final Map<String, List<User>> playerList = new HashMap<>();
for (final User onlineUser : ess.getOnlineUsers()) {
if ((sender == null && !showHidden && onlineUser.isHidden()) || (sender != null && !showHidden && !sender.getBase().canSee(onlineUser.getBase()))) {
if ((sender == null && !showHidden && onlineUser.isHidden()) || (sender != null && !showHidden && onlineUser.isHiddenFrom(sender.getBase()))) {
continue;
}
final String group = FormatUtil.stripFormat(FormatUtil.stripEssentialsFormat(onlineUser.getGroup().toLowerCase()));
@@ -152,7 +152,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
private boolean isAuthorizedCheck(final String node) {
if (base instanceof OfflinePlayer) {
if (base instanceof OfflinePlayerStub) {
return false;
}
@@ -170,7 +170,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
private boolean isPermSetCheck(final String node) {
if (base instanceof OfflinePlayer) {
if (base instanceof OfflinePlayerStub) {
return false;
}
@@ -188,7 +188,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
private TriState isAuthorizedExactCheck(final String node) {
if (base instanceof OfflinePlayer) {
if (base instanceof OfflinePlayerStub) {
return TriState.UNSET;
}
@@ -311,7 +311,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
private void _dispose() {
if (!base.isOnline()) {
this.base = new OfflinePlayer(getConfigUUID(), ess.getServer());
this.base = new OfflinePlayerStub(getConfigUUID(), ess.getServer());
}
cleanup();
}
@@ -679,6 +679,9 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
@Override
public boolean isHiddenFrom(Player player) {
if (getBase() instanceof OfflinePlayerStub || player instanceof OfflinePlayerStub) {
return true;
}
return !player.canSee(getBase());
}
@@ -706,7 +709,7 @@ public class User extends UserData implements Comparable<User>, IMessageRecipien
}
public boolean isHidden(final Player player) {
return hidden || !player.canSee(getBase());
return hidden || isHiddenFrom(player);
}
@Override
@@ -17,7 +17,6 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.spongepowered.configurate.serialize.SerializationException;
import java.io.File;
import java.math.BigDecimal;
@@ -83,7 +82,7 @@ public abstract class UserData extends PlayerExtension implements IConf {
config.load();
try {
holder = config.getRootNode().get(UserConfigHolder.class);
} catch (SerializationException e) {
} catch (Throwable e) {
ess.getLogger().log(Level.SEVERE, "Error while reading user config: " + config.getFile().getName(), e);
throw new RuntimeException(e);
}
@@ -40,7 +40,7 @@ public class UserMap {
if (player instanceof Player) {
userPlayer = (Player) player;
} else {
final com.earth2me.essentials.OfflinePlayer essPlayer = new com.earth2me.essentials.OfflinePlayer(player.getUniqueId(), Bukkit.getServer());
final OfflinePlayerStub essPlayer = new OfflinePlayerStub(player.getUniqueId(), Bukkit.getServer());
essPlayer.setName(player.getName());
userPlayer = essPlayer;
}
@@ -2,7 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.Console;
import com.earth2me.essentials.OfflinePlayer;
import com.earth2me.essentials.OfflinePlayerStub;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import org.bukkit.BanList;
@@ -30,7 +30,7 @@ public class Commandban extends EssentialsCommand {
user = getPlayer(server, args, 0, true, true);
} catch (final PlayerNotFoundException e) {
nomatch = true;
user = ess.getUser(new OfflinePlayer(args[0], ess.getServer()));
user = ess.getUser(new OfflinePlayerStub(args[0], ess.getServer()));
}
if (!user.getBase().isOnline()) {
if (sender.isPlayer() && !ess.getUser(sender.getPlayer()).isAuthorized("essentials.ban.offline")) {
@@ -25,7 +25,7 @@ public class Commandbook extends EssentialsCommand {
@Override
public void run(final Server server, final User user, final String commandLabel, final String[] args) throws Exception {
final ItemStack item = user.getItemInHand();
final ItemStack item = Inventories.getItemInMainHand(user.getBase());
final String player = user.getName();
if (item.getType() == Material.WRITTEN_BOOK) {
final BookMeta bmeta = (BookMeta) item.getItemMeta();
@@ -3,14 +3,22 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import com.google.common.collect.Lists;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.HangingSign;
import org.bukkit.block.data.type.WallHangingSign;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.block.sign.Side;
import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.util.Vector;
import java.util.Collections;
import java.util.List;
@@ -32,7 +40,7 @@ public class Commandeditsign extends EssentialsCommand {
if (!(target.getState() instanceof Sign)) {
throw new Exception(tl("editsignCommandTarget"));
}
final Sign sign = (Sign) target.getState();
final ModifiableSign sign = wrapSign((Sign) target.getState(), user);
try {
if (args[0].equalsIgnoreCase("set") && args.length > 2) {
final String[] existingLines = sign.getLines();
@@ -108,8 +116,15 @@ public class Commandeditsign extends EssentialsCommand {
}
}
private boolean callSignEvent(final Sign sign, final Player player, final String[] lines) {
final SignChangeEvent event = new SignChangeEvent(sign.getBlock(), player, lines);
private boolean callSignEvent(final ModifiableSign sign, final Player player, final String[] lines) {
final SignChangeEvent event;
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_1_R01)) {
event = new SignChangeEvent(sign.getBlock(), player, lines, sign.isFront() ? Side.FRONT : Side.BACK);
} else {
//noinspection deprecation
event = new SignChangeEvent(sign.getBlock(), player, lines);
}
Bukkit.getServer().getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (ess.getSettings().isDebug()) {
@@ -135,7 +150,7 @@ public class Commandeditsign extends EssentialsCommand {
final int line = Integer.parseInt(args[1]);
final Block target = user.getTargetBlock(5);
if (target.getState() instanceof Sign && line <= 4) {
final Sign sign = (Sign) target.getState();
final ModifiableSign sign = wrapSign((Sign) target.getState(), user);
return Lists.newArrayList(FormatUtil.unformatString(user, "essentials.editsign", sign.getLine(line - 1)));
}
return Collections.emptyList();
@@ -143,4 +158,93 @@ public class Commandeditsign extends EssentialsCommand {
return Collections.emptyList();
}
}
private ModifiableSign wrapSign(final Sign sign, final User user) {
if (VersionUtil.getServerBukkitVersion().isHigherThanOrEqualTo(VersionUtil.v1_20_1_R01)) {
final Vector eyeLocLessSign = user.getBase().getEyeLocation().toVector().subtract(sign.getLocation().add(.5, .5, .5).toVector());
final BlockData signBlockData = sign.getBlockData();
final BlockFace signDirection;
if (signBlockData instanceof org.bukkit.block.data.type.Sign) {
signDirection = ((org.bukkit.block.data.type.Sign) signBlockData).getRotation();
} else if (signBlockData instanceof WallSign) {
signDirection = ((WallSign) signBlockData).getFacing();
} else if (signBlockData instanceof HangingSign) {
signDirection = ((HangingSign) signBlockData).getRotation();
} else if (signBlockData instanceof WallHangingSign) {
signDirection = ((WallHangingSign) signBlockData).getFacing();
} else {
throw new IllegalStateException("Unknown block data for sign: " + signBlockData.getClass());
}
final Side side = eyeLocLessSign.dot(signDirection.getDirection()) > 0 ? Side.FRONT : Side.BACK;
return new ModifiableSign(sign) {
@Override
String[] getLines() {
return sign.getSide(side).getLines();
}
@Override
String getLine(int line) {
return sign.getSide(side).getLine(line);
}
@Override
void setLine(int line, String text) {
sign.getSide(side).setLine(line, text);
}
@Override
boolean isFront() {
return side == Side.FRONT;
}
};
}
return new ModifiableSign(sign) {
@Override
String[] getLines() {
return sign.getLines();
}
@Override
String getLine(int line) {
return sign.getLine(line);
}
@Override
void setLine(int line, String text) {
sign.setLine(line, text);
}
@Override
boolean isFront() {
return true;
}
};
}
private abstract static class ModifiableSign {
protected final Sign sign;
protected ModifiableSign(final Sign sign) {
this.sign = sign;
}
abstract String getLine(int line);
abstract String[] getLines();
abstract void setLine(int line, String text);
abstract boolean isFront();
Block getBlock() {
return sign.getBlock();
}
void update() {
sign.update();
}
}
}
@@ -3,7 +3,6 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.Enchantments;
import com.earth2me.essentials.MetaItemStack;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.StringUtil;
import com.google.common.collect.Lists;
import org.bukkit.Material;
@@ -57,7 +56,7 @@ public class Commandenchant extends EssentialsCommand {
final MetaItemStack metaStack = new MetaItemStack(stack);
final Enchantment enchantment = metaStack.getEnchantment(user, args[0]);
metaStack.addEnchantment(user.getSource(), ess.getSettings().allowUnsafeEnchantments() && user.isAuthorized("essentials.enchantments.allowunsafe"), enchantment, level);
Inventories.setItemInMainHand(user.getBase(), metaStack.getItemStack());
stack.setItemMeta(metaStack.getItemStack().getItemMeta());
user.getBase().updateInventory();
final String enchantName = enchantment.getName().toLowerCase(Locale.ENGLISH).replace('_', ' ');
if (level == 0) {
@@ -328,6 +328,7 @@ public class Commandessentials extends EssentialsCommand {
files.add(new PasteUtil.PasteFile("dump.json", dump.toString()));
final Plugin essDiscord = Bukkit.getPluginManager().getPlugin("EssentialsDiscord");
final Plugin essDiscordLink = Bukkit.getPluginManager().getPlugin("EssentialsDiscordLink");
final Plugin essSpawn = Bukkit.getPluginManager().getPlugin("EssentialsSpawn");
final Map<String, Command> knownCommandsCopy = new HashMap<>(ess.getKnownCommandsProvider().getKnownCommands());
@@ -389,6 +390,15 @@ public class Commandessentials extends EssentialsCommand {
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "discord-config.yml", e.getMessage()));
}
if (essDiscordLink != null) {
try {
files.add(new PasteUtil.PasteFile("discord-link-config.yml",
new String(Files.readAllBytes(essDiscordLink.getDataFolder().toPath().resolve("config.yml")), StandardCharsets.UTF_8)));
} catch (IOException e) {
sender.sendMessage(tl("dumpErrorUpload", "discord-link-config.yml", e.getMessage()));
}
}
}
if (kits) {
@@ -690,6 +700,8 @@ public class Commandessentials extends EssentialsCommand {
}
ess.getLogger().info("Found " + total + " orphaned userdata files.");
});
} else if (args[1].equalsIgnoreCase("cache")) {
sender.sendMessage(tl("usermapKnown", ess.getUsers().getAllUserUUIDs().size(), ess.getUsers().getNameCache().size()));
} else {
try {
final UUID uuid = UUID.fromString(args[1]);
@@ -1,6 +1,6 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.OfflinePlayer;
import com.earth2me.essentials.OfflinePlayerStub;
import com.earth2me.essentials.Trade;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.StringUtil;
@@ -42,7 +42,7 @@ public class Commandhome extends EssentialsCommand {
}
try {
if ("bed".equalsIgnoreCase(homeName) && user.isAuthorized("essentials.home.bed")) {
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayer) {
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayerStub) {
throw new Exception(tl("bedOffline"));
}
PaperLib.getBedSpawnLocationAsync(player.getBase(), true).thenAccept(location -> {
@@ -101,7 +101,7 @@ public class Commandhome extends EssentialsCommand {
user.sendMessage(tl("homes", StringUtil.joinList(homes), count, getHomeLimit(finalPlayer)));
}
});
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayer) {
if (!player.getBase().isOnline() || player.getBase() instanceof OfflinePlayerStub) {
message.complete(null);
return;
}
@@ -28,7 +28,7 @@ public class Commandkick extends EssentialsCommand {
final User user = sender.isPlayer() ? ess.getUser(sender.getPlayer()) : null;
if (user != null) {
if (target.isHidden(sender.getPlayer()) && !user.canInteractVanished() && !sender.getPlayer().canSee(target.getBase())) {
if (target.isHidden(sender.getPlayer()) && !user.canInteractVanished() && target.isHiddenFrom(sender.getPlayer())) {
throw new PlayerNotFoundException();
}
@@ -1,7 +1,7 @@
package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.OfflinePlayer;
import com.earth2me.essentials.OfflinePlayerStub;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.DateUtil;
import net.ess3.api.events.MuteStatusChangeEvent;
@@ -29,7 +29,7 @@ public class Commandmute extends EssentialsCommand {
user = getPlayer(server, args, 0, true, true);
} catch (final PlayerNotFoundException e) {
nomatch = true;
user = ess.getUser(new OfflinePlayer(args[0], ess.getServer()));
user = ess.getUser(new OfflinePlayerStub(args[0], ess.getServer()));
}
if (!user.getBase().isOnline() && sender.isPlayer()) {
if (!sender.isAuthorized("essentials.mute.offline", ess)) {
@@ -87,7 +87,7 @@ public class Commandnear extends EssentialsCommand {
final Queue<User> nearbyPlayers = new PriorityQueue<>((o1, o2) -> (int) (o1.getLocation().distanceSquared(loc) - o2.getLocation().distanceSquared(loc)));
for (final User player : ess.getOnlineUsers()) {
if (!player.equals(user) && !player.isAuthorized("essentials.near.exclude") && (!player.isHidden(user.getBase()) || showHidden || user.getBase().canSee(player.getBase()))) {
if (!player.equals(user) && !player.isAuthorized("essentials.near.exclude") && (!player.isHidden(user.getBase()) || showHidden || !player.isHiddenFrom(user.getBase()))) {
final Location playerLoc = player.getLocation();
if (playerLoc.getWorld() != world) {
continue;
@@ -25,7 +25,7 @@ public class Commandrealname extends EssentialsCommand {
final boolean skipHidden = sender.isPlayer() && !ess.getUser(sender.getPlayer()).canInteractVanished();
boolean foundUser = false;
for (final User u : ess.getOnlineUsers()) {
if (skipHidden && u.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(u.getBase())) {
if (skipHidden && u.isHidden(sender.getPlayer()) && u.isHiddenFrom(sender.getPlayer())) {
continue;
}
u.setDisplayNick();
@@ -2,6 +2,7 @@ package com.earth2me.essentials.commands;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.craftbukkit.Inventories;
import com.earth2me.essentials.utils.EnumUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
@@ -53,7 +54,18 @@ public class Commandrecipe extends EssentialsCommand {
throw new NotEnoughArgumentsException();
}
final ItemStack itemType = ess.getItemDb().get(args[0]);
final ItemStack itemType;
if (args[0].equalsIgnoreCase("hand")) {
if (!sender.isPlayer()) {
throw new Exception(tl("consoleCannotUseCommand"));
}
itemType = Inventories.getItemInHand(sender.getPlayer());
} else {
itemType = ess.getItemDb().get(args[0]);
}
int recipeNo = 0;
if (args.length > 1) {
@@ -67,7 +67,7 @@ public class Commandspeed extends EssentialsCommand {
final List<Player> matchedPlayers = server.matchPlayer(name);
for (final Player matchPlayer : matchedPlayers) {
final User player = ess.getUser(matchPlayer);
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(matchPlayer)) {
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
continue;
}
foundUser = true;
@@ -44,7 +44,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
} else if (matchWildcards && searchTerm.contentEquals("*")) {
final boolean skipHidden = sender.isPlayer() && !ess.getUser(sender.getPlayer()).canInteractVanished();
for (final User onlineUser : ess.getOnlineUsers()) {
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(onlineUser.getBase())) {
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && onlineUser.isHiddenFrom(sender.getPlayer())) {
continue;
}
userConsumer.accept(onlineUser);
@@ -81,7 +81,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
if (matchWildcards && (searchTerm.contentEquals("**") || searchTerm.contentEquals("*"))) {
for (final User onlineUser : ess.getOnlineUsers()) {
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(onlineUser.getBase())) {
if (skipHidden && onlineUser.isHidden(sender.getPlayer()) && onlineUser.isHiddenFrom(sender.getPlayer())) {
continue;
}
userConsumer.accept(onlineUser);
@@ -96,7 +96,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
if (matchedPlayers.isEmpty()) {
final String matchText = searchTerm.toLowerCase(Locale.ENGLISH);
for (final User player : ess.getOnlineUsers()) {
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(player.getBase())) {
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
continue;
}
final String displayName = FormatUtil.stripFormat(player.getDisplayName()).toLowerCase(Locale.ENGLISH);
@@ -108,7 +108,7 @@ public abstract class EssentialsLoopCommand extends EssentialsCommand {
} else {
for (final Player matchPlayer : matchedPlayers) {
final User player = ess.getUser(matchPlayer);
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(matchPlayer)) {
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
continue;
}
foundUser = true;
@@ -51,7 +51,7 @@ public abstract class EssentialsToggleCommand extends EssentialsCommand {
final List<Player> matchedPlayers = server.matchPlayer(args[0]);
for (final Player matchPlayer : matchedPlayers) {
final User player = ess.getUser(matchPlayer);
if (skipHidden && player.isHidden(sender.getPlayer()) && !sender.getPlayer().canSee(matchPlayer)) {
if (skipHidden && player.isHidden(sender.getPlayer()) && player.isHiddenFrom(sender.getPlayer())) {
continue;
}
foundUser = true;
@@ -131,6 +131,7 @@ public class EssentialsConfiguration {
try {
return node.get(LazyLocation.class);
} catch (SerializationException e) {
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
return null;
}
}
@@ -272,7 +273,8 @@ public class EssentialsConfiguration {
try {
return node.get(BigDecimal.class);
} catch (SerializationException e) {
return null;
Essentials.getWrappedLogger().log(Level.SEVERE, e.getMessage(), e);
return def;
}
}
@@ -17,7 +17,9 @@ public class MaterialTypeSerializer extends ScalarSerializer<Material> {
if (obj instanceof String) {
return Material.matchMaterial((String) obj);
}
return null;
// Configurate will use an EnumSet to deserialize, which doesn't support null types. Default to air.
return Material.AIR;
}
@Override
@@ -21,8 +21,9 @@ public final class BanLookup {
}
public static BanEntry getBanEntry(final IEssentials ess, final String name) {
final Set<BanEntry> benteries = ess.getServer().getBanList(BanList.Type.NAME).getBanEntries();
for (final BanEntry banEnt : benteries) {
final Set benteries = ess.getServer().getBanList(BanList.Type.NAME).getBanEntries();
for (final Object ob : benteries) {
final BanEntry banEnt = (BanEntry) ob;
if (banEnt.getTarget().equals(name)) {
return banEnt;
}
@@ -1,6 +1,7 @@
package com.earth2me.essentials.economy.vault;
import com.earth2me.essentials.Essentials;
import com.earth2me.essentials.OfflinePlayerStub;
import com.earth2me.essentials.api.NoLoanPermittedException;
import com.earth2me.essentials.api.UserDoesNotExistException;
import com.earth2me.essentials.config.EssentialsUserConfiguration;
@@ -324,7 +325,7 @@ public class VaultEconomyProvider implements Economy {
if (player instanceof Player) {
userPlayer = (Player) player;
} else {
final com.earth2me.essentials.OfflinePlayer essPlayer = new com.earth2me.essentials.OfflinePlayer(player.getUniqueId(), ess.getServer());
final OfflinePlayerStub essPlayer = new OfflinePlayerStub(player.getUniqueId(), ess.getServer());
essPlayer.setName(player.getName());
userPlayer = essPlayer;
}
@@ -75,6 +75,14 @@ public class LuckPermsHandler extends ModernVaultHandler {
}
final User user = ess.getUsers().loadUncachedUser(target.getUniqueId());
// This will occur for first time players during join,
// None of our contexts would apply to that kind of person anyway,
// lets just skip :O
if (user == null) {
return;
}
for (Calculator calculator : this.calculators) {
calculator.function.apply(user).forEach(value -> consumer.accept(calculator.id, value));
}
@@ -8,6 +8,7 @@ import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.FormatUtil;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.MaxMoneyException;
import net.ess3.api.events.SignBreakEvent;
@@ -18,7 +19,7 @@ import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.Sign;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.block.data.Directional;
import org.bukkit.entity.Player;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.inventory.ItemStack;
@@ -48,7 +49,7 @@ public class EssentialsSign {
final BlockFace[] directions = new BlockFace[] {BlockFace.NORTH, BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST};
for (final BlockFace blockFace : directions) {
final Block signBlock = block.getRelative(blockFace);
if (MaterialUtil.isWallSign(signBlock.getType())) {
if (MaterialUtil.isWallSign(signBlock.getType()) || MaterialUtil.isWallHangingSign(signBlock.getType())) {
try {
if (getWallSignFacing(signBlock) == blockFace && isValidSign(new BlockSign(signBlock))) {
return true;
@@ -84,13 +85,14 @@ public class EssentialsSign {
}
private static BlockFace getWallSignFacing(final Block block) {
try {
final WallSign signData = (WallSign) block.getState().getBlockData();
return signData.getFacing();
} catch (final NoClassDefFoundError | NoSuchMethodError e) {
if (VersionUtil.PRE_FLATTENING) {
//noinspection deprecation
final org.bukkit.material.Sign signMat = (org.bukkit.material.Sign) block.getState().getData();
return signMat.getFacing();
}
final Directional signData = (Directional) block.getState().getBlockData();
return signData.getFacing();
}
protected final boolean onSignCreate(final SignChangeEvent event, final IEssentials ess) {
@@ -179,7 +179,7 @@ public class SignTrade extends EssentialsSign {
if (amount.compareTo(MINTRANSACTION) < 0 || money.compareTo(MINTRANSACTION) < 0) {
throw new SignException(tl("moreThanZero"));
}
final String newLine = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.shortCurrency(amount, ess).substring(1);
final String newLine = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.formatAsCurrency(amount);
validateSignLength(newLine);
sign.setLine(index, newLine);
return;
@@ -333,7 +333,7 @@ public class SignTrade extends EssentialsSign {
final BigDecimal money = getMoney(split[0], ess);
final BigDecimal amount = getBigDecimal(split[1], ess);
if (money != null && amount != null) {
final String newline = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.shortCurrency(value, ess).substring(1);
final String newline = NumberUtil.shortCurrency(money, ess) + ":" + NumberUtil.formatAsCurrency(value);
validateSignLength(newline);
sign.setLine(index, newline);
return;
@@ -140,6 +140,13 @@ public class KeywordReplacer implements IText {
for (int i = 0; i < input.getLines().size(); i++) {
String line = input.getLines().get(i);
// Skip processing b64 encoded items, they will not have keywords in them.
if (line.startsWith("@")) {
replaced.add(line);
continue;
}
final Matcher matcher = KEYWORD.matcher(line);
while (matcher.find()) {
@@ -375,7 +382,10 @@ public class KeywordReplacer implements IText {
}
if (this.replaceSpacesWithUnderscores) {
replacer = replacer.replaceAll("\\s", "_");
// Don't replace spaces with underscores in command nor escape underscores.
if (!line.startsWith("/")) {
replacer = replacer.replace("_", "\\_").replaceAll("\\s", "_");
}
}
//If this is just a regular keyword, lets throw it into the cache
@@ -1,6 +1,6 @@
package com.earth2me.essentials.userstorage;
import com.earth2me.essentials.OfflinePlayer;
import com.earth2me.essentials.OfflinePlayerStub;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.NumberUtil;
import com.google.common.cache.CacheBuilder;
@@ -98,11 +98,11 @@ public class ModernUserMap extends CacheLoader<UUID, User> implements IUserMap {
}
final User user = getUser(uuidCache.getCachedUUID(name));
if (user != null && user.getBase() instanceof OfflinePlayer) {
if (user != null && user.getBase() instanceof OfflinePlayerStub) {
if (user.getLastAccountName() != null) {
((OfflinePlayer) user.getBase()).setName(user.getLastAccountName());
((OfflinePlayerStub) user.getBase()).setName(user.getLastAccountName());
} else {
((OfflinePlayer) user.getBase()).setName(name);
((OfflinePlayerStub) user.getBase()).setName(name);
}
}
return user;
@@ -164,21 +164,31 @@ public class ModernUserMap extends CacheLoader<UUID, User> implements IUserMap {
final File userFile = getUserFile(uuid);
if (userFile.exists()) {
player = new OfflinePlayer(uuid, ess.getServer());
player = new OfflinePlayerStub(uuid, ess.getServer());
user = new User(player, ess);
((OfflinePlayer) player).setName(user.getLastAccountName());
uuidCache.updateCache(uuid, null);
final String accName = user.getLastAccountName();
((OfflinePlayerStub) player).setName(accName);
// Check to see if there is already a UUID mapping for the name in the name cache before updating it.
// Since this code is ran for offline players, there's a chance we could be overriding the mapping
// for a player who changed their name to an older player's name, let that be handled during join.
//
// Here is a senerio which could take place if didn't do the containsKey check;
// "JRoyLULW" joins the server - "JRoyLULW" is mapped to 86f39a70-eda7-44a2-88f8-0ade4e1ec8c0
// "JRoyLULW" changes their name to "mbax" - Nothing happens, they are yet to join the server
// "mdcfe" changes their name to "JRoyLULW" - Nothing happens, they are yet to join the server
// "JRoyLULW" (formally "mdcfe") joins the server - "JRoyLULW" is mapped to 62a6a4bb-a2b8-4796-bfe6-63067250990a
// The /baltop command is ran, iterating over all players.
//
// During the baltop iteration, two uuids have the `last-account-name` of "JRoyLULW" creating the
// potential that "JRoyLULW" is mapped back to 86f39a70-eda7-44a2-88f8-0ade4e1ec8c0 when the true
// bearer of that name is now 62a6a4bb-a2b8-4796-bfe6-63067250990a.
uuidCache.updateCache(uuid, (accName == null || uuidCache.getNameCache().containsKey(accName)) ? null : accName);
return user;
}
return null;
}
public void addCachedUser(final User user) {
userCache.put(user.getUUID(), user);
debugLogCache(user);
}
@Override
public Map<String, UUID> getNameCache() {
return uuidCache.getNameCache();
@@ -26,7 +26,7 @@ public final class FormatUtil {
private static final Pattern LOGCOLOR_PATTERN = Pattern.compile("\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]");
private static final Pattern URL_PATTERN = Pattern.compile("((?:(?:https?)://)?[\\w-_\\.]{2,})\\.([a-zA-Z]{2,3}(?:/\\S+)?)");
//Used to strip ANSI control codes from console
private static final Pattern ANSI_CONTROL_PATTERN = Pattern.compile("\u001B(?:\\[0?m|\\[38;2(?:;\\d{1,3}){3}m|\\[([0-9]{1,2}[;m]?){3})");
private static final Pattern ANSI_CONTROL_PATTERN = Pattern.compile("[\\x1B\\x9B][\\[\\]()#;?]*(?:(?:(?:;[-a-zA-Z\\d/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d/#&.:=?%@~_]*)*)?\\x07|(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~])");
private static final Pattern PAPER_CONTROL_PATTERN = Pattern.compile("(?i)" + (char) 0x7f + "[0-9A-FK-ORX]");
private FormatUtil() {
@@ -27,6 +27,8 @@ public final class MaterialUtil {
private static final Set<Material> POTIONS;
private static final Set<Material> SIGN_POSTS;
private static final Set<Material> WALL_SIGNS;
private static final Set<Material> HANGING_SIGNS;
private static final Set<Material> HANGING_WALL_SIGNS;
private static final Set<Material> HELMETS;
private static final Set<Material> CHESTPLATES;
@@ -71,7 +73,7 @@ public final class MaterialUtil {
MOB_HEADS = EnumUtil.getAllMatching(Material.class, "SKELETON_SKULL",
"SKELETON_WALL_SKULL", "WITHER_SKELETON_SKULL", "WITHER_SKELETON_WALL_SKULL",
"CREEPER_HEAD", "CREEPER_WALL_HEAD", "ZOMBIE_HEAD", "ZOMBIE_WALL_HEAD", "DRAGON_HEAD"
, "DRAGON_WALL_HEAD");
, "DRAGON_WALL_HEAD", "PIGLIN_HEAD", "PIGLIN_WALL_HEAD");
PLAYER_HEADS = EnumUtil.getAllMatching(Material.class, "PLAYER_HEAD", "PLAYER_WALL_HEAD");
@@ -83,14 +85,30 @@ public final class MaterialUtil {
"DARK_OAK_SIGN", "JUNGLE_SIGN",
"OAK_SIGN", "SPRUCE_SIGN",
"CRIMSON_SIGN", "WARPED_SIGN",
"MANGROVE_SIGN");
"MANGROVE_SIGN", "CHERRY_SIGN",
"BAMBOO_SIGN");
WALL_SIGNS = EnumUtil.getAllMatching(Material.class, "WALL_SIGN",
"ACACIA_WALL_SIGN", "BIRCH_WALL_SIGN",
"DARK_OAK_WALL_SIGN", "JUNGLE_WALL_SIGN",
"OAK_WALL_SIGN", "SPRUCE_WALL_SIGN",
"CRIMSON_WALL_SIGN", "WARPED_WALL_SIGN",
"MANGROVE_WALL_SIGN");
"MANGROVE_WALL_SIGN", "CHERRY_WALL_SIGN",
"BAMBOO_WALL_SIGN");
HANGING_SIGNS = EnumUtil.getAllMatching(Material.class, "ACACIA_HANGING_SIGN", "BIRCH_HANGING_SIGN",
"DARK_OAK_HANGING_SIGN", "JUNGLE_HANGING_SIGN",
"OAK_HANGING_SIGN", "SPRUCE_HANGING_SIGN",
"CRIMSON_HANGING_SIGN", "WARPED_HANGING_SIGN",
"MANGROVE_HANGING_SIGN", "CHERRY_HANGING_SIGN",
"BAMBOO_HANGING_SIGN");
HANGING_WALL_SIGNS = EnumUtil.getAllMatching(Material.class, "ACACIA_WALL_HANGING_SIGN", "BIRCH_WALL_HANGING_SIGN",
"DARK_OAK_WALL_HANGING_SIGN", "JUNGLE_WALL_HANGING_SIGN",
"OAK_WALL_HANGING_SIGN", "SPRUCE_WALL_HANGING_SIGN",
"CRIMSON_WALL_HANGING_SIGN", "WARPED_WALL_HANGING_SIGN",
"MANGROVE_WALL_HANGING_SIGN", "CHERRY_WALL_HANGING_SIGN",
"BAMBOO_WALL_HANGING_SIGN");
}
private MaterialUtil() {
@@ -152,12 +170,20 @@ public final class MaterialUtil {
return WALL_SIGNS.contains(material);
}
public static boolean isHangingSign(final Material material) {
return HANGING_SIGNS.contains(material);
}
public static boolean isWallHangingSign(final Material material) {
return HANGING_WALL_SIGNS.contains(material);
}
public static boolean isEditableBook(final Material material) {
return EDITABLE_BOOKS.contains(material);
}
public static boolean isSign(final Material material) {
return isSignPost(material) || isWallSign(material);
return isSignPost(material) || isWallSign(material) || isHangingSign(material) || isWallHangingSign(material);
}
public static boolean isSkull(final Material material) {
@@ -36,10 +36,10 @@ public final class VersionUtil {
public static final BukkitVersion v1_17_1_R01 = BukkitVersion.fromString("1.17.1-R0.1-SNAPSHOT");
public static final BukkitVersion v1_18_2_R01 = BukkitVersion.fromString("1.18.2-R0.1-SNAPSHOT");
public static final BukkitVersion v1_19_R01 = BukkitVersion.fromString("1.19-R0.1-SNAPSHOT");
public static final BukkitVersion v1_19_2_R01 = BukkitVersion.fromString("1.19.2-R0.1-SNAPSHOT");
public static final BukkitVersion v1_19_4_R01 = BukkitVersion.fromString("1.19.4-R0.1-SNAPSHOT");
public static final BukkitVersion v1_20_1_R01 = BukkitVersion.fromString("1.20.1-R0.1-SNAPSHOT");
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_4_R01);
private static final Set<BukkitVersion> supportedVersions = ImmutableSet.of(v1_8_8_R01, v1_9_4_R01, v1_10_2_R01, v1_11_2_R01, v1_12_2_R01, v1_13_2_R01, v1_14_4_R01, v1_15_2_R01, v1_16_5_R01, v1_17_1_R01, v1_18_2_R01, v1_19_4_R01, v1_20_1_R01);
public static final boolean PRE_FLATTENING = VersionUtil.getServerBukkitVersion().isLowerThan(VersionUtil.v1_13_0_R01);
@@ -71,10 +71,12 @@ public final class VersionUtil {
builder.put("io.akarin.server.Config", SupportStatus.DANGEROUS_FORK);
// Forge - Doesn't support Bukkit
builder.put("net.minecraftforge.common.MinecraftForge", SupportStatus.UNSTABLE);
// The below translates to net.minecraftforge.common.MinecraftForge
builder.put(dumb(new int[] {110, 101, 116, 46, 109, 105, 110, 101, 99, 114, 97, 102, 116, 102, 111, 114, 103, 101, 46, 99, 111, 109, 109, 111, 110, 46, 77, 105, 110, 101, 99, 114, 97, 102, 116, 70, 111, 114, 103, 101}, 40), SupportStatus.UNSTABLE);
// Fabric - Doesn't support Bukkit
builder.put("net.fabricmc.loader.launch.knot.KnotServer", SupportStatus.UNSTABLE);
// The below translates to net.fabricmc.loader.launch.knot.KnotServer
builder.put(dumb(new int[] {110, 101, 116, 46, 102, 97, 98, 114, 105, 99, 109, 99, 46, 108, 111, 97, 100, 101, 114, 46, 108, 97, 117, 110, 99, 104, 46, 107, 110, 111, 116, 46, 75, 110, 111, 116, 83, 101, 114, 118, 101, 114}, 42), SupportStatus.UNSTABLE);
// Misc translation layers that do not add NMS will be caught by this
if (ReflUtil.getNmsVersionObject().isHigherThanOrEqualTo(ReflUtil.V1_17_R1)) {
@@ -345,4 +347,21 @@ public final class VersionUtil {
return supported;
}
}
private static String dumb(final int[] clazz, final int len) {
final char[] chars = new char[clazz.length];
for (int i = 0; i < clazz.length; i++) {
chars[i] = (char) clazz[i];
}
final String decode = String.valueOf(chars);
if (decode.length() != len) {
System.exit(1);
return "why do hybrids try to bypass this?";
}
return decode;
}
}
@@ -0,0 +1,62 @@
package net.essentialsx.api.v2.events;
import net.ess3.api.IUser;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import java.util.List;
/**
* Called when items from a kit are about to be given to a {@link IUser user}.
* <p>
* This event is not cancellable and is called right before items are about to be received by the {@link #getUser() user}.
* If you want to prevent kits from being claimed to begin with, use the {@link net.ess3.api.events.KitClaimEvent}
* @see net.ess3.api.events.KitClaimEvent
*/
public class KitPreExpandItemsEvent extends Event {
private static final HandlerList handlers = new HandlerList();
private final IUser user;
private final String kitName;
private final List<ItemStack> itemStacks;
public KitPreExpandItemsEvent(IUser user, String kitName, List<ItemStack> itemStacks) {
this.user = user;
this.kitName = kitName;
this.itemStacks = itemStacks;
}
/**
* Gets the {@link IUser user} who is receiving the kit.
* @return the user.
*/
public IUser getUser() {
return user;
}
/**
* Gets the name of the kit the {@link IUser user} is receiving.
* @return the name of the kit.
*/
public String getKitName() {
return kitName;
}
/**
* Returns a mutable list with items to be received by the {@link IUser user}.
* @return the list of items.
*/
public List<ItemStack> getItemStacks() {
return itemStacks;
}
@Override
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}
File diff suppressed because it is too large. Load diff
@@ -157,6 +157,7 @@ commandHelpLine3=\u00a76Usage(s);
commandHelpLine4=\u00a76Aliases(s): \u00a7f{0}
commandHelpLineUsage={0} \u00a76- {1}
commandNotLoaded=\u00a74Command {0} is improperly loaded.
consoleCannotUseCommand=This command cannot be used by Console.
compassBearing=\u00a76Bearing\: {0} ({1} degrees).
compassCommandDescription=Describes your current bearing.
compassCommandUsage=/<command>
@@ -1025,8 +1026,8 @@ recentlyForeverAlone=\u00a74{0} recently went offline.
recipe=\u00a76Recipe for \u00a7c{0}\u00a76 (\u00a7c{1}\u00a76 of \u00a7c{2}\u00a76)
recipeBadIndex=There is no recipe by that number.
recipeCommandDescription=Displays how to craft items.
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage=/<command> <<item>|hand> [number]
recipeCommandUsage1=/<command> <<item>|hand> [page]
recipeCommandUsage1Description=Displays how to craft the given item
recipeFurnace=\u00a76Smelt\: \u00a7c{0}\u00a76.
recipeGrid=\u00a7c{0}X \u00a76| \u00a7{1}X \u00a76| \u00a7{2}X
@@ -1461,6 +1462,7 @@ userIsAwaySelfWithMessage=\u00a77You are now AFK.
userIsNotAwaySelf=\u00a77You are no longer AFK.
userJailed=\u00a76You have been jailed\!
usermapEntry=\u00a7c{0} \u00a76is mapped to \u00a7c{1}\u00a76.
usermapKnown=\u00a76There are \u00a7c{0} \u00a76known users to the user cache with \u00a7c{1} \u00a76name to UUID pairs.
usermapPurge=\u00a76Checking for files in userdata that are not mapped, results will be logged to console. Destructive Mode: {0}
usermapSize=\u00a76Current cached users in user map is \u00a7c{0}\u00a76/\u00a7c{1}\u00a76/\u00a7c{2}\u00a76.
userUnknown=\u00a74Warning\: The user ''\u00a7c{0}\u00a74'' has never joined this server.
@@ -6,10 +6,10 @@ action=§5* {0} §5{1}
addedToAccount=§a{0} бяха добавени към вашият акаунт.
addedToOthersAccount=§a{0} бяха добавени към акаунта на {1}. Нов баланс\: {2}
adventure=приключенски
afkCommandDescription=Маркира ви като далеч-от-клавиатурата.
afkCommandDescription=Маркира ви като далеч-от-клавиятурата.
afkCommandUsage=/<command> [player/message...]
afkCommandUsage1=/<command> [message]
afkCommandUsage1Description=Активира вашия афк статус с опционална причина
afkCommandUsage1Description=Активира вашият афк статус с опционална причина
afkCommandUsage2=/<command> <player> [message]
afkCommandUsage2Description=Активира афк статуса на специфичен играч с опционална причина
alertBroke=счупени\:
@@ -36,9 +36,9 @@ backAfterDeath=§6Използвайте командата /back, за да с
backCommandDescription=Телепортира ви до вашата локация преди tp/spawn/warp.
backCommandUsage=/<command> [player]
backCommandUsage1=/<command>
backCommandUsage1Description=Телепортира Ви до предишната локация
backCommandUsage1Description=Телепортира ви до предишното ви местоположение
backCommandUsage2=/<command> <player>
backCommandUsage2Description=Телепортира специфичен играч до тяхната предишна локация
backCommandUsage2Description=Телепортира специфичен играч до тяхното предишно местоположение
backOther=§6Върнахте§c {0}§6 до предишното им местоположение.
backupCommandDescription=Прави резервно копие, ако е конфигурирано.
backupCommandUsage=/<command>
@@ -100,6 +100,7 @@ bookCommandUsage3=/<command> title <title>
bookCommandUsage3Description=Задава заглавието на подписана книга
bookLocked=§6Книгата е заключена.
bookTitleSet=§6Заглавието на книгата е зададено на {0}.
bottomCommandDescription=Телепортирайте се до най-ниският блог на текущата ви позиция.
bottomCommandUsage=/<command>
breakCommandDescription=Чупи блока към, който гледате.
breakCommandUsage=/<command>
@@ -156,6 +157,7 @@ commandHelpLine3=§6Употреба(и);
commandHelpLine4=§6Алиас(и)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Командата {0} е грешно заредена.
consoleCannotUseCommand=Тази команда не може да бъде използвата от Конзолата.
compassBearing=§6Посока\: {0} ({1} градуса).
compassCommandDescription=Описва текущото ви държание.
compassCommandUsage=/<command>
@@ -175,7 +177,7 @@ cooldownWithMessage=§4Изчакване\: {0}
coordsKeyword={0}, {1}, {2}
couldNotFindTemplate=§4Не може да се намери шаблон {0}
createdKit=§6Създадохте kit §c{0} §6с §c{1} §6употреби и интервал от §c{2}
createkitCommandDescription=Създава кит от играта\!
createkitCommandDescription=Създава кит в играта\!
createkitCommandUsage=/<command> <kitname> <delay>
createkitCommandUsage1=/<command> <kitname> <delay>
createkitCommandUsage1Description=Създава кит с дадено име и интервал
@@ -240,16 +242,44 @@ discordbroadcastCommandUsage1Description=Изпраща дадено съобщ
discordbroadcastInvalidChannel=§4Дискорд канала §c{0}§4 не съществува.
discordbroadcastPermission=§4Нямаш право да изпраща съобщения до канала §c{0}§4.
discordbroadcastSent=§6Съобщението е изпратно до §c{0}§6\!
discordCommandAccountArgumentUser=Акаунтът в Discord, който да бъде проверен
discordCommandAccountDescription=Проверява свързания Minecraft акаунт за вас или за друг потребител в Discord
discordCommandAccountResponseLinked=Вашият акаунт е свързан към Minecraft акаунта\: **{0}**
discordCommandAccountResponseLinkedOther=Акаунта на {0} е свързан към Minecraft акаунта\: **{1}**
discordCommandAccountResponseNotLinked=Нямате свързан Minecraft акаунт.
discordCommandAccountResponseNotLinkedOther={0} няма свързан Minecraft акаунт.
discordCommandDescription=Изпраща линк на Discord поканата до играча.
discordCommandLink=§6Присъединете се към нашият Discord сървър на §c{0}§6\!
discordCommandUsage=/<command>
discordCommandUsage1=/<command>
discordCommandUsage1Description=Изпраща линк на Discord поканата до играча
discordCommandExecuteDescription=Изпълнява конзолна команда в Minecraft сървъра.
discordCommandExecuteArgumentCommand=Командата, която трябва да бъде изпълнена
discordCommandExecuteReply=Изпълнява се команда\: "/{0}"
discordCommandUnlinkDescription=Развързва текущо свързания Minecraft акаунт към вашия Discord акаунт
discordCommandUnlinkInvalidCode=В момента нямате свързан Minecraft акаунт към вашия Discord акаунт\!
discordCommandUnlinkUnlinked=Вашият Discord акаунт беше развързан от всички свързани Minecraft акаунти.
discordCommandLinkArgumentCode=Кода, предоставен в играта, за свързване на вашия Minecraft акаунт
discordCommandLinkDescription=Свързва вашия Discord акаунт с вашия Minecraft акаунт, използвайки код от командата /link в играта
discordCommandLinkHasAccount=Вече имате свързан акаунт\! За да разваържете текущия си акаунт, напишете /unlink.
discordCommandLinkInvalidCode=Невалиден код за свързване\! Уверете се, че сте изпълнили командата /link в играта и сте копирали кода правилно.
discordCommandLinkLinked=Успешно свързахте вашият акаунт\!
discordCommandListDescription=Показва списък с онлайн потребителите.
discordCommandListArgumentGroup=Конкретна група, чрез която да се намали лимита на търсенето
discordCommandMessageDescription=Изпраща съобщение до играч в Minecraft сървъра.
discordCommandMessageArgumentUsername=Играча, до който да се изпрати съобщението
discordCommandMessageArgumentMessage=Съобщението, което да се изпрати на играча
discordErrorCommand=Добавихте бота си към сървъра си неправилно\! Моля, следвайте ръководството в конфигурацията и добавете бота си, използвайки https\://essentialsx.net/discord.html
discordErrorCommandDisabled=Тази команда е изключена\!
discordErrorLogin=Възникна грешка при влизането в Discord, която причини деактивирането на плъгина\:\n{0}
discordErrorLoggerInvalidChannel=Записването на конзолата в Discord беше деактивирано поради невалидно дефиниран канал\! Ако възнамерявате да го деактивирате, задайте ID-то на канала на "none"; в противен случай, проверете дали ID-то на канала ви е правилно.
discordErrorLoggerNoPerms=Записването на конзолата в Discord беше деактивирано поради липса на достатъчни разрешения\! Моля, уверете се, че вашият бот има разрешението "Manage Webhooks" в сървъра. След като го оправите, изпълнете командата "/ess reload".
discordErrorNoGuild=Невалидно или липсващо ИД на сървъра\! Моля, следвайте ръководството в конфигурацията, за да настроите плъгина правилно.
discordErrorNoGuildSize=Вашият бот не е в никакви сървъри\! Моля, следвайте ръководството в конфигурацията, за да настроите плъгина правилно.
discordErrorNoPerms=Вашият бот не може да вижда или да говори в никой канал\! Моля, уверете се, че ботът има разрешения за четене и писане във всички канали, които желаете да използвате.
discordErrorNoPrimary=Не сте дефинирали основен канал или дефинираният основен канал е невалиден. Връщаме се към основния канал по подразбиране\: \#{0}.
discordErrorNoPrimaryPerms=Вашият бот не може да говори в основния канал, \#{0}. Моля, уверете се, че ботът има разрешения за четене и писане във всички канали, които желаете да използвате.
discordErrorNoToken=Липсва предоставен токен\! Моля, следвайте ръководството в конфигурацията, за да настроите плъгина правилно.
discordLoggingInDone=Успешно сте влезли като {0}
disposal=Кошче
disposalCommandDescription=Отваря преносимо меню за изхвърляне.
@@ -157,6 +157,7 @@ commandHelpLine3=§6Použití\:
commandHelpLine4=§6Alias(y)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Příkaz {0} se nenačetl správně.
consoleCannotUseCommand=Tento příkaz nelze použít na konzoli.
compassBearing=§6Kurs\: {0} ({1} stupňů).
compassCommandDescription=Zobrazuje tvůj aktuální azimut.
compassCommandUsage=/<command>
@@ -621,7 +622,7 @@ jailMessage=§4Provinil ses, tak teď musíš pykat.
jailNotExist=§4Toto vězení neexistuje.
jailNotifyJailed=§6Hráč§c {0} §6uvězněn hráčem §c{1}§6.
jailNotifyJailedFor=§6Hráč§c {0} §6uvězněn za§c {1}§6 hráčem §c{2}§6.
jailNotifySentenceExtended=§6Uvěznění hráče§c{0} §6bylo hráčem §c{2}§6 prodlouženo na §c{1} §6.
jailNotifySentenceExtended=§6Uvěznění hráče §c{0} §6bylo hráčem §c{2}§6 prodlouženo na §c{1}§6.
jailReleased=§6Hráč §c{0}§6 byl propuštěn na svobodu.
jailReleasedPlayerNotify=§6Byl jsi propuštěn na svobodu\!
jailSentenceExtended=§6Uvěznění bylo prodlouženo na §c{0}§6.
@@ -1024,8 +1025,8 @@ recentlyForeverAlone=§4{0} se nedávno odpojil.
recipe=§6Recept pro §c{0}§6 (§c{1}§6 x §c{2}§6)
recipeBadIndex=Recept s takovýmto číslem neexistuje.
recipeCommandDescription=Zobrazuje, jak vyrábět předměty.
recipeCommandUsage=/<command> <předmět> [počet]
recipeCommandUsage1=/<příkaz> <předmět> [strana]
recipeCommandUsage=/<command> <<předmět>|hand> [počet]
recipeCommandUsage1=/<command> <<předmět>|hand> [strana]
recipeCommandUsage1Description=Ukáže, jak vyrobit daný předmět
recipeFurnace=§6Vypal\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -60,6 +60,8 @@ balancetopCommandUsage=/<command> [page]
balancetopCommandUsage1=/<command> [page]
balancetopCommandUsage1Description=Viser den første (eller specificerede) side af de øverste saldoværdier
banCommandDescription=Udelukker en spiller.
banCommandUsage=/<command> <player> [reason]
banCommandUsage1=/<command> <player> [reason]
banCommandUsage1Description=Udelukker den angivne spiller med en valgfri årsag
banExempt=§4Du kan ikke bandlyse den spiller.
banExemptOffline=§4Du kan ikke bandlyse offline spillere.
@@ -67,6 +69,8 @@ banFormat=§4Bandlyst\:\n§r{0}
banIpJoin=Your IP address is banned from this server. Reason\: {0}
banJoin=You are banned from this server. Reason\: {0}
banipCommandDescription=Udelukker en IP adresse.
banipCommandUsage=/<command> <address> [reason]
banipCommandUsage1=/<command> <address> [reason]
banipCommandUsage1Description=Udelukker den angivne IP adresse med en valgfri begrundelse
bed=§obed§r
bedMissing=§4Din seng er enten ikke sat, mangler eller også er den blokeret.
@@ -107,6 +111,7 @@ cantReadGeoIpDB=Fejl ved læsning af GeoIP databasen\!
cantSpawnItem=§4Du har ikke tilladelse til at spawne denne ting§c {0}§4.
cartographytableCommandDescription=Åbner en kartografisk tabel.
cartographytableCommandUsage=/<command>
chatTypeLocal=§3[L]
chatTypeSpy=[Spion]
cleaned=Brugerfiler blev renset.
cleaning=Renser brugerfiler.
@@ -338,6 +343,8 @@ jailSet=§6Fængslet§c {0} §6er sat.
jailsCommandUsage=/<command>
jumpCommandUsage=/<command>
jumpError=§4Det ville såre din computers hjerne.
kickCommandUsage=/<command> <player> [reason]
kickCommandUsage1=/<command> <player> [reason]
kickDefault=Smidt ud fra serveren.
kickedAll=§4Smed alle ud fra serveren.
kickExempt=§4Du kan ikke smide den person ud.
@@ -157,6 +157,7 @@ commandHelpLine3=§6Verwendung(en)\:
commandHelpLine4=§6Alias(e)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Befehl {0} ist nicht richtig geladen.
consoleCannotUseCommand=&cDieser Befehl kann nur per Konsole ausgeführt werden.
compassBearing=§6Peilung\: {0} ({1} Grad).
compassCommandDescription=Beschreibt deine momentane Haltung.
compassCommandUsage=/<command>
@@ -1024,8 +1025,6 @@ recentlyForeverAlone=§4{0} ging vor kurzem Offline.
recipe=§6Rezept für §c{0}§5 (§c{1}§6 von §c{2}§6)
recipeBadIndex=Es gibt kein Rezept mit dieser Nummer.
recipeCommandDescription=Zeigt, wie man Gegenstände herstellt.
recipeCommandUsage=/<command> <gegenstand> [nummer]
recipeCommandUsage1=/<command> <Gegenstand> [Seite]
recipeCommandUsage1Description=Zeigt an, wie der Gegenstand gecraftet werden kann
recipeFurnace=§6Schmelzen\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -1244,6 +1243,7 @@ teleportationDisabledWarning=§6Du musst Teleportation aktivieren, bevor andere
teleportationEnabled=§6Teleportation §caktiviert§6.
teleportationEnabledFor=§6Teleportation für §c{0} aktiviert§6.
teleportAtoB=§c{0}§6 teleportiert dich zu {1}§6.
teleportBottom=§6Nach unten teleportieren.
teleportDisabled=§c{0} §4verweigert die Teleportation.
teleportHereRequest=§c{0}§6 fragt, ob du dich zu ihm teleportieren möchtest.
teleportHome=§6Teleportiere zu §c{0}§6.
@@ -157,6 +157,7 @@ commandHelpLine3=§6Usage(s);
commandHelpLine4=§6Aliases(s)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Command {0} is improperly loaded.
consoleCannotUseCommand=This command cannot be used by Console.
compassBearing=§6Bearing\: {0} ({1} degrees).
compassCommandDescription=Describes your current bearing.
compassCommandUsage=/<command>
@@ -1024,8 +1025,8 @@ recentlyForeverAlone=§4{0} recently went offline.
recipe=§6Recipe for §c{0}§6 (§c{1}§6 of §c{2}§6)
recipeBadIndex=There is no recipe by that number.
recipeCommandDescription=Displays how to craft items.
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage=/<command> <<item>|hand> [number]
recipeCommandUsage1=/<command> <<item>|hand> [page]
recipeCommandUsage1Description=Displays how to craft the given item
recipeFurnace=§6Smelt\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -157,6 +157,7 @@ commandHelpLine3=§6Usage(s)\:
commandHelpLine4=§6Aliases(s)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Command {0} is improperly loaded.
consoleCannotUseCommand=This command cannot be used by Console.
compassBearing=§6Bearing\: {0} ({1} degrees).
compassCommandDescription=Describes your current bearing.
compassCommandUsage=/<command>
@@ -1024,8 +1025,8 @@ recentlyForeverAlone=§4{0} recently went offline.
recipe=§6Recipe for §c{0}§6 (§c{1}§6 of §c{2}§6)
recipeBadIndex=There is no recipe by that number.
recipeCommandDescription=Displays how to craft items.
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage=/<command> <<item>|hand> [number]
recipeCommandUsage1=/<command> <<item>|hand> [page]
recipeCommandUsage1Description=Displays how to craft the given item
recipeFurnace=§6Smelt\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -1254,6 +1255,7 @@ teleportationDisabledWarning=§6You must enable teleportation before other playe
teleportationEnabled=§6Teleportation §cenabled§6.
teleportationEnabledFor=§6Teleportation §cenabled §6for §c{0}§6.
teleportAtoB=§c{0}§6 teleported you to §c{1}§6.
teleportBottom=§6Teleporting to bottom.
teleportDisabled=§c{0} §4has teleportation disabled.
teleportHereRequest=§c{0}§6 has requested that you teleport to them.
teleportHome=§6Teleporting to §c{0}§6.
@@ -1269,6 +1271,7 @@ teleportRequestTimeoutInfo=§6This request will timeout after§c {0} seconds§6.
teleportTop=§6Teleporting to top.
teleportToPlayer=§6Teleporting to §c{0}§6.
teleportOffline=§6The player §c{0}§6 is currently offline. You are able to teleport to them using /otp.
teleportOfflineUnknown=§6Unable to find the last known position of §c{0}§6.
tempbanExempt=§4You may not tempban that player.
tempbanExemptOffline=§4You may not tempban offline players.
tempbanJoin=You are banned from this server for {0}. Reason\: {1}
@@ -1457,6 +1460,9 @@ userIsAwaySelf=§7You are now AFK.
userIsAwaySelfWithMessage=§7You are now AFK.
userIsNotAwaySelf=§7You are no longer AFK.
userJailed=§6You have been jailed\!
usermapEntry=§c{0} §6is mapped to §c{1}§6.
usermapPurge=§6Checking for files in userdata that are not mapped, results will be logged to console. Destructive Mode\: {0}
usermapSize=§6Current cached users in user map is §c{0}§6/§c{1}§6/§c{2}§6.
userUnknown=§4Warning\: The user ''§c{0}§4'' has never joined this server.
usingTempFolderForTesting=Using temp folder for testing\:
vanish=§6Vanish for {0}§6\: {1}
@@ -157,6 +157,7 @@ commandHelpLine3=§6Uso(s);
commandHelpLine4=§6Alias\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4El comando {0} no está cargado correctamente.
consoleCannotUseCommand=Este comando no puede usarse por Consola.
compassBearing=§6Orientación\: {0} ({1} grados).
compassCommandDescription=Describe tu rumbo actual.
compassCommandUsage=/<command>
@@ -1024,8 +1025,6 @@ recentlyForeverAlone=§4{0} recently went offline.
recipe=§6Receta para §c{0}§6 (§c{1}§6 de §c{2}§6)
recipeBadIndex=No hay ningún crafteo con ese número.
recipeCommandDescription=Muestra como craftear items.
recipeCommandUsage=/<command> <item> [número]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage1Description=Muestra como crear el objeto dado
recipeFurnace=§6Fundir\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -100,6 +100,7 @@ bookCommandUsage3=/<käsklus> title <pealkiri>
bookCommandUsage3Description=Määrab kirjutatud raamatu pealkirja
bookLocked=§6See raamat on nüüd lukus.
bookTitleSet=§6Raamatu pealkirjaks on määratud "{0}".
bottomCommandDescription=Teleporteeruge praeguse asukoha madalaimale plokile.
bottomCommandUsage=/<command>
breakCommandDescription=Lõhub vaadatava ploki.
breakCommandUsage=/<käsklus>
@@ -156,6 +157,7 @@ commandHelpLine3=§6Kasutus(ed);
commandHelpLine4=§6Alias(ed)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Käsklus {0} on sobimatult laetud.
consoleCannotUseCommand=Seda käsku ei saa kasutada konsool.
compassBearing=§6Suund\: {0} ({1} kraadi).
compassCommandDescription=Kirjeldab sinu asukohta kompassil.
compassCommandUsage=/<käsklus>
@@ -241,6 +243,7 @@ discordbroadcastCommandUsage1Description=Saadab antud sõnumi määratud Discord
discordbroadcastInvalidChannel=§4Discordi kanalit §c{0}§4 ei eksisteeri.
discordbroadcastPermission=§4Teil pole luba §c{0}§4 kanalile sõnumeid saata.
discordbroadcastSent=§6Sõnum saadetud kanalisse §c{0}§6\!
discordCommandAccountResponseNotLinked=Sul ei ole seotud Minecrafti kontot.
discordCommandDescription=Saadab discordi kutse lingi mängijale.
discordCommandLink=§6Liitu meie Discordi serveriga §c{0}§6\!
discordCommandUsage=/<käsklus>
@@ -249,11 +252,13 @@ discordCommandUsage1Description=Saadab discordi kutse lingi mängijale
discordCommandExecuteDescription=Täidab Minecrafti serveris konsoolikäsu.
discordCommandExecuteArgumentCommand=Käivitatav käsklus
discordCommandExecuteReply=Käskluse käivitamine\: "/{0}"
discordCommandLinkLinked=Konto edukalt seotud\!
discordCommandListDescription=Hangib võrgumängijate nimekirja.
discordCommandListArgumentGroup=Konkreetne rühm, mille järgi otsingut piirata
discordCommandMessageDescription=Saadab sõnumeid Minecrafti serveris olevale mängijale.
discordCommandMessageArgumentUsername=Mängija, kellele sõnum saata
discordCommandMessageArgumentMessage=Sõnum, mis tuleb mängijale saata
discordErrorCommand=Lisasite oma boti oma serverisse valesti. Järgige konfiguratsioonis toodud õpetust ja lisage oma bot, kasutades https\://essentialsx.net/discord.html
discordErrorCommandDisabled=See käsklus on keelatud\!
discordErrorLogin=Discordi sisselogimisel ilmnes viga, mis põhjustas pistikprogrammi enda keelamise\:\n{0}
discordErrorLoggerInvalidChannel=Discordi konsooli logimine on keelatud kanali definitsiooni tõttu\! Kui kavatsete selle keelata, määrake kanali ID-ks "puudub"; muul juhul kontrollige, kas teie kanali ID on õige.
@@ -968,8 +973,6 @@ recentlyForeverAlone=§4Mängija {0} läks hiljuti võrgust välja.
recipe=§6Retsept esemele §c{0}§6 (§c{1}§6/§c{2}§6)
recipeBadIndex=Selle arvuga retsepti ei leitud.
recipeCommandDescription=Kuvab, kuidas esemeid meisterdada.
recipeCommandUsage=/<käsklus> <ese> [number]
recipeCommandUsage1=/<käsklus> <ese> [lk]
recipeCommandUsage1Description=Näitab kuidas meisterdada antud eset
recipeFurnace=§6Sulata\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -776,7 +776,6 @@ recentlyForeverAlone=§4{0} meni äskettäin offline-tilaan.
recipe=§6Resepti tavaralle §c{0}§6 (§c{1}§6 / §c{2}§6)
recipeBadIndex=Tuolla numerolla ei ole reseptiä.
recipeCommandDescription=Näyttää, miten rakennetaan tavaroita.
recipeCommandUsage=/<command> <item> [number]
recipeFurnace=§6Sulatettu\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
recipeGridItem=§c{0}X §6on §c{1}
@@ -693,8 +693,6 @@ realName=§f{0}§r§6 is §f{1}
realnameCommandUsage=/<command> <nickname>
realnameCommandUsage1=/<command> <nickname>
recentlyForeverAlone=§4Naging offline lang si {0}.
recipeCommandUsage=/<command> <item> [numero]
recipeCommandUsage1=/<command> <item> [pahina]
recipeNothing=wala
removeCommandUsage=<command><all|tamed|named|drops|arrows|boats|minecarts|xp|paintings|itemframes|endercrystals|monsters|animals|ambient|mobs|[uri ng mundo]> [radyus|mundo]
repairCommandUsage=/<command> [hand|all]
@@ -100,6 +100,7 @@ bookCommandUsage3=/<command> title <titre>
bookCommandUsage3Description=Définit le titre d''un livre signé
bookLocked=§cCe livre est désormais scellé.
bookTitleSet=§6Le titre du livre est maintenant {0}.
bottomCommandDescription=Se téléporter vers le bloc le plus haut, de votre position actuelle.
bottomCommandUsage=/<command>
breakCommandDescription=Casse le bloc que vous regardez.
breakCommandUsage=/<command>
@@ -1023,8 +1024,6 @@ recentlyForeverAlone=§4{0} s''est récemment déconnecté(e).
recipe=§6Recette pour §c{0}§6 (§c{1}§6 sur §c{2}§6)
recipeBadIndex=Il n''y a pas de recette pour ce numéro.
recipeCommandDescription=Affiche la recette de fabrication de l''objet spécifié.
recipeCommandUsage=/<command> <objet> [nombre]
recipeCommandUsage1=/<command> <objet> [page]
recipeCommandUsage1Description=Affiche la recette de fabrication de l''objet donné
recipeFurnace=§6Faire fondre \: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -1253,6 +1252,7 @@ teleportationDisabledWarning=§6Vous devez activer la téléportation avant que
teleportationEnabled=§6Téléportation §cactivée§6.
teleportationEnabledFor=§6Téléportation §cactivée §6pour §c{0}§6.
teleportAtoB=§c{0}§6 vous a téléporté à §c{1}§6.
teleportBottom=§6Téléportation vers le bas.
teleportDisabled={0} a la téléportation désactivé.
teleportHereRequest=§c{0}§6 vous a envoyé une demande pour vous téléporter à lui/elle.
teleportHome=§6Téléportation vers §c{0}§6.
@@ -100,6 +100,7 @@ bookCommandUsage3=/<command> כותרת <title>
bookCommandUsage3Description=קובע את הכותרת של ספר חתום
bookLocked=§6 ספר זה נעול.
bookTitleSet=§6 כותרת הספר נקבע ל {0}.
bottomCommandDescription=השתגר לבלוק הנמוך ביותר במיקום שלך.
bottomCommandUsage=/<command>
breakCommandDescription=שובר את הבלוק שאתם מסתכלים עליו.
breakCommandUsage=/<command>
@@ -156,6 +157,7 @@ commandHelpLine3=§6שימוש(ים);
commandHelpLine4=§6כינוי(ם)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=\ {0} פקודה {0} לא נטענה כמו שצריך.
consoleCannotUseCommand=הפקודה הזאת אינה מאופשרת לשימוש דרך הקונסולה.
compassBearing=§6נושא\: {0} ({1} מעלות).
compassCommandDescription=מציג את הכיוון הנוכחי שלך.
compassCommandUsage=/<command>
@@ -240,6 +242,7 @@ discordbroadcastCommandUsage1Description=שולח את ההודעה הנתונה
discordbroadcastInvalidChannel=ערוץ §4דיסקורד §c{0}§4 אינו קיים.
discordbroadcastPermission=§4אין לך הרשאה לשלוח הודעות לערוץ הזה §c{0}§4.
discordbroadcastSent=§6ההודעה נשלחה אל §c{0}§6\!
discordCommandAccountArgumentUser=משתמש הדיסקורד לחיפוש
discordCommandAccountDescription=מחפש את משתמש המיינקראפט המחובר בשבילך או בשביל משתמש דיסקורד אחר
discordCommandAccountResponseLinked=המשתמש שלך מחובר למשתמש המיינקראפט\: **{0}**
discordCommandAccountResponseLinkedOther=המשתמש של {0} מחובר למשתמש המיינקראפט\: **{1}**
@@ -278,6 +281,7 @@ discordErrorNoPrimary=לא הגדרתם ערוץ ראשי או שהערוץ הר
discordErrorNoPrimaryPerms=הבוט שלכם לא יכול לדבר בערוץ הראשי שלכם, \#{0}. אנא ודאו שלבוט שלכם יש הרשאות קריאה וכתיבה בכל הערוצים שבהם ברצונכם להשתמש.
discordErrorNoToken=אין לבוט token\! אנא עקובו אחר המדריך ההגדרה כדי להגדיר את הפלאגין.
discordErrorWebhook=אירעה שגיאה בעת שליחת הודעות לערוץ הקונסולה שלכם\! זה כנראה נגרם על ידי מחיקה בטעות של ה-webhook של הקונסולה שלכם. אפשר לתקן את זה, פשוט מאוד הגדירו מחדש את ההרשאות "Manage Webhooks" והריצו את הפקודה "\\ess reload".
discordLinkInvalidGroup=קבוצה לא מאופשרת {0} קיבלה את התפקיד {1}. הקבוצות הבאות מאופשרות\: {2}
discordLoggingIn=מנסה להיכנס לדיסקורד...
discordLoggingInDone=נכנס בהצלחה בתור {0}
discordMailLine=**אימייל חדש מ{0}\:** {1}
@@ -357,6 +361,7 @@ expCommandUsage1Description=נותן לשחקן היעד את כמות ה-אקס
expCommandUsage2=\\<command> set <playername> <amount>
expCommandUsage2Description=מגדיר את ה-אקספי של שחקן שצוין אם כמות האקספי שצוינה
expCommandUsage3=\\<command> show <playername>
expCommandUsage4Description=מציג את הכמות של האקס פי שנמצא בבעלות השחקן
expCommandUsage5=\\<command> reset <playername>
expCommandUsage5Description=מאפס את כמות האקס פי של השחקן ל 0
expSet=\n§c{0} §6יש כעת§c {1} §6exp.\n
@@ -370,6 +375,7 @@ failedToCreateConfig=\nשגיאה בניסיון ליצור את קובץ הקו
failedToWriteConfig=שגיעה בעת כתיבה ל Config
false=לא נכון
feed=\n§6הרעב שלך התמלא.\n
feedCommandDescription=השבע את הרעב.
feedCommandUsage=שחקן
feedCommandUsage1=שחקן
feedCommandUsage1Description=מאכיל את עצמך או שחקן אחר, אם צוין
@@ -377,6 +383,7 @@ feedOther=\n§6מילאת את הרעב של §c{0}§6.\n
fileRenameError=\nשינוי שם של הקובץ {0} נכשל\!\n
fireballCommandUsage=\\<command> [fireball|small|large|arrow|skull|egg|snowball|expbottle|dragon|splashpotion|lingeringpotion|trident] [speed]
fireballCommandUsage1=/<command>
fireballCommandUsage1Description=זורק כדור אש רגיל מהמיקום שלך
fireballCommandUsage2=\\<command> <fireball|small|large|arrow|skull|egg|snowball|expbottle|dragon|splashpotion|lingeringpotion|trident> [speed]
fireworkColor=\n§4הנתונים של הזיקוק שהוכנו שגויים, עליך לבחור צבע קודם.\n
fireworkCommandUsage=\\<command> <<meta param>|power [amount]|clear|fire [amount]>
@@ -411,13 +418,17 @@ gcfree=§6 זיכרון פנוי\:§c {0} MB.
gcmax=§6 זיכרון מקסימלי\:§c {0} MB.
gctotal=§6 זיכרון מוקצה\:§c {0} MB.
gcWorld=§6{0} "§c{1}§6"\: חלקים §c{2}§6, ישויות §c{3}§6, צ''אנקים§c{4}§6.
geoipJoinFormat=השחקן6§ {0}c§ מגיע מ6§ {1}c§.
getposCommandDescription=השג את הקודינטות שלך או של שחקן מסוים.
getposCommandUsage=שחקן
getposCommandUsage1=שחקן
getposCommandUsage1Description=משיג את הקודינטות שלך או של שחקן אחר אם צוין
giveCommandDescription=מביא לשחקן פריט מסוים.
giveCommandUsage=\\<command> <player> <item|numeric> [amount [itemmeta...]]
giveCommandUsage1=/<command> <player> <item> [amount]
giveCommandUsage1Description=מביא לשחקן שצוין 64 (או הכמות שצויינה) מהפריט שצוין
giveCommandUsage2=\\<command> <player> <item> <amount> <meta>
godCommandDescription=מפעיל את הכוחות האגדיים שלך.
godCommandUsage=\\<command> [player] [on|off]
godCommandUsage1=שחקן
godDisabledFor=בוטלc& ל6& {0} c&
@@ -726,8 +737,6 @@ rCommandUsage=\\<command> <message>
rCommandUsage1=\\<command> <message>
realnameCommandUsage=\\<command> <nickname>
realnameCommandUsage1=\\<command> <nickname>
recipeCommandUsage=\\<command> <item> [number]
recipeCommandUsage1=\\<command> <item> [page]
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
recipeGridItem=§c{0}X §6הוא §c{1}
recipeNothing=שום דבר
@@ -875,7 +875,6 @@ recentlyForeverAlone=§4{0} nemrég offline.
recipe=§6A(z) §c{0}§6 receptje ({1} az {2}-ből)
recipeBadIndex=Ehhez a számhoz nincs recept.
recipeCommandDescription=Megjeleníti hogyan kell tárgyakat barkácsolni.
recipeCommandUsage=/<command> <tárgy> [szám]
recipeFurnace=§c{0} §6kiégetése.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
recipeGridItem=§c{0}X §6is §c{1}
@@ -1117,6 +1117,7 @@ serverTotal=§6Totale Server\:§c {0}
serverUnsupported=Stai utilizzando una versione server non supportata\!
serverUnsupportedClass=Stato che determina la classe\: {0}
serverUnsupportedCleanroom=Stai eseguendo un server che non supporta correttamente i plugin Bukkit che si basano sul codice Mojang interno. Considera di utilizzare un sostituto di Essentials per il tuo software server.
serverUnsupportedDangerous=Stai eseguendo un fork server che è noto per essere estremamente pericoloso e può portare alla perdita di dati. Si consiglia vivamente di passare a un software server più stabile come Paper.
serverUnsupportedLimitedApi=Stai eseguendo un server con API limitate. EssentialsX funzionerà ancora, ma alcune funzionalità potrebbero essere disabilitate.
serverUnsupportedDumbPlugins=Stai usando plugin noti per causare gravi problemi con EssentialsX e altri plugin.
serverUnsupportedMods=Stai eseguendo un server che non supporta correttamente i plugin di Bukkit. I plugin Bukkit non devono essere usati con le mod Forge/Fabric\! Per Forge\: Considera di usare ForgeEssentials, o SpongeForge + Nucleo.
@@ -996,8 +996,6 @@ recentlyForeverAlone=§4{0} は最近オフラインになりました
recipe=§c{0} §6のレシピです§6 (§c{1}§6 から §c{2}§6)
recipeBadIndex=その数字にレシピはありません。
recipeCommandDescription=アイテムのクラフト方法を表示します。
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage1Description=指定したアイテムのクラフトレシピを表示します
recipeFurnace=§6精錬\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -100,6 +100,7 @@ bookCommandUsage3=/<command> title <책 제목>
bookCommandUsage3Description=책의 제목을 설정합니다.
bookLocked=§6이 책은 잠긴상태로 전환되었습니다.
bookTitleSet=§6책의 제목을 §c{0}§6으로 설정합니다.
bottomCommandDescription=현재 위치에서 가장 낮은 블록으로 텔레포트합니다.
bottomCommandUsage=/<command>
breakCommandDescription=바라보고 있는 블록을 부숩니다.
breakCommandUsage=/<command>
@@ -156,6 +157,7 @@ commandHelpLine3=§6사용법(s);
commandHelpLine4=§6별칭\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§c 명령어 {0}를 잘못 불러왔습니다.
consoleCannotUseCommand=이 명령어는 콘솔에서 사용할 수 없습니다.
compassBearing=§6방위\: {0} ({1} 도).
compassCommandDescription=현재 방위를 보여줍니다.
compassCommandUsage=/<command>
@@ -258,6 +260,10 @@ discordCommandExecuteReply=명령어를 실행합니다\: "/{0}"
discordCommandUnlinkDescription=현재 연동된 Discord 계정에서 Minecraft 계정의 연동을 해제해요
discordCommandUnlinkInvalidCode=현재 Discord에 연동된 Minecraft 계정이 없어요\!
discordCommandUnlinkUnlinked=내 Discord 계정이 모든 Minecraft 계정에서 연동 해제됐어요.
discordCommandLinkArgumentCode=게임 내에서 제공된 Minecraft 계정을 연동하기 위한 코드
discordCommandLinkDescription=코드를 사용하여 디스코드 계정과 마인크래프트 계정을 연동\n/link 커맨드
discordCommandLinkHasAccount=이미 연동된 계정이 있습니다\! 연동을 해제하려면, /unlink 를 입력하세요.
discordCommandLinkInvalidCode=코드가 잘못되었습니다\! 게임 내 /link 커맨드를 사용하여 올바른 코드를 복사하세요.
discordCommandLinkLinked=계정을 성공적으로 연결했습니다\!
discordCommandListDescription=현재 접속중인 플레이어 목록을 표시합니다.
discordCommandListArgumentGroup=검색을 제한할 그룹
@@ -276,8 +282,12 @@ discordErrorNoPrimary=우선 채널을 정하지 않았거나 정한 우선 채
discordErrorNoPrimaryPerms=디스코드 봇이 우선 채널(\#{0})을 보거나 우선 채널에서 대화할 수 없습니다. 디스코드 봇에게 당신이 사용하고자 하는 채널에서 읽거나 쓸 수 있는 권한을 주었는지 확인하세요.
discordErrorNoToken=디스코드 봇 토큰이 설정되지 않았습니다\! 설정 파일에 명시된 튜토리얼대로 플러그인을 올바르게 설치해주세요.
discordErrorWebhook=콘솔 채널에 메세지를 보내는데 실패했습니다. 이러한 오류는 보통 콘솔 채널에서 웹후크를 삭제한 경우 발생합니다. 이러한 경우, 봇이 "웹후크 관리하기" 권한이 있는지 확인한 후, "/ess reload" 명령어를 실행함으로서 오류를 해결할 수 있습니다.
discordLinkInvalidGroup={1} 역할에 잘못된 {0} 그룹이 제공되었습니다. 다음 그룹을 사용할 수 있습니다\: {2}
discordLinkInvalidRole=잘못된 역할 아이디 ({0}) 가 그룹({1}) 에 제공되었습니다. 역할 아이디는 디스코드내 /roleinfo 커맨드로 확인하실 수 있습니다.
discordLinkUnlinked=§6연결된 모든 디스코드 계정에서 마인크래프트 계정을 연결 해제했습니다.
discordLoggingIn=디스코드에 로그인 하는 중...
discordLoggingInDone={0}로 성공적으로 로그인함
discordMailLine=**{0} 님으로부터 새 메일\: ** {1}
discordNoSendPermission=\#{0} 채널에 메시지를 보내는데에 실패했습니다. 봇이 해당 채널에서 "메시지 보내기" 권한을 갖고 있는지 확인하세요\!
discordReloadInvalid=EssentialsX Discord 플러그인이 잘못 설정된 상태에서 플러그인의 설정을 다시 불러오려 했습니다\! 만약 설정 파일을 수정했다면, 서버를 재시작해주세요.
disposal=폐기
@@ -498,8 +508,10 @@ homeSet=§6이곳을 집으로 설정하였습니다.
hour=시간
hours=시(시간)
ice=§6당신은 더 추워짐을 느낍니다..
iceCommandDescription=플레이어를 얼립니다.
iceCommandUsage=/<command> [플레이어]
iceCommandUsage1=/<command>
iceCommandUsage1Description=오한이 듭니다
iceCommandUsage2=/<command> <플레이어>
iceCommandUsage2Description=한 플래이어를 식힘.
iceCommandUsage3=/<command> *
@@ -983,8 +995,6 @@ recentlyForeverAlone=§4{0} (은)는 최근 접속을 종료했습니다.
recipe=§c{0}§6 (§c{2}§6의 §c{1}§6) 의 조합법
recipeBadIndex=그 번호에 대한 레시피가 존재하지 않습니다.
recipeCommandDescription=아이템 조합 방법을 표시합니다.
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage1Description=주어진 아이템의 제작법을 표시합니다.
recipeFurnace=§6제련\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -1199,6 +1209,7 @@ teleportationDisabledWarning=§6다른 플레이어가 당신에게 텔레포트
teleportationEnabled=§6텔레포트가 §c활성화§6되었습니다.
teleportationEnabledFor=§c{0}§6 에 대한 이동이 허가되었습니다.
teleportAtoB=§c{0}§6 가 §c{1}§6 에게 이동 하였습니다.
teleportBottom=§6바닥으로 내려갔습니다.
teleportDisabled=§c{0}§4에 대한 텔레포트는 비활성화 된 상태입니다,
teleportHereRequest=§c{0}§c 는 요청을 받아들였습니다.
teleportHome=§c{0}§6로 이동 합니다.
@@ -851,8 +851,6 @@ rCommandUsage=/<command> <message>
rCommandUsage1=/<command> <message>
realnameCommandUsage=/<command> <nickname>
realnameCommandUsage1=/<command> <nickname>
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
removeCommandUsage=/<command> <all|tamed|named|drops|arrows|boats|minecarts|xp|paintings|itemframes|endercrystals|monsters|animals|ambient|mobs|[mobType]> [radius|world]
removeCommandUsage1=/<command> <mob type> [world]
removeCommandUsage2=/<command> <mob type> <radius> [world]
@@ -985,8 +985,6 @@ recentlyForeverAlone=§4{0} recently went offline.
recipe=§6Receptas už §c {0} §6(§c{2} §c{1})
recipeBadIndex=There is no recipe by that number.
recipeCommandDescription=Parodo kaip gaminti daiktus.
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage1Description=Rodo, kaip sukurti nurodytą daiktą
recipeFurnace=§6Kepti\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -757,7 +757,6 @@ recentlyForeverAlone=§4{0} nesen devās bezsaistē.
recipe=§6Recepte §c{0}§6 (§c{1}§6 no §c{2}§6)
recipeBadIndex=Pēc šī numura nav nevienas receptes.
recipeCommandDescription=Parāda, kā veidot priekšmetus.
recipeCommandUsage=/<command> <item> [number]
recipeFurnace=§6Kausēt\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
recipeGridItem=§c{0}X §6ir §c{1}
@@ -100,6 +100,7 @@ bookCommandUsage3=/<command> titel <title>
bookCommandUsage3Description=Verandert de titel van een ondertekend boek
bookLocked=§cDit boek is nu vergrendeld.
bookTitleSet=§6Titel van het boek is veranderd naar\: {0}
bottomCommandDescription=Teleporteer naar het laagste blok op je huidige locatie.
bottomCommandUsage=/<command>
breakCommandDescription=Breekt het blok waar je naar kijkt.
breakCommandUsage=/<command>
@@ -156,6 +157,7 @@ commandHelpLine3=§6Gebruik;
commandHelpLine4=§6Aliassen\: §f{0}
commandHelpLineUsage={0} §6{1}
commandNotLoaded=§cOpdracht {0} is fout geladen.
consoleCannotUseCommand=Deze opdracht kan niet worden gebruikt vanuit de console.
compassBearing=§6Richting\: {0} ({1} graden).
compassCommandDescription=Beschrijft je huidige richting.
compassCommandUsage=/<command>
@@ -241,6 +243,12 @@ discordbroadcastCommandUsage1Description=Stuurt een gegeven bericht naar het geg
discordbroadcastInvalidChannel=§4Discord-kanaal §c{0} §4bestaat niet.
discordbroadcastPermission=§4Je hebt geen toestemming om berichten naar het §c{0}§4 kanaal te sturen.
discordbroadcastSent=§6Bericht verzonden naar §c{0}§6\!
discordCommandAccountArgumentUser=Het Discord account om op te zoeken
discordCommandAccountDescription=Zoekt de gekoppelde Minecraft-account van jezelf of een andere Discord-gebruiker op
discordCommandAccountResponseLinked=Je account is gekoppeld aan het Minecraft account\: **{0}**
discordCommandAccountResponseLinkedOther=Het account van {0} is gekoppeld aan het Minecraft account\: **{1}**
discordCommandAccountResponseNotLinked=Je hebt geen gekoppeld Minecraft-account.
discordCommandAccountResponseNotLinkedOther={0} heeft geen gekoppeld Minecraft account.
discordCommandDescription=Stuurt de Discord-uitnodingslink naar de speler.
discordCommandLink=§6Word lid van onze Discord-server\: §c{0}§6\!
discordCommandUsage=/<command>
@@ -249,6 +257,11 @@ discordCommandUsage1Description=Stuurt de Discord-uitnodingslink naar de speler
discordCommandExecuteDescription=Voert een consolecommando uit op de Minecraft server.
discordCommandExecuteArgumentCommand=Het commando om uit te voeren
discordCommandExecuteReply=Commando aan het uitvoeren\: "/{0}"
discordCommandUnlinkDescription=Ontkoppelt het Minecraft-account dat gekoppeld is aan je Discord account
discordCommandUnlinkInvalidCode=Je hebt momenteel geen Minecraft-account gekoppeld aan Discord\!
discordCommandUnlinkUnlinked=Je Discord account is ontkoppeld van alle Minecraft gekoppelde accounts.
discordCommandLinkArgumentCode=De code die in-game is verstrekt om uw Minecraft account te koppelen
discordCommandLinkDescription=Koppelt je Discord-account met je Minecraft-account met een code van de in-game /link opdracht
discordCommandListDescription=Toont een lijst met online spelers.
discordCommandListArgumentGroup=Een specifieke groep om je zoekopdracht te beperken
discordCommandMessageDescription=Stuurt een bericht naar een speler op de Minecraft server.
@@ -614,6 +627,7 @@ leatherSyntax=§6Leerkleur Syntaxis\:§c color\:<rood>,<groen>,<blauw> voorbeeld
lightningCommandDescription=De kracht van Thor. Raak de cursor of de speler met bliksem.
lightningCommandUsage=/<command> [speler] [kracht]
lightningCommandUsage1=/<command> [speler]
lightningCommandUsage2=/<command> <speler> <kracht>
lightningSmited=§6Gij zijt getroffen\!
lightningUse=§c{0}§6 wordt getroffen door bliksem.
linkCommandUsage=/<command>
@@ -633,6 +647,10 @@ loomCommandUsage=/<command>
mailClear=§6Om je mail te markeren als gelezen, typ§c /mail clear§6.\n
mailCleared=§6Mails verwijderd\!
mailCommandDescription=Beheert interplayer, intra-server mail.
mailCommandUsage1=/<command> read [pagina]
mailCommandUsage2=/<command> clear [nummer]
mailCommandUsage3=/<command> send <speler> <bericht>
mailCommandUsage4=/<command> sendall <bericht>
mailDelay=Er zijn teveel mails verzonden in een minuut. Het maximale aantal mails\: {0}
mailFormat=§6[§r{0}§6] §r{1}
mailMessage={0}
@@ -648,6 +666,7 @@ mayNotJailOffline=§4Je mag geen spelers in de gevangenis zetten wanneer zij off
meCommandDescription=Beschrijf een actie in de context van de speler.
meCommandUsage=/<command> <beschrijving>
meCommandUsage1=/<command> <beschrijving>
meCommandUsage1Description=Beschrijf een actie
meSender=ik
meRecipient=ik
minimumBalanceError=§4Het minimale saldo dat een gebruiker kan hebben is {0}.
@@ -711,6 +730,9 @@ nickChanged=Bijnaam veranderd.
nickCommandDescription=Verander je bijnaam of die van een andere speler.
nickCommandUsage=/<command> [speler] <bijnaam|off>
nickCommandUsage1=/<command> <bijnaam>
nickCommandUsage2=/<command> off
nickCommandUsage3=/<command> <speler> <bijnaam>
nickCommandUsage4=/<command> <speler> off
nickDisplayName=§4U moet ''change-displayname'' inschakelen in de Essentials configuratie.
nickInUse=§cDie naam is al in gebruik.
nickNameBlacklist=§4Die bijnaam is niet toegestaan.
@@ -873,7 +895,6 @@ recentlyForeverAlone=§4{0} is kort geleden offline gegaan.
recipe=§6Recept voor §c{0}§6 (§c{1}§6 van §c{2}§6)
recipeBadIndex=Er is geen recept met dat nummer.
recipeCommandDescription=Geeft vervaardigingsinstructies weer.
recipeCommandUsage=/<command> <voorwerp> [nummer]
recipeFurnace=§6Smelt\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
recipeGridItem=§c{0}X §6is §c{1}
@@ -905,7 +905,6 @@ recentlyForeverAlone=§4{0} logget nylig ut.
recipe=§6Oppskrift på §c{0}§6 (§c{1}§6 av §c{2}§6)
recipeBadIndex=Det er ingen oppskrift på det tallet.
recipeCommandDescription=Viser hvordan du lager gjenstander.
recipeCommandUsage=/<command> <gjenstand> [nummer]
recipeCommandUsage1Description=Viser hvordan man lager den angitte gjenstanden
recipeFurnace=§6Smelting\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -157,6 +157,7 @@ commandHelpLine3=§6Zastosowanie\:
commandHelpLine4=§7Alias(-y)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Polecenie {0} jest niewłaściwie załadowane.
consoleCannotUseCommand=To polecenie nie może być wykonywane przez konsolę.
compassBearing=§6Namiar\: {0} ({1} stopni).
compassCommandDescription=Opisuje twój aktualny namiar.
compassCommandUsage=/<command>
@@ -1024,8 +1025,6 @@ recentlyForeverAlone=§4{0} niedawno wszedł w tryb offline.
recipe=§6Receptura dla §c{0}§6 ({1} z {2})
recipeBadIndex=Nie ma receptury dla tego numeru.
recipeCommandDescription=Wyświetla jak wytwarzać przedmioty.
recipeCommandUsage=/<command> <item> [numer]
recipeCommandUsage1=/<command> <item> [strona]
recipeCommandUsage1Description=Wyświetla jak wytwarzać dany item
recipeFurnace=§6Przepal §c{0}
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -980,8 +980,6 @@ recentlyForeverAlone=§4{0} saiu recentemente do servidor.
recipe=§6Receita para §c {0} §6 (§6 §c {1} de §c {2} §6)
recipeBadIndex=Não existe nenhuma receita com esse número.
recipeCommandDescription=Mostra como criar itens.
recipeCommandUsage=/<command> <item> [número]
recipeCommandUsage1=/<command> <item> [página]
recipeCommandUsage1Description=Mostra como criar o item especificado
recipeFurnace=§6Fundir\:§c {0}.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -157,6 +157,7 @@ commandHelpLine3=§6Uso(s)\:
commandHelpLine4=§6Atalho(s)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4O comando {0} está carregado incorretamente.
consoleCannotUseCommand=Este comando não pode ser usado no Console.
compassBearing=§6Apontando para\: {0} ({1} graus).
compassCommandDescription=Indica a direção cardeal para qual você está olhando.
compassCommandUsage=/<command>
@@ -1024,8 +1025,8 @@ recentlyForeverAlone=§4{0} recently went offline.
recipe=§6Receita para §c {0} §6 (§6 §c {1} de §c {2} §6)
recipeBadIndex=Não há receita para esse numero.
recipeCommandDescription=Exibe como fazer os itens.
recipeCommandUsage=/<command> <item> [número]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage=/<command> <item>|hand> [número]
recipeCommandUsage1=/<command> <item>|hand> [página]
recipeCommandUsage1Description=Mostra como fabricar um item determinado
recipeFurnace=§6Fundir\:§c {0}.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -27,7 +27,7 @@ antiochCommandDescription=Небольшой сюрприз для операт
antiochCommandUsage=/<command> [сообщение]
anvilCommandDescription=Открывает наковальню.
anvilCommandUsage=/<command>
autoAfkKickReason=Вы были кикнуты за бездействие более {0} минут.
autoAfkKickReason=Вы были выкинуты с сервера за бездействие более {0} минут.
autoTeleportDisabled=§6Вы больше не принимаете запросы на телепортацию автоматически.
autoTeleportDisabledFor=§c{0}§6 больше не принимает запросы на телепортацию автоматически.
autoTeleportEnabled=§6Теперь вы принимаете запросы на телепортацию автоматически.
@@ -45,7 +45,7 @@ backupCommandUsage=/<command>
backupDisabled=§4Внешний скрипт резервного копирования не был настроен.
backupFinished=§6Резервное копирование завершено.
backupStarted=§6Резервное копирование начато.
backupInProgress=§6В данный момент выполняется скрипт внешнего резервного копирования\! Отключение плагина недоступно до завершения процесса.
backupInProgress=§6Выполняется скрипт внешнего резервного копирования\! Отключение плагина недоступно до завершения процесса.
backUsageMsg=§6Возвращение на прежнюю локацию.
balance=§aБаланс\:§c {0}
balanceCommandDescription=Отображает текущий баланс игрока.
@@ -157,6 +157,7 @@ commandHelpLine3=§6Использование\:
commandHelpLine4=§6Альтернативы\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Команда {0} загружена неправильно.
consoleCannotUseCommand=Эту команду нельзя использовать в консоли.
compassBearing=§6Азимут\: {0} ({1} градусов).
compassCommandDescription=Описывает вашу текущую локацию.
compassCommandUsage=/<command>
@@ -515,7 +516,7 @@ homeSet=§6Точка дома установлена.
hour=час
hours=часов
ice=§6Вы чувствуете себя намного холоднее...
iceCommandDescription=Охлаждает игрока
iceCommandDescription=Охлаждает игрока.
iceCommandUsage=/<command> [игрок]
iceCommandUsage1=/<command>
iceCommandUsage1Description=Охлаждает вас
@@ -912,12 +913,12 @@ paytoggleCommandUsage1Description=Переключает, принимаете
pendingTeleportCancelled=§4Запрос на телепортацию отменен.
pingCommandDescription=Понг\!
pingCommandUsage=/<command>
playerBanIpAddress=§6Игрок§c {0} §6забанил IP-адрес§c {1} §6за\: §c{2}§6.
playerTempBanIpAddress=§6Игрок§c {0} §6временно забанил IP-адрес §c{1}§6 на §c{2}§6\: §c{3}§6.
playerBanned=§6Игрок§c {0} §6забанил§c {1} §6за §c{2}§6.
playerBanIpAddress=§c{0} §6забанил IP-адрес§c {1} §6за\: §c{2}§6.
playerTempBanIpAddress=§c{0} §6временно забанил IP-адрес §c{1}§6 на §c{2}§6\: §c{3}§6.
playerBanned=§c{0} §6забанил§c {1} §6за §c{2}§6.
playerJailed=§6Игрок§c {0} §6посажен в тюрьму.
playerJailedFor=§6Игрок§c {0} §6посажен в тюрьму на§c {1}§6.
playerKicked=§6Игрок§c {0} §6выкинул§c {1}§6 за§c {2}§6.
playerKicked=§c{0} §6выкинул с сервера§c {1}§6 за§c {2}§6.
playerMuted=§6Вы были заглушены\!
playerMutedFor=§6Вы были заглушены на§c {0}§6.
playerMutedForReason=§6Вы были заглушены на§c {0}§6. Причина\: §c{1}
@@ -925,8 +926,8 @@ playerMutedReason=§6Вы были заглушены\! Причина\: §c{0}
playerNeverOnServer=§4Игрока§c {0} §4никогда не было на сервере.
playerNotFound=§4Игрок не найден.
playerTempBanned=§6Игрок §c{0}§6 временно забанил §c{1}§6 на §c{2}§6\: §c{3}§6.
playerUnbanIpAddress=§6Игрок§c {0} §6разбанил IP-адрес§c {1}
playerUnbanned=§6Игрок§c {0} §6разбанил§c {1}
playerUnbanIpAddress=§c{0} §6разбанил IP-адрес§c {1}
playerUnbanned=§c{0} §6разбанил§c {1}
playerUnmuted=§6Вы снова можете писать в чат.
playtimeCommandDescription=Показывает проведенное игроком время в игре.
playtimeCommandUsage=/<command> [игрок]
@@ -1024,8 +1025,8 @@ recentlyForeverAlone=§4{0} недавно вышел.
recipe=§6Рецепт §c{0}§6 (§c{1}§6 из §c{2}§6)
recipeBadIndex=Рецепта под этим номером не найдено.
recipeCommandDescription=Показывает рецепты предметов.
recipeCommandUsage=/<command> <предмет> [номер]
recipeCommandUsage1=/<command> <предмет> [номер]
recipeCommandUsage=/<command> <<предмет>|hand> [номер]
recipeCommandUsage1=/<command> <<предмет>|hand> [номер]
recipeCommandUsage1Description=Показывает, как создать указанный предмет
recipeFurnace=§6Жарить в печи\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -1130,7 +1131,7 @@ sethomeCommandUsage1=/<command> <название>
sethomeCommandUsage1Description=Устанавливает дом с заданным названием на вашем месте
sethomeCommandUsage2=/<command> <игрок>\:<название>
sethomeCommandUsage2Description=Устанавливает дом указанного игрока с заданным названием на вашем месте
setjailCommandDescription=Создает тюрьму с названием, указанным в аргументе [тюрьма].
setjailCommandDescription=Создает тюрьму с указанным названием.
setjailCommandUsage=/<command> <тюрьма>
setjailCommandUsage1=/<command> <тюрьма>
setjailCommandUsage1Description=Устанавливает тюрьму с указанным названием на вашем месте
@@ -1306,7 +1307,7 @@ timeWorldAdd=§6Время сдвинуто вперёд на§c {0} §6в\: §c
timeWorldCurrent=§6Tекущее время в мире§c {0} §6- §c{1}§6.
timeWorldCurrentSign=§6Текущее время §c{0}§6.
timeWorldSet=§6Время установлено на§c {0} §6в\: §c{1}§6.
togglejailCommandDescription=Сажает и телепортирует игрока в указанную тюрьму, или выводит из неё.
togglejailCommandDescription=Сажает и телепортирует игрока в указанную тюрьму, или высвобождает из неё.
togglejailCommandUsage=/<command> <игрок> <тюрьма> [длительность]
toggleshoutCommandDescription=Переключает режим возгласа вашего чата.
toggleshoutCommandUsage=/<command> [игрок] [on|off]
@@ -1332,7 +1333,7 @@ tpaallCommandDescription=Запрашивает всех онлайн игрок
tpaallCommandUsage=/<command> <игрок>
tpaallCommandUsage1=/<command> <игрок>
tpaallCommandUsage1Description=Отправляет всем игрокам запрос на телепортацию к вам
tpacancelCommandDescription=Отменяет все исходящие запросы на телепорт. Укажите [игрок] для отмены запросов к конкретному игроку.
tpacancelCommandDescription=Отменяет все исходящие запросы на телепорт. Укажите игрока для отмены запросов к тому.
tpacancelCommandUsage=/<command> [игрок]
tpacancelCommandUsage1=/<command>
tpacancelCommandUsage1Description=Отменяет все ваши запросы на телепортацию
@@ -1504,7 +1505,7 @@ warpCommandUsage2=/<command> <варп> [игрок]
warpCommandUsage2Description=Телепортирует вас или указанного игрока в заданный варп
warpDeleteError=§4Ошибка при удалении варпа.
warpInfo=§6Информация о варпе\:§c {0}§6\:
warpinfoCommandDescription=Отображает информцию об указанном варпе.
warpinfoCommandDescription=Отображает информацию об указанном варпе.
warpinfoCommandUsage=/<command> <варп>
warpinfoCommandUsage1=/<command> <варп>
warpinfoCommandUsage1Description=Предоставляет информацию об указанном варпе
@@ -36,9 +36,9 @@ backAfterDeath=§6Použi príkaz§c /back§6 pre návrat na miesto smrti.
backCommandDescription=Teleportuje ťa na miesto pred posledným tp/spawn/warp.
backCommandUsage=/<command> [hráč]
backCommandUsage1=/<command>
backCommandUsage1Description=Teleportuje ťa na tvoju predošlú lokácii
backCommandUsage1Description=Teleportuje ťa na tvoju predošlú polohu
backCommandUsage2=/<command> <hráč>
backCommandUsage2Description=Teleportuje hráča na jeho predchádzajúce miesto
backCommandUsage2Description=Teleportuje hráča na jeho predchádzajúcu polohu
backOther=§6Hráč§c {0}§6 bol vrátený na predošlú polohu.
backupCommandDescription=Spustí zálohovanie, ak je nakonfigurované.
backupCommandUsage=/<command>
@@ -60,11 +60,11 @@ balanceTopLine={0}, {1}, {2}
balancetopCommandDescription=Zobrazí hodnoty najväčších účtov.
balancetopCommandUsage=/<command> [strana]
balancetopCommandUsage1=/<command> [strana]
balancetopCommandUsage1Description=Zobrazí prvú (alebo špecifikovanú) stranu najvyšších zostatkov
balancetopCommandUsage1Description=Zobrazí prvú (alebo zadanú) stranu najvyšších zostatkov
banCommandDescription=Udelí hráčovi ban.
banCommandUsage=/<command> <hráč> [dôvod]
banCommandUsage1=/<command> <hráč> [dôvod]
banCommandUsage1Description=Zabanuje hráča s voliteľným dôvodom
banCommandUsage1Description=Udelí hráčovi ban s voliteľným dôvodom
banExempt=§4Tomuto hráčovi nemôžeš dať ban.
banExemptOffline=§4Nemôžeš dať ban offline hráčovi.
banFormat=§cDostal si ban\:\n§r{0}
@@ -73,7 +73,7 @@ banJoin=Na tomto serveri máš ban. Dôvod\: {0}
banipCommandDescription=Zablokuje IP adresu.
banipCommandUsage=/<command> <adresa> [dôvod]
banipCommandUsage1=/<command> <adresa> [dôvod]
banipCommandUsage1Description=Zabanuje IP s voliteľným dôvodom
banipCommandUsage1Description=Udelí IP adrese ban s voliteľným dôvodom
bed=§oposteľ§r
bedMissing=§4Tvoja posteľ je buď nenastavená, zablokovaná, alebo zničená.
bedNull=§mposteľ§r
@@ -86,7 +86,7 @@ bigTreeSuccess=§6Veľký strom vytvorený.
bigtreeCommandDescription=Zasaď obrovský strom tam, kam sa pozeráš.
bigtreeCommandUsage=/<command> <tree|redwood|jungle|darkoak>
bigtreeCommandUsage1=/<command> <tree|redwood|jungle|darkoak>
bigtreeCommandUsage1Description=Vytvorí veľký strom určeného typu
bigtreeCommandUsage1Description=Vytvorí veľký strom zadaného typu
blockList=§6EssentialsX prenáša nasledujúce príkazy na iné pluginy\:
blockListEmpty=§6EssentialsX neprenáša žiadne príkazy na iné pluginy.
bookAuthorSet=§6Autor knihy nastavený na {0}.
@@ -108,11 +108,11 @@ broadcast=§6[§4Oznam§6]§a {0}
broadcastCommandDescription=Vyšle správu celému serveru.
broadcastCommandUsage=/<command> <správa>
broadcastCommandUsage1=/<command> <správa>
broadcastCommandUsage1Description=Vysiela danú správu na celý server
broadcastCommandUsage1Description=Vyšle zadanú správu pre celý server
broadcastworldCommandDescription=Vyšle správu do sveta.
broadcastworldCommandUsage=/<command> <svet> <správa>
broadcastworldCommandUsage1=/<command> <svet> <správa>
broadcastworldCommandUsage1Description=Vysiela danú správu do určeného sveta
broadcastworldCommandUsage1Description=Vyšle zadanú správu do zadaného sveta
burnCommandDescription=Zapáli hráča.
burnCommandUsage=/<command> <hráč> <sekundy>
burnCommandUsage1=/<command> <hráč> <sekundy>
@@ -139,9 +139,9 @@ clearinventoryCommandUsage=/<command> [hráč|*] [predmet[\:<dáta>]|*|**] [poč
clearinventoryCommandUsage1=/<command>
clearinventoryCommandUsage1Description=Vymaže všetky predmety v tvojom inventári
clearinventoryCommandUsage2=/<command> <hráč>
clearinventoryCommandUsage2Description=Vymaže všetky predmety z inventára určeného hráča
clearinventoryCommandUsage2Description=Vymaže všetky predmety z inventára zadaného hráča
clearinventoryCommandUsage3=/<command> <hráč> <predmet> [množstvo]
clearinventoryCommandUsage3Description=Vymaže všetky (alebo určené množstvo) daného predmetu z inventára určeného hráča
clearinventoryCommandUsage3Description=Vymaže všetky (alebo zadané množstvo) daného predmetu z inventára zadaného hráča
clearinventoryconfirmtoggleCommandDescription=Zapína/vypína nutnosť potvrdenia vyčistenia inventára.
clearinventoryconfirmtoggleCommandUsage=/<command>
commandArgumentOptional=§7
@@ -157,6 +157,7 @@ commandHelpLine3=§6Použitie\:
commandHelpLine4=§6Alias(y)\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Príkaz {0} je nesprávne načítaný.
consoleCannotUseCommand=Tento príkaz nemôže použiť Konzola.
compassBearing=§6Kurz\: {0} ({1} stupňov).
compassCommandDescription=Vypíše tvoj aktuálny azimut.
compassCommandUsage=/<command>
@@ -165,7 +166,7 @@ condenseCommandUsage=/<command> [predmet]
condenseCommandUsage1=/<command>
condenseCommandUsage1Description=Zhustí všetky predmety v tvojom inventári
condenseCommandUsage2=/<command> <predmet>
condenseCommandUsage2Description=Zhustí špecifikovaný predmet v tvojom inventári
condenseCommandUsage2Description=Zhustí zadaný predmet v tvojom inventári
configFileMoveError=Nepodarilo sa premiestniť config.yml do zálohy.
configFileRenameError=Nepodarilo sa premenovať dočasný súbor na config.yml.
confirmClear=§7Pre §lPOTVRDENIE§7 vyprázdnenia inventára zopakuj príkaz\: §6{0}
@@ -242,8 +243,8 @@ discordbroadcastCommandUsage1Description=Odošle správu zadanému Discord kaná
discordbroadcastInvalidChannel=§4Discord kanál §c{0}§4 neexistuje.
discordbroadcastPermission=§4Nemáš povolenie posielať správy do kanálu §c{0}§4.
discordbroadcastSent=§6Správa odoslaná do kanálu §c{0}§6\!
discordCommandAccountArgumentUser=Vyhľadanie Discord účtu
discordCommandAccountDescription=Vyhľadá prepojený Minecraft účet pre seba alebo iného Discord používateľa
discordCommandAccountArgumentUser=Discord účet, ktorý sa má vyhľadať
discordCommandAccountDescription=Vyhľadá tvoj prepojený Minecraft účet, alebo účet iného Discord používateľa
discordCommandAccountResponseLinked=Tvoj účet je prepojený s Minecraft účtom\: **{0}**
discordCommandAccountResponseLinkedOther=Účet {0} je prepojený s Minecraft účtom\: **{1}**
discordCommandAccountResponseNotLinked=Nemáš prepojený Minecraft účet.
@@ -256,7 +257,7 @@ discordCommandUsage1Description=Odošle hráčovi pozvánku na Discord
discordCommandExecuteDescription=Spustí konzolový príkaz na Minecraft serveri.
discordCommandExecuteArgumentCommand=Príkaz ktorý bude vykonaný
discordCommandExecuteReply=Vykonáva sa príkaz\: "/{0}"
discordCommandUnlinkDescription=Odpojí Minecraft účet, ktorý je momentálne prepojený s vaším Discord účtom
discordCommandUnlinkDescription=Odpojí Minecraft účet, ktorý je momentálne prepojený s tvojím Discord účtom
discordCommandUnlinkInvalidCode=Momentálne nemáš Minecraft účet prepojený s Discordom\!
discordCommandUnlinkUnlinked=Tvoj Discord účet bol odpojený od všetkých súvisiacich Minecraft účtov.
discordCommandLinkArgumentCode=Poskytnutý kód v hre na prepojenie tvojho Minecraft účtu
@@ -283,7 +284,7 @@ discordErrorNoToken=Token nebol zadaný. Postupuj podľa inštrukcií v konfigur
discordErrorWebhook=Pri odosielaní správ do tvojho konzolového kanála sa vyskytla chyba. Pravdepodobne to bolo spôsobené neúmyselným vymazaním tvojho konzolového webhooku. Uisti sa, že tvoj bot má právo "Spravovať webhooky" a následne použi príkaz "/ess reload".
discordLinkInvalidGroup=Pre rolu {1} bola poskytnutá neplatná skupina {0}. K dispozícii sú nasledujúce skupiny\: {2}
discordLinkInvalidRole=Pre skupinu\: {1} bolo poskytnuté neplatné ID roly, {0}. ID rolí môžeš vidieť pomocou príkazu /roleinfo v Discorde.
discordLinkInvalidRoleInteract=Rola {0} ({1}) sa nedá použiť na synchronizáciu skupina->rola, pretože je nad najvyššou rolou tvojho bota. Presuň rolu bota nad "{0}" alebo "{0}" pod rolu bota.
discordLinkInvalidRoleInteract=Rola {0} ({1}) sa nedá použiť na synchronizáciu skupina->rola, pretože je nad najvyššou rolou tvojho bota. Presuň rolu bota nad "{0}" alebo presuň "{0}" pod rolu bota.
discordLinkInvalidRoleManaged=Rola {0} ({1}) sa nedá použiť na synchronizáciu skupina->rola, pretože ju spravuje iný bot alebo integrácia.
discordLinkLinked=§6Ak chceš prepojiť svoj Minecraft účet s Discordom, napíš §c{0} §6na Discord serveri.
discordLinkLinkedAlready=§6Svoj Discord účet si už prepojil/a\! Ak chceš zrušiť prepojenie tvojho Discord účtu, použi §c/unlink§6.
@@ -1024,8 +1025,8 @@ recentlyForeverAlone=§4{0} išiel nedávno offline.
recipe=§6Recept pre §c{0}§6 (§c{1}§6 x §c{2}§6)
recipeBadIndex=Recept s takýmto číslom neexistuje.
recipeCommandDescription=Zobrazí, ako vyrábať predmety.
recipeCommandUsage=/<command> <predmet> [počet]
recipeCommandUsage1=/<command> <predmet> [strana]
recipeCommandUsage=/<command> <<predmet>|hand> [počet]
recipeCommandUsage1=/<command> <<predmet>|hand> [strana]
recipeCommandUsage1Description=Zobrazí ako vyrobiť daný predmet
recipeFurnace=§6Vypáľ\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -242,6 +242,12 @@ discordbroadcastCommandUsage1Description=Skickar det inmatade meddelandet till d
discordbroadcastInvalidChannel=§4Det finns ingen Discord-kanal som heter §c{0}§4.
discordbroadcastPermission=§4Du har inte behörighet att skicka meddelanden i Discord-kanalen §c{0}§4.
discordbroadcastSent=§6Meddelandet skickades till §c{0}§6\!
discordCommandAccountArgumentUser=Discord kontot för att slå upp
discordCommandAccountDescription=Söker upp det länkade Minecraft kontot för dig själv eller en annan Discord användare
discordCommandAccountResponseLinked=Ditt konto är kopplat till Minecraft kontot\: **{0}**
discordCommandAccountResponseLinkedOther={0} konto är kopplat till Minecraft kontot\: **{1}**
discordCommandAccountResponseNotLinked=Du har inte ett länkat Minecraft konto.
discordCommandAccountResponseNotLinkedOther={0} har inte ett länkat Minecraft konto.
discordCommandDescription=Skickar Discord-serverns inbjudningslänk till spelaren.
discordCommandLink=§6Gå med i vår Discord-server här\: §c{0}§6\!
discordCommandUsage=/<command>
@@ -6,8 +6,11 @@ action=§5* {0} §5{1}
addedToAccount=§a{0} ถูกเพิ่มเข้าบัญชีของคุณ
addedToOthersAccount=§a{0} ถูกเพิ่มเข้าบัญชีของ {1} จำนวนเงินในบัญชีล่าสุด\: {2}
adventure=โหมดผจญภัย
afkCommandUsage=/<command> [ชื่อผู้เล่น/ข้อความ...]
afkCommandUsage1=/<command> [message]
afkCommandUsage1Description=ปรับสถานะ afk ด้วยเหตุผลเพิ่มเติม
afkCommandUsage2=/<command> <player> [message]
afkCommandUsage2Description=ปรับสถานะ afk ของผู้เล่นที่ระบุพร้อมกับเหตุผลเพิ่มเติม
alertBroke=ทำลายบล็อค\:
alertFormat=§3 [{0}] §r {1} §6 {2} โดย\: {3}
alertPlaced=วางบล็อค\:
@@ -19,6 +22,7 @@ antiBuildDrop=§4คุณยังไม่ได้รับอนุญาต
antiBuildInteract=§4คุณยังไม่ได้รับอนุญาตให้ใช้งาน§c {0}§4.
antiBuildPlace=§4คุณยังไม่ได้รับอนุญาตให้วาง§c {0} §4ที่นี้.
antiBuildUse=§4คุณยังไม่ได้รับอนุญาตให้ใช้งาน§c {0}§4
antiochCommandDescription=เซอร์ไพร์สเล็กๆ สำหรับผู้ดูแล
antiochCommandUsage=/<command> [message]
anvilCommandUsage=/<command>
autoAfkKickReason=คุณถูกเตะเนื่องจากอยู่นิ่งเกิน {0} นาที
@@ -27,19 +31,28 @@ autoTeleportDisabledFor=§c{0}§6 จะไม่ตอบรับคำขอ
autoTeleportEnabled=§6คุณจะตอบรับคำขอเทเลพอร์ตอัตโนมัติ
autoTeleportEnabledFor=§c{0}§6 จะตอบรับคำขอเทเลพอร์ตอัตโนมัติ
backAfterDeath=§6พิมพ์ /back เพื่อกลับไปยังจุดที่คุณตายล่าสุด
backCommandDescription=เทเลพอร์ตคุณไปยังตำแหน่งก่อนใช้งาน tp/spawn/warp.
backCommandUsage=/<command> [player]
backCommandUsage1=/<command>
backCommandUsage1Description=เทเลพอร์ตคุณไปยังตำแหน่งก่อนหน้า
backCommandUsage2Description=เทเลพอร์ตผู้เล่นที่ระบุไปยังตำแหน่งก่อนหน้า
backOther=§6เทเลพอร์ต§c {0}§6 ไปยังตำแหน่งก่อนหน้า
backupCommandDescription=เริ่มการสำรองข้อมูลถ้ากำหนดค่าแล้ว
backupCommandUsage=/<command>
backupDisabled=§aHEXCore\: §7§oไม่มีการกำหนดค่าสคริปต์ของระบบสำรองข้อมูล
backupFinished=§6สำรองข้อมูลเสร็จสิ้น
backupStarted=§6เริ่มสำรองข้อมูล
backUsageMsg=§6คุณได้กลับมายังตำแหน่งล่าสุด
balance=§aBalance\:§c {0}\n
balanceCommandDescription=ระบุยอดเงินปัจจุบันของผู้เล่น
balanceCommandUsage=/<command> [player]
balanceCommandUsage1=/<command>
balanceCommandUsage1Description=ระบุยอดเงินปัจจุบันของคุณ
balanceCommandUsage2Description=ระบุยอดเงินปัจจุบันของผู้เล่นที่ระบุ
balanceOther=§aยอดเงินในบัญชีของ {0}§aคือ §c {1}
balanceTop=§7อันดับคนที่รวยที่สุดภายในเซิฟเวอร์§f\:\n§a(§c{0}§a)
balanceTopLine={0}. {1}, {2}
balancetopCommandDescription=เรียกดูผู้ที่มียอดเงินสูงสุด
balancetopCommandUsage=/<command> [หน้า]
balancetopCommandUsage1=/<command> [หน้า]
banCommandDescription=แบนผู้เล่น
@@ -50,7 +50,9 @@ balance=§aBakiye\:§c {0}
balanceCommandDescription=Bir oyuncunun şimdiki bakiyesini gösterir.
balanceCommandUsage=/<komut> [oyuncu]
balanceCommandUsage1=/<komut>
balanceCommandUsage1Description=Mevcut bakiyeni görüntüler
balanceCommandUsage2=/<komut> <oyuncu>
balanceCommandUsage2Description=Belirtilen oyuncunun bakiyesini görüntüler
balanceOther=§a{0} §aBakiyesi\:§c {1}
balanceTop=§6Bakiye sıralaması ({0})
balanceTopLine={0}. {1}, {2}
@@ -212,6 +214,11 @@ disabledToSpawnMob=§4Bu mobun oluşturulması konfigürasyon dosyasından devre
disableUnlimited=§c {1} §6isimli eşyanın §c {0}§6 için sınırsız yerleştirilmesi devre dışı bırakıldı.
discordCommandUsage=/<komut>
discordCommandUsage1=/<komut>
discordCommandExecuteArgumentCommand=Çalıştırılacak komut
discordCommandExecuteReply="/{0}" komutu çalıştırılıyor
discordCommandUnlinkDescription=Şu anda Minecraft hesabına bağlı olan Discord hesabını kaldırır
discordCommandListDescription=Çevrimiçi olan oyuncuların bir listesini gösterir.
discordErrorCommandDisabled=Bu komut devre dışı\!
disposal=Tasfiye
disposalCommandDescription=Sanal çöp menüsü açar.
disposalCommandUsage=/<komut>
@@ -738,7 +745,6 @@ recentlyForeverAlone=§4{0} az önce çevrimdışı oldu.
recipe=§c{0} §6için tarif gösteriliyor (§c{1}§6/§c{2}§6)
recipeBadIndex=Bu sayıda bir tarif bulunamadı.
recipeCommandDescription=Öğelerin nasıl yapılacağını gösterir.
recipeCommandUsage=/<komut> <öğe> [numara]
recipeFurnace=§6Pişirilmiş\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
recipeGridItem=\ §{0}X §6 -> §c{1}
@@ -1024,8 +1024,6 @@ recentlyForeverAlone=§4{0} нещодавно перейшов оффлайн.
recipe=§6Рецепт для §c{0}§6 (§c{1}§6 із §c{2}§6)
recipeBadIndex=Немає рецепту для цього предмета.
recipeCommandDescription=Показує як створити предмети.
recipeCommandUsage=/<command> <предмет> [number]
recipeCommandUsage1=/<command> <предмет> [page]
recipeCommandUsage1Description=Показує як створити вказаний предмет
recipeFurnace=§6Переплавити\: §c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -98,6 +98,7 @@ bookCommandUsage3=/<command> title <title>
bookCommandUsage3Description=Đặt tiêu đề cho quyển sách đã được ký
bookLocked=§6Quyển sách này đã bị khóa.
bookTitleSet=§6Tiêu để của quyền sách được đặt thành {0}.
bottomCommandDescription=Dịch chuyển đến khối thấp nhất tại vị trí của bạn.
bottomCommandUsage=/<command>
breakCommandDescription=Phá vỡ khối nơi bạn đang nhìn.
breakCommandUsage=/<command>
@@ -152,6 +153,7 @@ commandHelpLine3=§6Sử dụng;
commandHelpLine4=§6Bí danh\: §f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4Lệnh {0} không chính xác.
consoleCannotUseCommand=Lệnh này chỉ có thể dùng bởi người chơi.
compassBearing=§6Hướng\: {0} ({1} độ).
compassCommandDescription=Mô tả phương hướng hiện tại của bạn.
compassCommandUsage=/<command>
@@ -277,10 +279,17 @@ discordErrorNoPrimaryPerms=Bot của bạn không thể nói trong kênh chính,
discordErrorNoToken=Không có token nào được cung cấp\! Vui lòng làm theo hướng dẫn trong config để thiết lập plugin.
discordErrorWebhook=Đã xảy ra lỗi khi gửi tin nhắn đến channel console của bạn\! Điều này có thể được gây ra bởi vô tình xóa webhook console của bạn. Điều này thường có thể được khắc phục bằng cách đảm bảo bot của bạn có quyền "Quản lý Webhook" và chạy "/ess reload".
discordLinkInvalidGroup=Nhóm {0} không hợp lệ đã được cung cấp cho vai trò {1}. Có các nhóm sau\: {2}
discordLinkInvalidRole=Một ID không hợp lệ {0}, được cấp bởi nhóm\: {1}. Bạn có thể xem ID của vai trò với lệnh /roleinfo trên Discord.
discordLinkLinked=§6Để liên kết tài khoản Minecraft của bạn với Discord, hãy nhập §c{0} §6 vào máy chủ Discord.
discordLinkLinkedAlready=§6Bạn đã liên kết tài khoản Discord của mình\! Nếu bạn muốn hủy liên kết tài khoản Discord của mình, sử dụng §c/unlink§6.
discordLinkLoginKick=§6Bạn phải liên kết tài khoản Discord của mình trước khi bạn có thể vào máy chủ này\n§6Để liên kết tài khoản Minecraft của bạn tới Discord, nhập\:\n§c{0}\n§6vào trong máy chủ Discord của máy chủ này\:\n§c{1}
discordLinkLoginPrompt=§6Bạn cần phải liên kết tài khoản Discord của bạn trước khi bạn có thể di chuyển, trò chuyện hoặc tương tác với máy chủ. Để liên kết tài khoản Minecraft tới Discord, nhập §c{0} §6vào trong máy chủ Discord của máy chủ này\: §c{1}
discordLinkNoAccount=§6Bạn không có tài khoản Discord nào đang liên kết với tài khoản Minecraft của bạn.
discordLinkPending=§6Bạn đã có mã liên kết. Để hoàn thành việc liên kết tài khoản Minecraft của bạn tới Discord, nhập §c{0} §6vào trong máy chủ Discord.
discordLinkUnlinked=§6Hủy liên kết tài khoản Minecraft của bạn khỏi toàn bộ tài khoản Discord liên quan tới.
discordLoggingIn=Đang cố gắng đăng nhập vào Discord...
discordLoggingInDone=Đăng nhập thành công với tên đăng nhập {0}
discordMailLine=**Thư mới từ {0}\:** {1}
discordNoSendPermission=Không thể gửi tin nhắn trong kênh\: \#{0} Hãy đảm bảo bot có quyền "Gửi tin nhắn" trong kênh đó\!
discordReloadInvalid=Đã cố gắng reload cấu hình EssentialsX Discord trong khi plugin ở trạng thái không hợp lệ\! Nếu bạn đã sửa đổi config của mình, khởi động lại server của bạn.
disposal=Xếp đặt
@@ -558,12 +567,15 @@ itemloreInvalidItem=§4Bạn cần cầm một vật phẩm để chỉnh sửa
itemloreNoLine=§4Vật phẩm bạn cầm không có lore trên dòng §c{0}§4.
itemloreNoLore=§4Vật phẩm bạn cầm không có bất kỳ dòng lore nào.
itemloreSuccess=§6Bạn đã thêm "§c{0}§6" vào lore của vật phẩm bạn cầm.
itemloreSuccessLore=§6Bạn đã đặt dòng §c{0}§6 của vật phẩm của bạn thành "§c{1}§6".
itemMustBeStacked=§4Vật phẩm đổi được phải đầy. Một số lượng đầy hơn nó sẽ thành hai, v.v....
itemNames=§6Tên thu gọn\:§r {0}
itemnameClear=§6Bạn đã xóa tên vật phẩm này.
itemnameCommandDescription=Đặt tên cho một vật phẩm.
itemnameCommandUsage1=/<command>
itemnameCommandUsage1Description=Xóa tên của vật phẩm đang cầm
itemnameCommandUsage2=/<command> <name>
itemnameCommandUsage2Description=Đặt tên của vật phẩm thành văn bản đã cho
itemnameInvalidItem=§cBạn phải giữ vật phẩm trên tay để đổi tên.
itemnameSuccess=§6Bạn đã đổi tên vật phẩm đang giữ thành "§c{0}§6".
itemNotEnough1=§4Bạn không có đủ vật phẩm để bán.
@@ -577,25 +589,36 @@ itemSold=§aĐã bán được §c{0} §a({1} {2} với {3} mỗi cái).
itemSoldConsole=§e{0} §ađã bán§e {1}§a cho §e{2} §a({3} vật phẩm với {4} mỗi cái).
itemSpawn=§6Cho§c {0} §6cái§c {1}
itemType=§6Vật phẩm\:§c {0}
itemdbCommandDescription=Tìm kiếm một vật phẩm.
itemdbCommandUsage=/<command> <item>
itemdbCommandUsage1=/<command> <item>
jailAlreadyIncarcerated=§4Người này đã bị giam\:§c {0}
jailList=§6Jails\:§r {0}
jailMessage=§4Bạn phạm tội, bạn bị phạt tù.
jailNotExist=§4Nhà tù đó không tồn tại.
jailNotifyJailed=§6Người chơi §c {0} §6đã bị giam bởi §c{1}.
jailReleased=§6Người chơi §c{0}§6 đã được thả.
jailReleasedPlayerNotify=§6Bạn đã được thả\!
jailSentenceExtended=§6Thời gian bị bắt giam kéo dài đến §c{0}§6.
jailSet=§6Ngục§c {0} §6đã được thiết lập.
jailsCommandDescription=Danh sách nhà tù.
jailsCommandUsage=/<command>
jumpCommandUsage=/<command>
jumpError=§4Điều này sẽ tổn thương bộ não của máy tính bạn đấy.
kickCommandDescription=Đá người chơi được chỉ định với lý do.
kickCommandUsage=/<command> <player> [reason]
kickCommandUsage1=/<command> <player> [reason]
kickCommandUsage1Description=Đá người chơi với lý do bạn muốn
kickDefault=Đá khỏi máy chủ.
kickedAll=§4Đá tất cả người chơi ra khỏi máy chủ.
kickExempt=§4Bạn không thể đá người chơi này.
kickallCommandDescription=Đá tất cả người chơi ra khỏi máy chủ trừ người ra lệnh.
kickallCommandUsage=/<command> [reason]
kickallCommandUsage1=/<command> [reason]
kickallCommandUsage1Description=Đá tất cả người chơi với lý do bạn muốn
kill=§6Đã giết§c {0}§6.
killCommandDescription=Giết người chơi cụ thể.
killCommandUsage1Description=Giết người chơi được chỉ định
killExempt=§4Bạn không thể giết §c{0}§4.
kitCommandUsage1=/<command>
kitContains=§6Bộ dụng cụ §c{0} §6bao gồm\:
@@ -680,17 +703,20 @@ months=tháng
moreCommandDescription=Làm đầy stack vật phẩm trong tay đến số lượng đã chỉ định hoặc đến kích thước tối đa nếu không có kích thước nào được chỉ định.
moreThanZero=§4Số lượng phải lớn hơn 0.
moveSpeed=§6Đặt tốc độ§c {0}§6 thành§c {1} §6trong §c{2}§6.
msgCommandDescription=Gửi tin nhắn riêng cho người chơi được chỉ định.
msgDisabled=§6Đã §ctắt§6 chế độ nhận thư.
msgDisabledFor=§6Đã §ctắt §6chế độ nhận thư cho §c{0}§6.
msgEnabled=§6Đã §cbật§6 chế độ nhận thư.
msgEnabledFor=§6Đã §cbật §6chế độ nhận thư cho §c{0}§6.
msgFormat=§6[§c{0}§6 -> §c{1}§6] §r{2}
msgIgnore=§c{0} §4đã tắt trò chuyện riêng.
msgtoggleCommandDescription=Chặn tất cả các tin nhắn riêng tư.
msgtoggleCommandUsage=/<command> [player] [on|off]
msgtoggleCommandUsage1=/<command> [người chơi]
msgtoggleCommandUsage1Description=Bật tắt bay cho chính bạn hoặc người chơi khác nếu được chỉ định
multipleCharges=§4Bạn không thể thêm nhiều hơn 1 việc cho pháo hoa này.
multiplePotionEffects=§4Bạn không thể đặt nhiều hơn một hiệu ứng cho thuốc này.
muteCommandDescription=Tắt tiếng hoặc bỏ tắt tiếng một người chơi.
mutedPlayer=§6Người chơi§c {0} §6đã bị cấm trò chuyện.
mutedPlayerFor=§6Người chơi§c {0} §6bị cấm trò chuyện trong§c {1}§6.
mutedPlayerForReason=§6Người chơi§c {0} §6đã bị câm trong§c {1}§6. §6Lí do\: §c{2}
@@ -157,6 +157,7 @@ commandHelpLine3=§6用法:
commandHelpLine4=§6别名:§f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4{0}命令加载失败。
consoleCannotUseCommand=此命令不能在控制台使用。
compassBearing=§6方向:{0}({1} 度)。
compassCommandDescription=描述你当前的方位。
compassCommandUsage=/<command>
@@ -1024,8 +1025,8 @@ recentlyForeverAlone=§4{0}最近离线。
recipe=§c{0}§6的合成方法(§c{1}§6|§c{2}§6)
recipeBadIndex=这个编号没有匹配的合成方法。
recipeCommandDescription=显示物品合成方法。
recipeCommandUsage=/<command> <物品> [数量]
recipeCommandUsage1=/<command> <物品> [页码]
recipeCommandUsage=/<command> <<物品>|hand> [数量]
recipeCommandUsage1=/<command> <<物品>|hand> [页码]
recipeCommandUsage1Description=展示如何合成指定物品
recipeFurnace=§6冶炼:§c{0}§6.
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X
@@ -1251,7 +1252,7 @@ teleportationCommencing=§6准备传送……
teleportationDisabled=§6传送§c已禁用§6。
teleportationDisabledFor=§6已为§c{0}禁用§6了传送。
teleportationDisabledWarning=§6你必须启用传送功能才能让其他玩家传送到你这里。
teleportationEnabled=§6传送§c已禁用§6。
teleportationEnabled=§6传送§a已启用§6。
teleportationEnabledFor=§6传送功能 §c开启 §6了 §c{0}§6.
teleportAtoB=§c{0}§6将你传送至§c{1}§6。
teleportBottom=§6传送到底部。
@@ -65,7 +65,7 @@ banCommandDescription=封禁玩家。
banCommandUsage=/<command> <player> [reason]
banCommandUsage1=/<command> <player> [reason]
banCommandUsage1Description=封禁指定玩家並附加自訂原因
banExempt=§4你無法封禁該玩家。
banExempt=§4你無法封禁此玩家。
banExemptOffline=§4你無法封禁離線玩家。
banFormat=§4你已被封禁:\n§r{0}
banIpJoin=你的 IP 位址已被伺服器封禁。原因:{0}
@@ -93,13 +93,14 @@ bookAuthorSet=§6這本書的作者已被設定為 {0}。
bookCommandDescription=允許重新打開及編輯封存的書。
bookCommandUsage=/<command> [title|author [name]]
bookCommandUsage1=/<command>
bookCommandUsage1Description=鎖定或解鎖一本 書和羽毛筆 或 已署名的書 。
bookCommandUsage1Description=鎖定或解鎖一本 書和羽毛筆 或 已署名的書。
bookCommandUsage2=/<command> author <author>
bookCommandUsage2Description=設定書的作者簽名
bookCommandUsage3=/<command> title <title>
bookCommandUsage3Description=設定書的標題
bookLocked=§6已鎖定這本書。
bookTitleSet=§6這本書的標題已被設定為 {0}。
bottomCommandDescription=傳送到你目前位置的最低點。
bottomCommandUsage=/<command>
breakCommandDescription=破壞你前方的方塊。
breakCommandUsage=/<command>
@@ -122,7 +123,7 @@ cannotSellTheseNamedItems=§6你沒有出售已命名物品 §4{0} §6的權限
cannotStackMob=§4你沒有堆疊多個生物的權限。
canTalkAgain=§6你已獲得發言資格。
cantFindGeoIpDB=找不到 GeoIP 資料庫!
cantGamemode=§4你沒有更改 {0} 的權限。
cantGamemode=§4你沒有變更 {0} 的權限。
cantReadGeoIpDB=讀取 GeoIP 資料庫失敗!
cantSpawnItem=§4你沒有生成物品§c {0}§4 的權限。
cartographytableCommandDescription=開啟製圖台。
@@ -149,13 +150,14 @@ commandArgumentRequired=§e
commandCooldown=§c請在 {0}後重新輸入指令。
commandDisabled=§c已停用指令§6 {0}§c。
commandFailed=執行指令 {0} 失敗:
commandHelpFailedForPlugin=取得該插件的說明時發生錯誤:{0}
commandHelpFailedForPlugin=取得此插件的說明時發生錯誤:{0}
commandHelpLine1=§6指令說明:§f/{0}
commandHelpLine2=§6描述:§f{0}
commandHelpLine3=§6用法:
commandHelpLine4=§6別稱:§f{0}
commandHelpLineUsage={0} §6- {1}
commandNotLoaded=§4無法載入指令 {0}。
consoleCannotUseCommand=此指令無法在控制台使用。
compassBearing=§6方位:{0}({1} 度)
compassCommandDescription=描述你目前的方位。
compassCommandUsage=/<command>
@@ -183,7 +185,7 @@ createkitCommandUsage1Description=建立具有指定名稱和延遲的工具包
createKitFailed=§4建立 {0} 工具包時發生錯誤。
createKitSeparator=§m-----------------------
createKitSuccess=§6建立的工具包:§f{0}\n§6冷卻:§f{1}\n§6連結:§f{2}\n§6請將連結中的內容複製到 kits.yml。
createKitUnsupported=§4已啟用 NBT 物品序列化,但該伺服器端並不是運行 Paper 1.15.2 以上,所以返回為標準物品序列化。
createKitUnsupported=§4已啟用 NBT 物品序列化,但此伺服器端並不是運行 Paper 1.15.2 以上,所以返回為標準物品序列化。
creatingConfigFromTemplate=從模版 {0} 建立配置。
creatingEmptyConfig=建立空白配置:{0}
creative=創造模式
@@ -193,13 +195,13 @@ customtextCommandDescription=允許建立自訂文字指令。
customtextCommandUsage=/<alias> - 定義 bukkit.yml
day=天
days=天
defaultBanReason=你的帳號已被該伺服器封禁!
defaultBanReason=你的帳號已被此伺服器封禁!
deletedHomes=已刪除所有家點。
deletedHomesWorld=已刪除世界 {0} 中的所有家點。
deleteFileError=無法刪除檔案:{0}
deleteHome=§6家點§c {0} §6已被移除。
deleteJail=§6已移除§c {0} §6監獄 。
deleteKit=§6已移除§c {0} §6工具包 。
deleteJail=§6已移除§c {0} §6監獄。
deleteKit=§6已移除§c {0} §6工具包。
deleteWarp=§6已移除§c {0} §6地標。
deletingHomes=正在刪除所有家點……
deletingHomesWorld=正在刪除世界 {0} 的所有家點……
@@ -223,8 +225,8 @@ delwarpCommandUsage1=/<command> <warp>
delwarpCommandUsage1Description=刪除指定名稱的地標
deniedAccessCommand=§4拒絕讓 §c{0} §4使用指令。
denyBookEdit=§4你不能解鎖這本書。
denyChangeAuthor=§4你不能更改這本書的作者。
denyChangeTitle=§4你不能更改這本書的標題。
denyChangeAuthor=§4你不能變更這本書的作者。
denyChangeTitle=§4你不能變更這本書的標題。
depth=§6你位於海平面。
depthAboveSea=§6你位於海平面正§c {0} §6格處。
depthBelowSea=§6你位於海平面負§c {0} §6格處。
@@ -232,7 +234,7 @@ depthCommandDescription=指出目前相對於海平面的深度。
depthCommandUsage=/depth
destinationNotSet=未設定目的地!
disabled=停用
disabledToSpawnMob=§4配置檔案中已停用該生物的生成。
disabledToSpawnMob=§4配置檔案中已停用此生物的生成。
disableUnlimited=§c已停用 {1} §6的無限放置§c {0} §6能力。
discordbroadcastCommandDescription=廣播訊息到指定的 Discord 頻道。
discordbroadcastCommandUsage=/<command> <channel> <msg>
@@ -269,7 +271,7 @@ discordCommandMessageDescription=向 Minecraft 伺服器中的玩家傳送訊息
discordCommandMessageArgumentUsername=將收到訊息的玩家
discordCommandMessageArgumentMessage=要傳送給玩家的訊息
discordErrorCommand=你錯誤地將機器人新增到伺服器!請按照配置中的教學並使用 https\://essentialsx.net/discord.html 新增你的機器人。
discordErrorCommandDisabled=該指令已被停用!
discordErrorCommandDisabled=此指令已被停用!
discordErrorLogin=登入 Discord 時發生錯誤,故插件已自行停用:\n{0}
discordErrorLoggerInvalidChannel=由於頻道定義無效,Discord 控制台記錄已被停用!如果你原本就打算停用,請將頻道 ID 設為「none」;否則請確認你的頻道 ID 是否正確。
discordErrorLoggerNoPerms=由於權限不足,Discord 控制台記錄器已被停用!請確保你的機器人在伺服器中有「管理 Webhooks」這項權限。修正後請執行「/ess reload」。
@@ -286,30 +288,30 @@ discordLinkInvalidRoleInteract=身份組 {0}({1})不能在組 -> 身份組
discordLinkInvalidRoleManaged=身份組 {0}({1})不能在組 -> 身份組之間同步,因為它是由另一個機器人或集成管理的。
discordLinkLinked=§6如果要綁定你的 Minecraft 與Discord 帳號,請在 Discord 伺服器中輸入 §c{0}§6。
discordLinkLinkedAlready=§6你的 Discord 帳號已經連結過了!如果你想要解除連結,請使用 §c/unlink§6。
discordLinkLoginKick=§6你必須連結 Discord 帳號才能加入該伺服器。\n§6如果要將你的 Minecraft 帳號與 Discord 帳號連結,請在這個伺服器的 Discord 伺服器中輸入:\n§c{0}\n§6Discord 伺服器位址:\n§c{1}
discordLinkLoginPrompt=§6你必須連結你的 Discord 帳號才能在該伺服器上移動、聊天或互動。如果要將你的 Minecraft 帳號與 Discord 連結,請在本伺服器的 Discord 伺服器中輸入 §c{0}§6,伺服器位址:§c{1}
discordLinkLoginKick=§6你必須連結 Discord 帳號才能加入此伺服器。\n§6如果要將你的 Minecraft 帳號與 Discord 帳號連結,請在此伺服器的 Discord 伺服器中輸入:\n§c{0}\n§6Discord 伺服器位址:\n§c{1}
discordLinkLoginPrompt=§6你必須連結你的 Discord 帳號才能在此伺服器上移動、聊天或互動。如果要將你的 Minecraft 帳號與 Discord 連結,請在本伺服器的 Discord 伺服器中輸入 §c{0}§6,伺服器位址:§c{1}
discordLinkNoAccount=§6目前你的 Minecraft 帳號沒有連結 Discord 帳號。
discordLinkPending=§6你已經有了一個連結代碼。如果要完成連結你的 Minecraft 與 Discord 連結,請在 Discord 伺服器中輸入 §c{0}§6。
discordLinkUnlinked=§6把你的 Minecraft 帳號與所有相關 Discord 帳號解除連結。
discordLoggingIn=正在嘗試登入至 Discord……
discordLoggingInDone=成功以 {0} 的身分登入
discordMailLine=**來自 {0} 的新郵件\:** {1}
discordNoSendPermission=無法在頻道 \#{0} 中傳送訊息。請確保機器人在該頻道有「傳送訊息」的權限!
discordNoSendPermission=無法在頻道 \#{0} 中傳送訊息。請確保機器人在此頻道有「傳送訊息」的權限!
discordReloadInvalid=嘗試在插件處於無效狀態時,載入 EssentialsX Discord 配置檔案!如果你修改了配置檔案,請重新啟動伺服器。
disposal=垃圾桶
disposalCommandDescription=開啟簡易垃圾桶選單。
disposalCommandUsage=/<command>
distance=§6距離:{0}
dontMoveMessage=§6傳送將在 §c{0}§6後開始,不要移動。
downloadingGeoIp=下載 GeoIP 資料庫中…… 這可能會花點時間。
downloadingGeoIp=正在下載 GeoIP 資料庫中……這可能會花點時間。
dumpConsoleUrl=已經建立伺服器傾印檔案:§c{0}
dumpCreating=§6正在建立伺服器傾印檔案……
dumpDeleteKey=§6若你稍後想刪除這份傾印檔案,請使用這個刪除代碼:§c{0}
dumpDeleteKey=§6若你稍後想刪除這份傾印檔案,請使用此刪除代碼:§c{0}
dumpError=§4建立 §c{0}§4 傾印檔案時發生錯誤。
dumpErrorUpload=§4上傳 §c{0}§4 時發生錯誤:§c{1}
dumpUrl=§6已建立伺服器傾印檔案:§c{0}
duplicatedUserdata=玩家資料重複:{0} 和 {1}。
durability=§6這個工具還有 §c{0}§6 點耐久度。
durability=§6此工具還有 §c{0}§6 點耐久度。
east=東
ecoCommandDescription=管理伺服器經濟。
ecoCommandUsage=/<command> <give|take|set|reset> <player> <amount>
@@ -329,7 +331,7 @@ enchantCommandUsage1=/<command> <enchantment name> [level]
enchantCommandUsage1Description=附魔手中的物品並設定自訂等級
enableUnlimited=§6給予 §c{1}§6 無限的 §c{0}§6。
enchantmentApplied=§6附魔 §c{0}§6 已被套用到你手中的物品。
enchantmentNotFound=§4找不到該附魔!
enchantmentNotFound=§4找不到此附魔!
enchantmentPerm=§4你沒有附魔§c {0} §4的權限。
enchantmentRemoved=§6附魔 §c{0}§6 已從你手中的物品移除。
enchantments=§6附魔:§r{0}
@@ -341,7 +343,7 @@ enderchestCommandUsage2=/<command> <player>
enderchestCommandUsage2Description=開啟指定玩家的終界箱
errorCallingCommand=呼叫指令 /{0} 時發生錯誤
errorWithMessage=§c錯誤:§4{0}
essChatNoSecureMsg=EssentialsX Chat {0} 版本的安全聊天不支援該伺服器核心。請更新 EssentialsX,若此問題仍然存在,請通知開發人員。
essChatNoSecureMsg=EssentialsX Chat {0} 版本的安全聊天不支援此伺服器核心。請更新 EssentialsX,若此問題仍然存在,請通知開發人員。
essentialsCommandDescription=重新載入 Essentials。
essentialsCommandUsage=/<command>
essentialsCommandUsage1=/<command> reload
@@ -360,8 +362,8 @@ essentialsCommandUsage7=/<command> homes
essentialsCommandUsage7Description=管理玩家的家點
essentialsCommandUsage8=/<command> dump [all] [config] [discord] [kits] [log]
essentialsCommandUsage8Description=根據請求的資訊產生伺服器傾印檔案
essentialsHelp1=檔案毀損以致於 Essentials 無法將其開啟,現在已停用 Essentials。若你無法修正該檔案,請前往 https\://essentialsx.net/wiki/Home.html 尋求協助。
essentialsHelp2=檔案毀損以致於 Essentials 無法將其開啟,現在已停用 Essentials。若你無法修正該檔案,請在遊戲中輸入 /essentialshelp 或前往 https\://essentialsx.net/wiki/Home.html 尋求協助。
essentialsHelp1=檔案毀損以致於 Essentials 無法將其開啟,現在已停用 Essentials。若你無法修正此檔案,請前往 https\://essentialsx.net/wiki/Home.html 尋求協助。
essentialsHelp2=檔案毀損以致於 Essentials 無法將其開啟,現在已停用 Essentials。若你無法修正此檔案,請在遊戲中輸入 /essentialshelp 或前往 https\://essentialsx.net/wiki/Home.html 尋求協助。
essentialsReload=§6已重新載入 Essentials§c {0}§6。
exp=§c{0} §6擁有§c {1} §6點經驗值(等級§c {2}§6)。需要§c {3} §6點經驗才能升級。
expCommandDescription=給予、設定、重設或查看玩家的經驗值。
@@ -425,7 +427,7 @@ fullStackDefault=§6你的堆疊已被設定為預設大小 §c{0}§6。
fullStackDefaultOversize=§6你的堆疊已被設定為最大 §c{0}§6。
gameMode=§6已設定 §c{1}§6 的遊戲模式為§c {0}§6。
gameModeInvalid=§4你必須指定有效的玩家或遊戲模式。
gamemodeCommandDescription=更改玩家遊戲模式。
gamemodeCommandDescription=變更玩家遊戲模式。
gamemodeCommandUsage=/<command> <survival|creative|adventure|spectator> [player]
gamemodeCommandUsage1=/<command> <survival|creative|adventure|spectator> [player]
gamemodeCommandUsage1Description=設定你或指定玩家的遊戲模式
@@ -463,9 +465,9 @@ godEnabledFor=§a已啟用§c {0} §6的
godMode=§c{0}§6上帝模式。
grindstoneCommandDescription=開啟砂輪機。
grindstoneCommandUsage=/<command>
groupDoesNotExist=§4該組別沒有人在線!
groupDoesNotExist=§4此組別沒有人在線!
groupNumber=§c{0}§f 位在線,想要獲得完整列表請使用:§c/{1} {2}
hatArmor=§4你無法使用該物品作為帽子!
hatArmor=§4你無法使用此物品作為帽子!
hatCommandDescription=戴上一些酷炫的帽子。
hatCommandUsage=/<command> [remove]
hatCommandUsage1=/<command>
@@ -565,8 +567,8 @@ invseeCommandUsage1Description=開啟指定玩家的物品欄
invseeNoSelf=§c你只能檢視其他玩家的物品欄。
is=是
isIpBanned=§6IP 位址 §c{0} §6已被封禁。
internalError=§c執行該指令時發生內部錯誤。
itemCannotBeSold=§4該物品無法賣給伺服器。
internalError=§c執行此指令時發生內部錯誤。
itemCannotBeSold=§4此物品無法賣給伺服器。
itemCommandDescription=生成物品。
itemCommandUsage=/<command> <item|numeric> [amount [itemmeta...]]
itemCommandUsage1=/<command> <item> [amount]
@@ -574,7 +576,7 @@ itemCommandUsage1Description=給予你一組或指定數量的物品
itemCommandUsage2=/<command> <item> <amount> <meta>
itemCommandUsage2Description=給予你指定數量帶有元資料物品
itemId=§6ID:§c{0}
itemloreClear=§6你已清除該物品的描述文字。
itemloreClear=§6你已清除此物品的描述文字。
itemloreCommandDescription=編輯物品描述文字。
itemloreCommandUsage=/<command> <add/set/clear> [text/line] [text]
itemloreCommandUsage1=/<command> add [text]
@@ -590,7 +592,7 @@ itemloreSuccess=§6你已將描述文字「§c{0}§6」新增到你拿著的物
itemloreSuccessLore=§6你將拿著的物品描述文字第 §c{0}§6 行設定為「§c{1}§6」。
itemMustBeStacked=§4物品必須成組交易,2s 的數量是 2 組,以此類推。
itemNames=§6物品簡稱:§r{0}
itemnameClear=§6你已清除該物品的名稱。
itemnameClear=§6你已清除此物品的名稱。
itemnameCommandDescription=命名物品。
itemnameCommandUsage=/<command> [name]
itemnameCommandUsage1=/<command>
@@ -601,7 +603,7 @@ itemnameInvalidItem=§c你需要拿著物品才能重新命名。
itemnameSuccess=§6你已將手中的物品重新命名為「§c{0}§6」。
itemNotEnough1=§4你沒有足夠的物品可以賣出。
itemNotEnough2=§6如果你想要賣出物品欄所有的物品,輸入 §c/sell itemname§6。
itemNotEnough3=§c/sell itemname -1 §6將賣出所有該物品,但剩餘 1 個物品,以此類推。
itemNotEnough3=§c/sell itemname -1 §6將賣出所有此物品,但剩餘 1 個物品,以此類推。
itemsConverted=§6轉換所有物品為更緊實的方塊。
itemsCsvNotLoaded=無法載入 {0}!
itemSellAir=你難道想賣空氣嗎?放個東西在你手裡。
@@ -617,7 +619,7 @@ itemdbCommandUsage1Description=在資料庫中搜尋指定物品
jailAlreadyIncarcerated=§4已在監獄中的玩家:§c{0}
jailList=§6監獄:§r{0}
jailMessage=§4請在監獄中面壁思過。
jailNotExist=§4該監獄不存在。
jailNotExist=§4此監獄不存在。
jailNotifyJailed=§c {1}§6將玩家§c {0} §6關進監獄。
jailNotifyJailedFor=§6玩家§c {0} §6被§c {2} §6逮捕並關進監獄§c {1}§6。
jailNotifySentenceExtended=§6玩家§c {0} §6的監禁時間被§c {2} §6延長到§c {1}§6。
@@ -625,7 +627,7 @@ jailReleased=§6玩家 §c{0}§6 出獄了。
jailReleasedPlayerNotify=§6你已被釋放!
jailSentenceExtended=§6監禁時間增加到:§c{0}§6。
jailSet=§6監獄 §c{0}§6 已被設定。
jailWorldNotExist=§4該監獄位於的世界不存在。
jailWorldNotExist=§4此監獄位於的世界不存在。
jumpEasterDisable=§c已停用§6飛行導向模式(飛行時對傳送目標點擊左鍵觸發傳送)。
jumpEasterEnable=§c已啟用§6飛行導向模式。(飛行時對傳送目標點擊左鍵觸發傳送)
jailsCommandDescription=列出所有監獄列表。
@@ -639,7 +641,7 @@ kickCommandUsage1=/<command> <player> [reason]
kickCommandUsage1Description=踢出指定玩家並附加自訂原因
kickDefault=從伺服器踢出
kickedAll=§4已將所有玩家踢出伺服器。
kickExempt=§4你無法踢出該玩家。
kickExempt=§4你無法踢出此玩家。
kickallCommandDescription=踢出除了傳送指令者之外的所有玩家出伺服器。
kickallCommandUsage=/<command> [reason]
kickallCommandUsage1=/<command> [reason]
@@ -660,14 +662,14 @@ kitContains=§6工具包 §c{0} §6包含:
kitCost=\ §7§o({0})§r
kitDelay=§m{0}§r
kitError=§4沒有有效的工具包。
kitError2=§4該工具包的配置不正確。請聯絡管理員。
kitError2=§4此工具包的配置不正確。請聯絡管理員。
kitError3=無法給予玩家 {1} 工具包,因為工具包「{0}」需要 Paper 1.15.2+ 來反序列化。
kitGiveTo=§6給予§c {1} §6工具包§c {0}§6。
kitInvFull=§4你的物品欄已滿,工具包將放在地上。
kitInvFullNoDrop=§4沒有足夠的物品欄空間放置該工具包。
kitInvFullNoDrop=§4沒有足夠的物品欄空間放置此工具包。
kitItem=§6- §f{0}
kitNotFound=§4工具包不存在。
kitOnce=§4你不能再次使用該工具包。
kitOnce=§4你不能再次使用此工具包。
kitReceive=§6收到一個§c {0} §6工具包。
kitReset=§6將工具包 §c{0}§6 重設冷卻時間。
kitresetCommandDescription=重設指定工具包的冷卻時間。
@@ -678,7 +680,7 @@ kitResetOther=§6將 §c{1}§6 的工具包 §c{0}§6 重設冷卻時間。
kits=§6工具包:§r{0}
kittycannonCommandDescription=向你的敵人投擲一隻爆炸貓。
kittycannonCommandUsage=/<command>
kitTimed=§4你不能再次對其他人使用該工具包§c {0}§4。
kitTimed=§4你不能再次對其他人使用此工具包§c {0}§4。
leatherSyntax=§6皮革顏色語法:§ccolor\:<red>,<green>,<blue> 例如:color\:255,0,0 §6或§c color\:<rgb int> §6例如:color\:16777011
lightningCommandDescription=以雷神索爾的力量,劈向目標玩家。
lightningCommandUsage=/<command> [player] [power]
@@ -735,10 +737,10 @@ mailSentTo=§c{0}§6 已被傳送以下郵件:
mailSentToExpire=§c{0}§6 傳送了以下郵件,郵件將於 §c{1}§6 過期:
mailTooLong=§4郵件訊息過長,請不要超過 1000 字。
markMailAsRead=§6輸入§c /mail clear§6 將郵件標示為已讀。
matchingIPAddress=§6以下是使用該 IP 位址的玩家:
matchingIPAddress=§6以下是使用此 IP 位址的玩家:
maxHomes=§4你無法設立超過§c {0} §4個家點。
maxMoney=§4這筆交易將超出該帳戶的金錢限制。
mayNotJail=§4你無法將該玩家關進監獄!
maxMoney=§4這筆交易將超出此帳戶的金錢限制。
mayNotJail=§4你無法將此玩家關進監獄!
mayNotJailOffline=§4你無法將離線玩家關進監獄。
meCommandDescription=以第三人稱描述一件事。
meCommandUsage=/<command> <description>
@@ -753,7 +755,7 @@ minutes=分鐘
missingItems=§4你沒有 {0} §4個§c {1}§4。
mobDataList=§6有效的生物資料:§r{0}
mobsAvailable=§6生物:§r{0}
mobSpawnError=§4更改生怪磚時發生錯誤。
mobSpawnError=§4變更生怪磚時發生錯誤。
mobSpawnLimit=生物數量超出伺服器限制。
mobSpawnTarget=§4目標方塊必須是生怪磚。
moneyRecievedFrom=§a{0}§6 已收到來自 §a {1}§6。
@@ -773,7 +775,7 @@ msgCommandUsage=/<command> <to> <message>
msgCommandUsage1=/<command> <to> <message>
msgCommandUsage1Description=傳送私人訊息到指定玩家
msgDisabled=§c已停用§6接收訊息。
msgDisabledFor=§c已停用 {0} §6的接收訊息 。
msgDisabledFor=§c已停用 {0} §6的接收訊息。
msgEnabled=§a已啟用§6接收訊息。
msgEnabledFor=§a已啟用 {0} §6的接收訊息。
msgFormat=§6[§c{0}§6 -> §c{1}§6] §r{2}
@@ -782,8 +784,8 @@ msgtoggleCommandDescription=阻擋所有私人訊息接收。
msgtoggleCommandUsage=/<command> [player] [on|off]
msgtoggleCommandUsage1=/<command> [player]
msgtoggleCommandUsage1Description=切換你或指定玩家的飛行模式
multipleCharges=§4你不能對這個煙火應用多種的填充物。
multiplePotionEffects=§4你不能對這個煙火應用多種的效果。
multipleCharges=§4你不能對此煙火套用多種的填充物。
multiplePotionEffects=§4你不能對此煙火套用多種的效果。
muteCommandDescription=禁言或解除禁言玩家。
muteCommandUsage=/<command> <player> [datediff] [reason]
muteCommandUsage1=/<command> <player>
@@ -795,7 +797,7 @@ mutedPlayerFor=§6玩家§c {0} §6被禁言§c {1}§6。
mutedPlayerForReason=§6玩家§c {0} §6被禁言§c {1}§6。原因:§c{2}
mutedPlayerReason=§6玩家§c {0} §6被禁言。原因:§c{1}
mutedUserSpeaks={0} 想要說話,但被禁言了:{1}
muteExempt=§4你無法禁言該玩家。
muteExempt=§4你無法禁言此玩家。
muteExemptOffline=§4你無法將離線玩家禁言。
muteNotify=§c{0} §6將 §c{1} §6禁言。
muteNotifyFor=§6玩家 §c{1}§6 被 §c{0} §6禁言§c {2}§6。
@@ -814,26 +816,26 @@ nearCommandUsage4Description=列出以指定玩家為中心,指定半徑內的
nearbyPlayers=§6附近的玩家:§r{0}
nearbyPlayersList={0}§f(§c{1} 公尺§f)
negativeBalanceError=§4金錢不可小於零。
nickChanged=§6暱稱已更改。
nickCommandDescription=更改你的暱稱或其他玩家的暱稱。
nickChanged=§6暱稱已變更。
nickCommandDescription=變更你的暱稱或其他玩家的暱稱。
nickCommandUsage=/<command> [player] <nickname|off>
nickCommandUsage1=/<command> <nickname>
nickCommandUsage1Description=更改你的暱稱
nickCommandUsage1Description=變更你的暱稱
nickCommandUsage2=/<command> off
nickCommandUsage2Description=移除你的暱稱
nickCommandUsage3=/<command> <player> <nickname>
nickCommandUsage3Description=更改指定玩家的暱稱
nickCommandUsage3Description=變更指定玩家的暱稱
nickCommandUsage4=/<command> <player> off
nickCommandUsage4Description=移除指定玩家的暱稱
nickDisplayName=§4你需要在 Essentials 配置檔案內啟用 change-displayname。
nickInUse=§4那個暱稱已被使用。
nickNameBlacklist=§4不允許使用這個暱稱。
nickNameBlacklist=§4不允許使用此暱稱。
nickNamesAlpha=§4暱稱必須為有效的文字。
nickNamesOnlyColorChanges=§4暱稱只能更改顏色。
nickNamesOnlyColorChanges=§4暱稱只能變更顏色。
nickNoMore=§6你不再擁有暱稱。
nickSet=§6你的暱稱現在是 §c{0}§6。
nickTooLong=§4這個暱稱太長。
noAccessCommand=§4你沒有使用該指令的權限。
nickTooLong=§4此暱稱太長。
noAccessCommand=§4你沒有使用此指令的權限。
noAccessPermission=§4你沒有訪問 §c{0}§4 的權限。
noAccessSubCommand=§4你沒有使用 §c{0}§4 的權限。
noBreakBedrock=§4你沒有破壞基岩的權限。
@@ -841,29 +843,29 @@ noDestroyPermission=§4你沒有破壞 §c{0}§4 的權限。
northEast=東北
north=北
northWest=西北
noGodWorldWarning=§4警告!該世界的上帝模式已被停用。
noHomeSetPlayer=§6該玩家還未設立家點。
noGodWorldWarning=§4警告!此世界的上帝模式已被停用。
noHomeSetPlayer=§6此玩家還未設立家點。
noIgnored=§6你沒有忽略任何人。
noJailsDefined=§6沒有被定義的監獄。
noKitGroup=§4你沒有使用這個工具包的權限。
noKitPermission=§4你需要 §c{0}§4 權限來使用該工具包。
noKitGroup=§4你沒有使用此工具包的權限。
noKitPermission=§4你需要 §c{0}§4 權限來使用此工具包。
noKits=§6還沒有可獲得的工具包。
noLocationFound=§4找不到有效地點。
noMail=§6你沒有任何郵件。
noMatchingPlayers=§6找不到匹配的玩家。
noMetaFirework=§4你沒有應用煙火資料的權限。
noMetaJson=這個版本的 Bukkit 不支援 JSON 元資料。
noMetaPerm=§4你沒有應用 §c{0}§4 資料的權限。
noMetaFirework=§4你沒有套用煙火資料的權限。
noMetaJson=此版本的 Bukkit 不支援 JSON 元資料。
noMetaPerm=§4你沒有套用 §c{0}§4 資料的權限。
none=無
noNewMail=§6你沒有新的郵件。
nonZeroPosNumber=§4指定的值必須為非零數字。
noPendingRequest=§4你沒有待解決的請求。
noPerm=§4你沒有 §c{0}§4 的權限。
noPermissionSkull=§4你沒有修改這個頭顱的權限。
noPermissionSkull=§4你沒有修改此頭顱的權限。
noPermToAFKMessage=§4你沒有設定暫時離開訊息的權限。
noPermToSpawnMob=§4你沒有生成該生物的權限。
noPermToSpawnMob=§4你沒有生成此生物的權限。
noPlacePermission=§4你沒有在告示牌旁邊放置方塊的權限。
noPotionEffectPerm=§4你沒有應用特效 §c{0} §4到這個藥水的權限。
noPotionEffectPerm=§4你沒有套用特效 §c{0} §4到此藥水的權限。
noPowerTools=§6你沒有綁定指令。
notAcceptingPay=§4{0} §4不接受付款。
notAllowedToLocal=§4你沒有在區域聊天的權限。
@@ -887,8 +889,8 @@ onlyPlayerSkulls=§4你只能設定玩家頭顱的擁有者。
onlySunStorm=§4/weather 指令只有 sun/storm 兩個選擇。
openingDisposal=§6正在打開垃圾桶選單……
orderBalances=§6正在排序§c {0} §6個玩家的金錢中,請稍候……
oversizedMute=§4你無法禁言該玩家。
oversizedTempban=§4你無法以該時長封禁玩家。
oversizedMute=§4你無法禁言此玩家。
oversizedTempban=§4你無法以此時長封禁玩家。
passengerTeleportFail=§4你無法在乘坐時被傳送。
payCommandDescription=從你的金錢中扣款支付給其他玩家。
payCommandUsage=/<command> <player> <amount>
@@ -951,7 +953,7 @@ posY=§6Y:{0}(+上 <-> -下)
posYaw=§6角度:{0}(旋轉)
posZ=§6Z:{0}(+南 <-> -北)
potions=§6藥水:§r{0}§6。
powerToolAir=§4該指令不能對著空氣使用。
powerToolAir=§4此指令不能對著空氣使用。
powerToolAlreadySet=§4指令 §c{0}§4 已綁定給 §c{1}§4。
powerToolAttach=§c{0}§6 指令綁定給§c {1}§6。
powerToolClearAll=§6所有綁定指令已被清除。
@@ -1020,11 +1022,11 @@ realnameCommandUsage=/<command> <nickname>
realnameCommandUsage1=/<command> <nickname>
realnameCommandUsage1Description=顯示指定暱稱玩家的真實名稱
recentlyForeverAlone=§4{0} 剛才離線了。
recipe=§c{0}§6 的合成方式 (§c第 {1} 頁§6,§c共 {2} 頁§6) 。
recipeBadIndex=這個編號沒有匹配的合成方式。
recipe=§c{0}§6 的合成方式 (§c第 {1} 頁§6,§c共 {2} 頁§6)。
recipeBadIndex=此編號沒有匹配的合成方式。
recipeCommandDescription=顯示如何合成物品。
recipeCommandUsage=/<command> <item> [number]
recipeCommandUsage1=/<command> <item> [page]
recipeCommandUsage=/<command> <<item>|hand> [number]
recipeCommandUsage1=/<command> <<item>|hand> [page]
recipeCommandUsage1Description=顯示如何合成物品
recipeFurnace=§6熔煉:§c{0}§6。
recipeGrid=§c{0}X §6| §{1}X §6| §{2}X。
@@ -1048,7 +1050,7 @@ renamehomeCommandUsage1Description=重新命名指定名稱的家點
renamehomeCommandUsage2=/<command> <player>\:<name> <new name>
renamehomeCommandUsage2Description=重新命名屬於指定玩家,指定名稱的家點
repair=§6你成功修好了 §c{0}§6。
repairAlreadyFixed=§4該物品無需修復。
repairAlreadyFixed=§4此物品無需修復。
repairCommandDescription=修復一個或多個物品的耐久度。
repairCommandUsage=/<command> [hand|all]
repairCommandUsage1=/<command>
@@ -1056,7 +1058,7 @@ repairCommandUsage1Description=修復手中的物品
repairCommandUsage2=/<command> all
repairCommandUsage2Description=修復物品欄的所有物品
repairEnchanted=§4你沒有修復附魔物品的權限。
repairInvalidType=§4該物品無法修復。
repairInvalidType=§4此物品無法修復。
repairNone=§4沒有需要被修復的物品。
replyFromDiscord=**來自 {0} 的回覆\:** {1}
replyLastRecipientDisabled=§c已停用§6回覆上一則訊息功能。
@@ -1084,14 +1086,14 @@ restCommandUsage1=/<command> [player]
restCommandUsage1Description=重設你或指定玩家精神狀態
restOther=§c{0} §6休息中。
returnPlayerToJailError=§4嘗試將玩家§c {0} §4關回監獄時發生錯誤:§c{1}§4!
rtoggleCommandDescription=更改回覆收件人為最後的收件人或發件人
rtoggleCommandDescription=變更回覆收件人為最後的收件人或發件人
rtoggleCommandUsage=/<command> [player] [on|off]
rulesCommandDescription=查看伺服器規則。
rulesCommandUsage=/<command> [chapter] [page]
runningPlayerMatch=§6正在搜尋匹配「§c{0}§6」的玩家(這可能會花費一些時間)。
second=秒
seconds=秒
seenAccounts=§6該玩家也擁有其他帳號:§c{0}
seenAccounts=§6此玩家也擁有其他帳號:§c{0}
seenCommandDescription=顯示玩家的最後登出時間。
seenCommandUsage=/<command> <playername>
seenCommandUsage1=/<command> <playername>
@@ -1119,10 +1121,10 @@ serverUnsupportedCleanroom=你正在運行一個不依賴 Mojang 內部代碼的
serverUnsupportedDangerous=你正在運行一個已知極其危險並導致資料遺失的伺服器分支。 強烈建議你切換到更穩定的伺服器核心,例如 Paper。
serverUnsupportedLimitedApi=你正在運行 API 功能受限的伺服器。EssentialsX 仍然可以使用,但是某些功能可能被停用。
serverUnsupportedDumbPlugins=你正在使用已知會導致 EssentialsX 和其他插件出現嚴重問題的插件。
serverUnsupportedMods=你正在運行的伺服器端無法正常支援 Bukkit 插件。Bukkit 插件不應該與 Forge 或 Fabric 模組一起使用!建議使用 ForgeEssentials 或 SpongeForge + Nucleus 代替本插件。
serverUnsupportedMods=你正在運行的伺服器端無法正常支援 Bukkit 插件。Bukkit 插件不應此與 Forge 或 Fabric 模組一起使用!建議使用 ForgeEssentials 或 SpongeForge + Nucleus 代替本插件。
setBal=§a你的金錢已被設定為 {0}。
setBalOthers=§a成功設定 {0} §a的金錢為 {1}。
setSpawner=§6更改生怪磚類型為§c {0}§6。
setSpawner=§6變更生怪磚類型為§c {0}§6。
sethomeCommandDescription=在你目前的位置設立家點。
sethomeCommandUsage=/<command> [[player\:]name]
sethomeCommandUsage1=/<command> <name>
@@ -1191,7 +1193,7 @@ similarWarpExist=§4一個同名的地標已存在。
southEast=東南
south=南
southWest=西南
skullChanged=§6頭顱更改為 §c{0}§6。
skullChanged=§6頭顱變更為 §c{0}§6。
skullCommandDescription=設定玩家頭顱
skullCommandUsage=/<command> [owner]
skullCommandUsage1=/<command>
@@ -1209,9 +1211,9 @@ socialspyCommandUsage=/<command> [player] [on|off]
socialspyCommandUsage1=/<command> [player]
socialspyCommandUsage1Description=切換你或指定玩家的監聽模式
socialSpyPrefix=§f[§6監聽§f] §r
soloMob=§4該生物喜歡獨居。
soloMob=§4此生物喜歡獨居。
spawned=已生成
spawnerCommandDescription=更改生怪磚生物類型。
spawnerCommandDescription=變更生怪磚生物類型。
spawnerCommandUsage=/<command> <mob> [delay]
spawnerCommandUsage1=/<command> <mob> [delay]
spawnerCommandUsage1Description=修改你看著的生怪磚裡的生物類型(可選自定義生怪延遲)
@@ -1223,7 +1225,7 @@ spawnmobCommandUsage2=/<command> <mob>[\:data],<mount>[\:data] [amount] [player]
spawnmobCommandUsage2Description=在你 (或指定玩家) 的位置生成一個 (或指定數量的) 騎著另一個指定生物的指定生物
spawnSet=§6已設定§c {0}§6 組的重生點。
spectator=旁觀者模式
speedCommandDescription=更改你的速度限制。
speedCommandDescription=變更你的速度限制。
speedCommandUsage=/<command> [type] <speed> [player]
speedCommandUsage1=/<command> <speed>
speedCommandUsage1Description=設定你的飛行或走路速度
@@ -1253,22 +1255,24 @@ teleportationDisabledWarning=§6你必須先啟用傳送,其他玩家才能傳
teleportationEnabled=§a已啟用§6傳送。
teleportationEnabledFor=§a已啟用 {0}§6 的傳送。
teleportAtoB=§c{0}§6 將你傳送到 §c{1}§6。
teleportBottom=§6正在傳送到底部。
teleportDisabled=§c{0} §4已停用傳送。
teleportHereRequest=§c{0}§6 請求你傳送到他那裡 (請注意安全)。
teleportHome=§6正在傳送到 §c{0}§6。
teleporting=§6正在傳送……
teleportInvalidLocation=座標的數值不得超過 30000000
teleportNewPlayerError=§4傳送新玩家失敗!
teleportNoAcceptPermission=§c{0} §4沒有接受該傳送的權限。
teleportNoAcceptPermission=§c{0} §4沒有接受此傳送的權限。
teleportRequest=§c{0}§6 請求傳送到你這裡 (請注意安全)。
teleportRequestAllCancelled=§6所有傳送請求已取消。
teleportRequestCancelled=§6你的傳送請求 §c{0}§6 已取消。
teleportRequestSpecificCancelled=§c{0}§6 的傳送請求已取消。
teleportRequestTimeoutInfo=§6該請求將在 §c{0} 秒§6內取消。
teleportRequestTimeoutInfo=§6此請求將在 §c{0} 秒§6內取消。
teleportTop=§6正在傳送到頂部。
teleportToPlayer=§6正在傳送到 §c{0}§6。
teleportOffline=§6玩家 §c{0}§6 離線。你可以 /otp 傳送他們。
tempbanExempt=§4你無法暫時封禁該玩家。
teleportOfflineUnknown=§6無法找到 §c{0}§6 已知的最後位置。
tempbanExempt=§4你無法暫時封禁此玩家。
tempbanExemptOffline=§4你無法暫時封禁離線玩家。
tempbanJoin=你被伺服器暫時封禁 {0}。原因:{1}
tempBanned=§c你被伺服器暫時封禁§r {0}§c:\n§r{2}
@@ -1288,7 +1292,7 @@ thunderCommandUsage1Description=在指定持續時間內啟用或停用閃電
thunderDuration=§6你持續 §c{0} §6了你所在世界的閃電§c {1} §6秒。
timeBeforeHeal=§4治療冷卻:§c{0}§4。
timeBeforeTeleport=§4傳送冷卻:§c{0}§4。
timeCommandDescription=顯示或更改世界時間,預設為目前的世界。
timeCommandDescription=顯示或變更世界時間,預設為目前的世界。
timeCommandUsage=/<command> [set|add] [day|night|dawn|17\:30|4pm|4000ticks] [worldname|all]
timeCommandUsage1=/<command>
timeCommandUsage1Description=顯示所有世界的時間
@@ -1309,7 +1313,7 @@ toggleshoutCommandDescription=切換是否在喊話模式下聊天
toggleshoutCommandUsage=/<command> [player] [on|off]
toggleshoutCommandUsage1=/<command> [player]
toggleshoutCommandUsage1Description=切換你或指定玩家的喊話模式
topCommandDescription=傳送到目前位置的最高處。
topCommandDescription=傳送到你目前位置的最高點。
topCommandUsage=/<command>
totalSellableAll=§a所有可賣出物品和方塊的價值為 §c{1}§a。
totalSellableBlocks=§a所有可賣出方塊的價值為 §c{1}§a。
@@ -1439,7 +1443,7 @@ unlinkCommandUsage1Description=將你的 Minecraft 與目前的 Discord 帳號
unmutedPlayer=§6玩家§c {0} §6被解除禁言。
unsafeTeleportDestination=§4傳送目的地不安全,且安全傳送處於停用狀態。
unsupportedBrand=§4你正在運行的伺服器版本沒有為此功能提供支援。
unsupportedFeature=§4目前伺服器版本不支援該功能。
unsupportedFeature=§4目前伺服器版本不支援此功能。
unvanishedReload=§4插件重新載入迫使你的隱身模式失效。
upgradingFilesError=更新檔案時發生錯誤。
uptime=§6已運行時間:§c{0}
@@ -1508,8 +1512,8 @@ warpinfoCommandUsage1Description=提供有關地標的資訊
warpingTo=§6傳送到地標 §c{0}§6。
warpList={0}
warpListPermission=§4你沒有列出地標的權限。
warpNotExist=§4該地標不存在。
warpOverwrite=§4你不能覆蓋該地標。
warpNotExist=§4此地標不存在。
warpOverwrite=§4你不能覆蓋此地標。
warps=§6地標:§r{0}
warpsCount=§6總共有§c {0} §6個地標。顯示頁數:第 §c{1} §6頁,共 §c{2}§6 頁。
weatherCommandDescription=設定天氣。
@@ -1517,7 +1521,7 @@ weatherCommandUsage=/<command> <storm/sun> [duration]
weatherCommandUsage1=/<command> <storm|sun> [duration]
weatherCommandUsage1Description=設定天氣狀態持續時間
warpSet=§6已設定地標 §c{0} §6。
warpUsePermission=§4你沒有使用該地標的權限。
warpUsePermission=§4你沒有使用此地標的權限。
weatherInvalidWorld=找不到名為 {0} 的世界!
weatherSignStorm=§6天氣:§c暴風雨(雪)§6。
weatherSignSun=§6天氣:§c晴天§6。
@@ -30,8 +30,8 @@ public class EconomyTest {
} catch (final IOException ex) {
Assert.fail("IOException");
}
server.addPlayer(new OfflinePlayer(PLAYERNAME, ess.getServer()));
server.addPlayer(new OfflinePlayer(PLAYERNAME2, ess.getServer()));
server.addPlayer(new OfflinePlayerStub(PLAYERNAME, ess.getServer()));
server.addPlayer(new OfflinePlayerStub(PLAYERNAME2, ess.getServer()));
}
// only one big test, since we use static instances
@@ -14,7 +14,7 @@ import static org.junit.Assert.assertEquals;
public class MessagingTest {
private final OfflinePlayer base1;
private final OfflinePlayerStub base1;
private final Essentials ess;
private final FakeServer server;
@@ -30,7 +30,7 @@ public class StorageTest {
public void testOldUserdata() {
final ExecuteTimer ext = new ExecuteTimer();
ext.start();
final OfflinePlayer base1 = server.createPlayer("testPlayer1");
final OfflinePlayerStub base1 = server.createPlayer("testPlayer1");
server.addPlayer(base1);
ext.mark("fake user created");
final UserData user = ess.getUser(base1);
@@ -9,7 +9,7 @@ import org.bukkit.plugin.InvalidDescriptionException;
import java.io.IOException;
public class ToggleTest extends TestCase {
private final OfflinePlayer base1;
private final OfflinePlayerStub base1;
private final Essentials ess;
private final FakeServer server;
@@ -9,7 +9,7 @@ import java.io.IOException;
import java.math.BigDecimal;
public class UserTest extends TestCase {
private final OfflinePlayer base1;
private final OfflinePlayerStub base1;
private final Essentials ess;
private final FakeServer server;
@@ -34,7 +34,7 @@ public class UserTest extends TestCase {
}
public void testUpdate() {
final OfflinePlayer base1alt = server.createPlayer(base1.getName());
final OfflinePlayerStub base1alt = server.createPlayer(base1.getName());
assertEquals(base1alt, ess.getUser(base1alt).getBase());
}
@@ -43,7 +43,7 @@ public class UserTest extends TestCase {
final Location loc = base1.getLocation();
loc.setWorld(server.getWorlds().get(0));
user.setHome("home", loc);
final OfflinePlayer base2 = server.createPlayer(base1.getName());
final OfflinePlayerStub base2 = server.createPlayer(base1.getName());
final User user2 = ess.getUser(base2);
final Location home = user2.getHome(loc);
@@ -192,6 +192,10 @@ public class EssentialsAntiBuildListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onItemFrameInteract(final PlayerInteractEntityEvent event) {
if (event.getPlayer().hasMetadata("NPC")) {
return;
}
final User user = ess.getUser(event.getPlayer());
if (!(event.getRightClicked() instanceof ItemFrame)) {
@@ -221,6 +225,10 @@ public class EssentialsAntiBuildListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onArmorStandInteract(final PlayerInteractAtEntityEvent event) {
if (event.getPlayer().hasMetadata("NPC")) {
return;
}
final User user = ess.getUser(event.getPlayer());
if (!(event.getRightClicked() instanceof ArmorStand)) {
@@ -319,6 +327,10 @@ public class EssentialsAntiBuildListener implements Listener {
@EventHandler(priority = EventPriority.LOW)
public void onPlayerInteract(final PlayerInteractEvent event) {
if (event.getPlayer().hasMetadata("NPC")) {
return;
}
// Do not return if cancelled, because the interact event has 2 cancelled states.
final User user = ess.getUser(event.getPlayer());
final ItemStack item = event.getItem();
@@ -415,6 +427,9 @@ public class EssentialsAntiBuildListener implements Listener {
private class PlayerPickupItemListener implements Listener {
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
public void onPlayerPickupItem(final PlayerPickupItemEvent event) {
if (event.getPlayer().hasMetadata("NPC")) {
return;
}
final User user = ess.getUser(event.getPlayer());
final ItemStack item = event.getItem().getItemStack();
@@ -104,15 +104,13 @@ public abstract class AbstractChatHandler {
// Local, shout and question chat types are only enabled when there's a valid radius
if (chat.getRadius() > 0 && event.getMessage().length() > 0) {
if (event.getMessage().length() > 1 && ((chat.getType() == ChatType.SHOUT && event.getMessage().charAt(0) == ess.getSettings().getChatShout()) || (chat.getType() == ChatType.QUESTION && event.getMessage().charAt(0) == ess.getSettings().getChatQuestion()))) {
event.setMessage(event.getMessage().substring(1));
}
if (chat.getType() == ChatType.UNKNOWN) {
if (user.isToggleShout() && event.getMessage().charAt(0) == ess.getSettings().getChatShout()) {
event.setMessage(event.getMessage().substring(1));
}
format = tl("chatTypeLocal").concat(format);
} else {
if (event.getMessage().charAt(0) == ess.getSettings().getChatShout() || (event.getMessage().charAt(0) == ess.getSettings().getChatQuestion() && ess.getSettings().isChatQuestionEnabled())) {
event.setMessage(event.getMessage().substring(1));
}
format = tl(chat.getType().key() + "Format", format);
}
}
@@ -293,16 +291,23 @@ public abstract class AbstractChatHandler {
return ChatType.UNKNOWN;
}
final char shoutPrefix = ess.getSettings().getChatShout();
final char questionPrefix = ess.getSettings().getChatQuestion();
final char prefix = message.charAt(0);
if (prefix == ess.getSettings().getChatShout()) {
final boolean singleChar = message.length() == 1;
if (singleChar) {
if (user.isToggleShout()) {
return ChatType.UNKNOWN;
return ChatType.SHOUT;
}
return message.length() > 1 ? ChatType.SHOUT : ChatType.UNKNOWN;
} else if (ess.getSettings().isChatQuestionEnabled() && prefix == ess.getSettings().getChatQuestion()) {
return message.length() > 1 ? ChatType.QUESTION : ChatType.UNKNOWN;
} else if (user.isToggleShout()) {
return message.length() > 1 ? ChatType.SHOUT : ChatType.UNKNOWN;
return ChatType.UNKNOWN;
}
if (prefix == questionPrefix && ess.getSettings().isChatQuestionEnabled()) {
return ChatType.QUESTION;
} else if (prefix == shoutPrefix || user.isToggleShout()) {
return ChatType.SHOUT;
} else {
return ChatType.UNKNOWN;
}
+1 -1
View File
@@ -56,7 +56,7 @@ and finally then clicking "Yes, do it!".
Intents", and then click "Save Changes". This prevents other people from adding your bot and also
allows your bot to use more Discord features.
> ![Update Bot Settings](https://i.imgur.com/eIegfCC.gif)
> Uncheck `Public Bot` -> Check `Presence Intent` -> Check `Server Members Intent` -> Check `Message Content Invent` -> Save Changes`
> Uncheck `Public Bot` -> Check `Presence Intent` -> Check `Server Members Intent` -> Check `Message Content Intent` -> Save Changes`
6. Finally, you'll need to copy your bot's token and save it for a later step. To copy your bot's token,
click the blue "Reset Token" button right of your bot's icon, then click "Yes, do it!", and finally
+10 -5
View File
@@ -4,12 +4,14 @@ plugins {
dependencies {
compileOnly project(':EssentialsX')
implementation('net.dv8tion:JDA:4.4.1_353') {
implementation('net.dv8tion:JDA:5.0.0-beta.12') {
exclude(module: 'opus-java')
}
implementation 'com.vdurmont:emoji-java:5.1.1'
implementation 'club.minnced:discord-webhooks:0.7.2'
compileOnly 'org.apache.logging.log4j:log4j-core:2.15.0'
implementation 'com.github.MinnDevelopment:emoji-java:v6.1.0'
implementation('club.minnced:discord-webhooks:0.8.2') {
exclude(module: 'okhttp')
}
compileOnly 'org.apache.logging.log4j:log4j-core:2.17.1'
compileOnly 'me.clip:placeholderapi:2.10.9'
}
@@ -20,15 +22,17 @@ shadowJar {
include(dependency('com.neovisionaries:nv-websocket-client'))
include(dependency('com.squareup.okhttp3:okhttp'))
include(dependency('com.squareup.okio:okio'))
include(dependency('com.squareup.okio:okio-jvm'))
include(dependency('org.apache.commons:commons-collections4'))
include(dependency('net.sf.trove4j:trove4j'))
include(dependency('com.fasterxml.jackson.core:jackson-databind'))
include(dependency('com.fasterxml.jackson.core:jackson-core'))
include(dependency('com.fasterxml.jackson.core:jackson-annotations'))
include(dependency('org.slf4j:slf4j-api'))
include(dependency('org.jetbrains.kotlin:kotlin-stdlib'))
// Emoji
include(dependency('com.vdurmont:emoji-java'))
include(dependency('com.github.MinnDevelopment:emoji-java'))
include(dependency('org.json:json'))
// discord-webhooks
@@ -47,6 +51,7 @@ shadowJar {
relocate 'com.fasterxml.jackson.core', 'net.essentialsx.dep.com.fasterxml.jackson.core'
relocate 'com.fasterxml.jackson.annotation', 'net.essentialsx.dep.com.fasterxml.jackson.annotation'
relocate 'gnu.trove', 'net.essentialsx.dep.gnu.trove'
relocate 'kotlin', 'net.essentialsx.dep.garbage.kotlin'
// Emoji
relocate 'com.vdurmont.emoji', 'net.essentialsx.dep.com.vdurmont.emoji'
@@ -168,6 +168,10 @@ public class DiscordSettings implements IConf {
return consoleFilter;
}
public int getConsoleSkipDelay() {
return config.getInt("console.skip-delay", 2);
}
public boolean isShowAvatar() {
return config.getBoolean("show-avatar", false);
}
@@ -472,7 +476,7 @@ public class DiscordSettings implements IConf {
activityType = Activity.ActivityType.valueOf(activity);
}
} catch (IllegalArgumentException e) {
activityType = Activity.ActivityType.DEFAULT;
activityType = Activity.ActivityType.PLAYING;
}
if (activityType != null) {
statusActivity = Activity.of(activityType, config.getString("presence.message", "Minecraft"));
@@ -1,6 +1,5 @@
package net.essentialsx.discord;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.send.WebhookMessage;
import club.minnced.discord.webhook.send.WebhookMessageBuilder;
@@ -11,14 +10,14 @@ import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.Webhook;
import net.dv8tion.jda.api.events.ShutdownEvent;
import net.dv8tion.jda.api.hooks.EventListener;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji;
import net.dv8tion.jda.api.events.session.ShutdownEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.cache.CacheFlag;
import net.ess3.nms.refl.providers.AchievementListenerProvider;
import net.ess3.nms.refl.providers.AdvancementListenerProvider;
@@ -46,6 +45,7 @@ import net.essentialsx.discord.listeners.BukkitChatListener;
import net.essentialsx.discord.util.ConsoleInjector;
import net.essentialsx.discord.util.DiscordUtil;
import net.essentialsx.discord.util.MessageUtil;
import net.essentialsx.discord.util.WrappedWebhookClient;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.HandlerList;
@@ -79,11 +79,11 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
private JDA jda;
private Guild guild;
private TextChannel primaryChannel;
private WebhookClient consoleWebhook;
private WrappedWebhookClient consoleWebhook;
private String lastConsoleId;
private final Map<String, MessageType> registeredTypes = new HashMap<>();
private final Map<MessageType, String> typeToChannelId = new HashMap<>();
private final Map<String, WebhookClient> channelIdToWebhook = new HashMap<>();
private final Map<String, WrappedWebhookClient> channelIdToWebhook = new HashMap<>();
private ConsoleInjector injector;
private DiscordCommandDispatcher commandDispatcher;
private InteractionControllerImpl interactionController;
@@ -140,7 +140,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
final String webhookChannelId = typeToChannelId.get(event.getType());
if (webhookChannelId != null) {
final WebhookClient client = channelIdToWebhook.get(webhookChannelId);
final WrappedWebhookClient client = channelIdToWebhook.get(webhookChannelId);
if (client != null) {
final String avatarUrl = event.getAvatarUrl() != null ? event.getAvatarUrl() : jda.getSelfUser().getAvatarUrl();
final String name = event.getName() != null ? event.getName() : guild.getSelfMember().getEffectiveName();
@@ -154,7 +154,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
return;
}
channel.sendMessage(strippedContent)
.allowedMentions(groupMentions ? null : DiscordUtil.NO_GROUP_MENTIONS)
.setAllowedMentions(groupMentions ? null : DiscordUtil.NO_GROUP_MENTIONS)
.queue();
}
@@ -169,7 +169,8 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
jda = JDABuilder.createDefault(plugin.getSettings().getBotToken())
.addEventListeners(new DiscordListener(this))
.enableCache(CacheFlag.EMOTE)
.enableIntents(GatewayIntent.MESSAGE_CONTENT)
.enableCache(CacheFlag.EMOJI)
.disableCache(CacheFlag.MEMBER_OVERRIDES, CacheFlag.VOICE_STATE)
.setContextEnabled(false)
.build()
@@ -205,7 +206,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
}
// Load emotes into cache, JDA will handle updates from here on out.
guild.retrieveEmotes().queue();
guild.retrieveEmojis().queue();
updatePrimaryChannel();
@@ -323,10 +324,10 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
public void updatePrimaryChannel() {
TextChannel channel = guild.getTextChannelById(plugin.getSettings().getPrimaryChannelId());
if (channel == null) {
channel = guild.getDefaultChannel();
if (channel == null) {
if (!(guild.getDefaultChannel() instanceof TextChannel)) {
throw new RuntimeException(tl("discordErrorNoPerms"));
}
channel = (TextChannel) guild.getDefaultChannel();
logger.warning(tl("discordErrorNoPrimary", channel.getName()));
}
@@ -337,7 +338,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
}
public String parseMessageEmotes(String message) {
for (final Emote emote : guild.getEmoteCache()) {
for (final RichCustomEmoji emote : guild.getEmojiCache()) {
message = message.replaceAll(":" + Pattern.quote(emote.getName()) + ":", emote.getAsMention());
}
return message;
@@ -362,7 +363,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
public void updateTypesRelay() {
if (!getSettings().isShowAvatar() && !getSettings().isShowName() && !getSettings().isShowDisplayName()) {
for (WebhookClient webhook : channelIdToWebhook.values()) {
for (WrappedWebhookClient webhook : channelIdToWebhook.values()) {
webhook.close();
}
typeToChannelId.clear();
@@ -382,7 +383,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
final Webhook webhook = DiscordUtil.getOrCreateWebhook(channel, DiscordUtil.ADVANCED_RELAY_NAME).join();
if (webhook == null) {
final WebhookClient current = channelIdToWebhook.get(channel.getId());
final WrappedWebhookClient current = channelIdToWebhook.get(channel.getId());
if (current != null) {
current.close();
}
@@ -483,15 +484,13 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
shutdownConsoleRelay(true);
for (WebhookClient webhook : channelIdToWebhook.values()) {
for (WrappedWebhookClient webhook : channelIdToWebhook.values()) {
webhook.close();
}
// Unregister leftover jda listeners
for (Object obj : jda.getRegisteredListeners()) {
if (!(obj instanceof EventListener)) { // Yeah bro I wish I knew too :/
jda.removeEventListener(obj);
}
jda.removeEventListener(obj);
}
// Unregister Bukkit Events
@@ -512,7 +511,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
// Wait for JDA to wrap it up
future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
logger.warning("JDA took longer than expected to shutdown, this may have caused some problems.");
logger.log(Level.WARNING, "JDA took longer than expected to shutdown, this may have caused some problems.", e);
} finally {
jda = null;
}
@@ -588,7 +587,7 @@ public class JDADiscordService implements DiscordService, IEssentialsModule {
return plugin.getSettings();
}
public WebhookClient getConsoleWebhook() {
public WrappedWebhookClient getConsoleWebhook() {
return consoleWebhook;
}
@@ -4,8 +4,8 @@ import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.commands.EssentialsCommand;
import com.earth2me.essentials.commands.NotEnoughArgumentsException;
import com.vdurmont.emoji.EmojiParser;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji;
import net.essentialsx.discord.JDADiscordService;
import net.essentialsx.discord.util.DiscordUtil;
import net.essentialsx.discord.util.MessageUtil;
@@ -48,7 +48,7 @@ public class Commanddiscordbroadcast extends EssentialsCommand {
}
channel.sendMessage(jda.parseMessageEmotes(message))
.allowedMentions(sender.isAuthorized("essentials.discordbroadcast.ping", ess) ? null : DiscordUtil.NO_GROUP_MENTIONS)
.setAllowedMentions(sender.isAuthorized("essentials.discordbroadcast.ping", ess) ? null : DiscordUtil.NO_GROUP_MENTIONS)
.queue();
sender.sendMessage(tl("discordbroadcastSent", "#" + EmojiParser.parseToAliases(channel.getName())));
@@ -65,12 +65,12 @@ public class Commanddiscordbroadcast extends EssentialsCommand {
final String curArg = args[args.length - 1];
if (!curArg.isEmpty() && curArg.charAt(0) == ':' && (curArg.length() == 1 || curArg.charAt(curArg.length() - 1) != ':')) {
final JDADiscordService jda = (JDADiscordService) module;
if (jda.getGuild().getEmoteCache().isEmpty()) {
if (jda.getGuild().getEmojiCache().isEmpty()) {
return Collections.emptyList();
}
final List<String> completions = new ArrayList<>();
for (final Emote emote : jda.getGuild().getEmoteCache()) {
for (final RichCustomEmoji emote : jda.getGuild().getEmojiCache()) {
completions.add(":" + emote.getName() + ":");
}
return completions;
@@ -1,12 +1,13 @@
package net.essentialsx.discord.interactions;
import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.essentialsx.api.v2.services.discord.InteractionChannel;
public class InteractionChannelImpl implements InteractionChannel {
private final GuildChannel channel;
private final GuildMessageChannel channel;
public InteractionChannelImpl(GuildChannel channel) {
public InteractionChannelImpl(GuildMessageChannel channel) {
this.channel = channel;
}
@@ -1,12 +1,14 @@
package net.essentialsx.discord.interactions;
import com.earth2me.essentials.utils.StringUtil;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.exceptions.ErrorResponseException;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.requests.ErrorResponse;
import net.essentialsx.api.v2.services.discord.InteractionCommand;
import net.essentialsx.api.v2.services.discord.InteractionCommandArgument;
@@ -42,7 +44,7 @@ public class InteractionControllerImpl extends ListenerAdapter implements Intera
}
@Override
public void onSlashCommand(@NotNull SlashCommandEvent event) {
public void onSlashCommandInteraction(@NotNull SlashCommandInteractionEvent event) {
if (event.getGuild() == null || event.getMember() == null || !commandMap.containsKey(event.getName())) {
return;
}
@@ -77,7 +79,7 @@ public class InteractionControllerImpl extends ListenerAdapter implements Intera
for (final InteractionCommand command : batchRegistrationQueue.values()) {
// German is quite the language
final String description = StringUtil.abbreviate(command.getDescription(), 100);
final CommandData data = new CommandData(command.getName(), description);
final SlashCommandData data = Commands.slash(command.getName(), description);
if (command.getArguments() != null) {
for (final InteractionCommandArgument argument : command.getArguments()) {
// German doesn't support spaces between words
@@ -132,7 +134,7 @@ public class InteractionControllerImpl extends ListenerAdapter implements Intera
return;
}
final CommandData data = new CommandData(command.getName(), command.getDescription());
final SlashCommandData data = Commands.slash(command.getName(), command.getDescription());
if (command.getArguments() != null) {
for (final InteractionCommandArgument argument : command.getArguments()) {
data.addOption(OptionType.valueOf(argument.getType().name()), argument.getName(), argument.getDescription(), argument.isRequired());
@@ -2,10 +2,10 @@ package net.essentialsx.discord.interactions;
import com.earth2me.essentials.utils.FormatUtil;
import com.google.common.base.Joiner;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.interactions.commands.OptionMapping;
import net.dv8tion.jda.api.utils.messages.MessageEditBuilder;
import net.essentialsx.api.v2.services.discord.InteractionChannel;
import net.essentialsx.api.v2.services.discord.InteractionEvent;
import net.essentialsx.api.v2.services.discord.InteractionMember;
@@ -23,11 +23,11 @@ import java.util.logging.Logger;
*/
public class InteractionEventImpl implements InteractionEvent {
private final static Logger logger = EssentialsDiscord.getWrappedLogger();
private final SlashCommandEvent event;
private final SlashCommandInteractionEvent event;
private final InteractionMember member;
private final List<String> replyBuffer = new ArrayList<>();
public InteractionEventImpl(final SlashCommandEvent jdaEvent) {
public InteractionEventImpl(final SlashCommandInteractionEvent jdaEvent) {
this.event = jdaEvent;
this.member = new InteractionMemberImpl(jdaEvent.getMember());
}
@@ -39,7 +39,7 @@ public class InteractionEventImpl implements InteractionEvent {
String reply = Joiner.on('\n').join(replyBuffer);
reply = reply.substring(0, Math.min(Message.MAX_CONTENT_LENGTH, reply.length()));
event.getHook().editOriginal(
new MessageBuilder()
new MessageEditBuilder()
.setContent(reply)
.setAllowedMentions(DiscordUtil.NO_GROUP_MENTIONS).build())
.queue(null, error -> logger.log(Level.SEVERE, "Error while editing command interaction response", error));
@@ -77,7 +77,7 @@ public class InteractionEventImpl implements InteractionEvent {
@Override
public InteractionChannel getChannelArgument(String key) {
final OptionMapping mapping = event.getOption(key);
return mapping == null ? null : new InteractionChannelImpl(mapping.getAsGuildChannel());
return mapping == null ? null : new InteractionChannelImpl(mapping.getAsChannel().asGuildMessageChannel());
}
@Override
@@ -2,8 +2,8 @@ package net.essentialsx.discord.interactions;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.PrivateChannel;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.concrete.PrivateChannel;
import net.essentialsx.api.v2.services.discord.InteractionMember;
import net.essentialsx.api.v2.services.discord.InteractionRole;
import net.essentialsx.discord.util.DiscordUtil;
@@ -119,7 +119,7 @@ public class BukkitListener implements Listener {
}
public void sendJoinQuitMessage(final Player player, final String message, MessageType type) {
int userCount = jda.getPlugin().getEss().getUsers().getUserCount();
int onlineCount = jda.getPlugin().getEss().getOnlinePlayers().size();
final MessageFormat format;
switch (type.getKey()) {
case "join":
@@ -130,7 +130,7 @@ public class BukkitListener implements Listener {
break;
default: // So that it will always be initialised. Other options shouldn't be possible.
format = jda.getSettings().getQuitFormat(player);
userCount = userCount - 1;
onlineCount = onlineCount - 1;
break;
}
@@ -139,8 +139,8 @@ public class BukkitListener implements Listener {
MessageUtil.sanitizeDiscordMarkdown(player.getName()),
MessageUtil.sanitizeDiscordMarkdown(player.getDisplayName()),
MessageUtil.sanitizeDiscordMarkdown(message),
jda.getPlugin().getEss().getOnlinePlayers().size(),
userCount),
onlineCount,
jda.getPlugin().getEss().getUsers().getUserCount()),
player);
}
@@ -1,6 +1,7 @@
package net.essentialsx.discord.listeners;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.essentialsx.discord.JDADiscordService;
import net.essentialsx.discord.util.DiscordCommandSender;
@@ -18,7 +19,11 @@ public class DiscordCommandDispatcher extends ListenerAdapter {
}
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
public void onMessageReceived(@NotNull MessageReceivedEvent event) {
if (event.getMessage().getChannelType() != ChannelType.TEXT) {
return;
}
if (jda.getConsoleWebhook() != null && event.getChannel().getId().equals(channelId)) {
if ((event.isWebhookMessage() || event.getAuthor().isBot()) && (!jda.getSettings().isConsoleBotCommandRelay() || DiscordUtil.ACTIVE_WEBHOOKS.contains(event.getAuthor().getId()) || event.getAuthor().getId().equals(event.getGuild().getSelfMember().getId()))) {
return;
@@ -6,7 +6,8 @@ import com.vdurmont.emoji.EmojiParser;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.ess3.api.IUser;
import net.essentialsx.api.v2.events.discord.DiscordRelayEvent;
@@ -36,7 +37,11 @@ public class DiscordListener extends ListenerAdapter {
}
@Override
public void onGuildMessageReceived(@NotNull GuildMessageReceivedEvent event) {
public void onMessageReceived(@NotNull MessageReceivedEvent event) {
if (event.getMessage().getChannelType() != ChannelType.TEXT) {
return;
}
if (event.getAuthor().isBot() && !event.isWebhookMessage() && (!plugin.getSettings().isShowBotMessages() || event.getAuthor().getId().equals(plugin.getJda().getSelfUser().getId()))) {
return;
}
@@ -120,7 +125,7 @@ public class DiscordListener extends ListenerAdapter {
// Do not create the event specific objects if there are no listeners
if (DiscordRelayEvent.getHandlerList().getRegisteredListeners().length != 0) {
final DiscordRelayEvent relayEvent = new DiscordRelayEvent(
new InteractionMemberImpl(member), new InteractionChannelImpl(event.getChannel()),
new InteractionMemberImpl(member), new InteractionChannelImpl(event.getGuildChannel()),
Collections.unmodifiableList(keys), event.getMessage().getContentRaw(), formattedMessage, viewers);
Bukkit.getPluginManager().callEvent(relayEvent);
if (relayEvent.isCancelled()) {
@@ -16,6 +16,8 @@ import org.bukkit.Bukkit;
import java.time.Instant;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import static com.earth2me.essentials.I18n.tl;
@@ -24,16 +26,41 @@ import static com.earth2me.essentials.I18n.tl;
public class ConsoleInjector extends AbstractAppender {
private final static java.util.logging.Logger logger = EssentialsDiscord.getWrappedLogger();
private final static long QUEUE_PROCESS_PERIOD_SECONDS = 2;
private final JDADiscordService jda;
private final BlockingQueue<String> messageQueue = new LinkedBlockingQueue<>();
private final int taskId;
private boolean removed = false;
private final AtomicLong lastRateLimitTime = new AtomicLong(0);
private final AtomicInteger recentRateLimit = new AtomicInteger(0);
private final AtomicInteger totalBackoffEvents = new AtomicInteger();
public ConsoleInjector(JDADiscordService jda) {
super("EssentialsX-ConsoleInjector", null, null, false);
this.jda = jda;
((Logger) LogManager.getRootLogger()).addAppender(this);
taskId = Bukkit.getScheduler().runTaskTimerAsynchronously(jda.getPlugin(), () -> {
// Check to see if we're supposed to be backing off, preform backoff if the case.
if (recentRateLimit.get() < 0) {
if (totalBackoffEvents.get() * 20 >= jda.getSettings().getConsoleSkipDelay() * 60) {
logger.warning("EssXBackoff: Reached console skip delay, attempt to skip");
jda.getConsoleWebhook().abandonRequests();
messageQueue.clear();
totalBackoffEvents.set(0);
recentRateLimit.set(0);
lastRateLimitTime.set(0);
return;
}
final int backoff = recentRateLimit.incrementAndGet();
if (jda.isDebug()) {
logger.warning("EssXBackoff: Webhook backoff in progress, skipping queue processing. Resuming in " + Math.abs(backoff) + " cycles.");
}
return;
}
final StringBuilder buffer = new StringBuilder();
String curLine;
while ((curLine = messageQueue.peek()) != null) {
@@ -47,7 +74,7 @@ public class ConsoleInjector extends AbstractAppender {
if (buffer.length() != 0) {
sendMessage(buffer.toString());
}
}, 20, 40).getTaskId();
}, 20, 20 * QUEUE_PROCESS_PERIOD_SECONDS).getTaskId();
}
private void sendMessage(String content) {
@@ -70,6 +97,33 @@ public class ConsoleInjector extends AbstractAppender {
return;
}
if (entry.startsWith("EssXBackoff: ")) {
return;
}
if (event.getLoggerName().contains("club.minnced.discord.webhook.WebhookClient") && entry.startsWith("Encountered 429, retrying after ")) {
if (recentRateLimit.get() >= 0) {
recentRateLimit.incrementAndGet();
}
if (lastRateLimitTime.get() == 0 || System.currentTimeMillis() - lastRateLimitTime.get() > 5000) {
lastRateLimitTime.set(System.currentTimeMillis());
// A negative value would mean the timer is current preforming a backoff, don't stop it.
if (recentRateLimit.get() >= 0) {
recentRateLimit.set(0);
}
} else if (recentRateLimit.get() >= 2) {
// Start the webhook backoff, defaulting to 20s, which should reset our bucket.
if (jda.isDebug()) {
totalBackoffEvents.getAndIncrement();
logger.warning("EssXBackoff: Beginning Webhook Backoff");
}
recentRateLimit.set(-20);
}
return;
}
if (!jda.getSettings().getConsoleFilters().isEmpty()) {
for (final Pattern pattern : jda.getSettings().getConsoleFilters()) {
if (pattern.matcher(entry).find()) {
@@ -78,12 +132,14 @@ public class ConsoleInjector extends AbstractAppender {
}
}
final String loggerName = event.getLoggerName();
if (!loggerName.isEmpty() && !loggerName.contains(".")) {
entry = "[" + event.getLoggerName() + "] " + entry;
final String[] loggerNameSplit = event.getLoggerName().split("\\.");
final String loggerName = loggerNameSplit[loggerNameSplit.length - 1].trim();
if (!loggerName.isEmpty()) {
entry = "[" + loggerName + "] " + entry;
}
messageQueue.addAll(Splitter.fixedLength(Message.MAX_CONTENT_LENGTH - 2).splitToList(
messageQueue.addAll(Splitter.fixedLength(Message.MAX_CONTENT_LENGTH - 50).splitToList(
MessageUtil.formatMessage(jda.getSettings().getConsoleFormat(),
TimeFormat.TIME_LONG.format(Instant.now()),
event.getLevel().name(),
@@ -94,6 +150,9 @@ public class ConsoleInjector extends AbstractAppender {
((Logger) LogManager.getRootLogger()).removeAppender(this);
Bukkit.getScheduler().cancelTask(taskId);
messageQueue.clear();
if (jda.getConsoleWebhook() != null && !jda.getConsoleWebhook().isShutdown()) {
jda.getConsoleWebhook().close();
}
removed = true;
}
@@ -1,7 +1,6 @@
package net.essentialsx.discord.util;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.send.AllowedMentions;
import com.earth2me.essentials.utils.DownsampleUtil;
import com.earth2me.essentials.utils.FormatUtil;
@@ -13,8 +12,8 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.Webhook;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.essentialsx.api.v2.events.discord.DiscordMessageEvent;
import net.essentialsx.api.v2.services.discord.MessageType;
import net.essentialsx.discord.JDADiscordService;
@@ -39,7 +38,7 @@ public final class DiscordUtil {
final ImmutableList.Builder<Message.MentionType> types = new ImmutableList.Builder<>();
types.add(Message.MentionType.USER);
types.add(Message.MentionType.CHANNEL);
types.add(Message.MentionType.EMOTE);
types.add(Message.MentionType.EMOJI);
NO_GROUP_MENTIONS = types.build();
}
@@ -54,13 +53,8 @@ public final class DiscordUtil {
* @param client The http client of the webhook.
* @return The {@link WebhookClient}.
*/
public static WebhookClient getWebhookClient(long id, String token, OkHttpClient client) {
return new WebhookClientBuilder(id, token)
.setWait(false)
.setAllowedMentions(AllowedMentions.none())
.setHttpClient(client)
.setDaemon(true)
.build();
public static WrappedWebhookClient getWebhookClient(long id, String token, OkHttpClient client) {
return new WrappedWebhookClient(id, token, client);
}
/**
@@ -0,0 +1,88 @@
package net.essentialsx.discord.util;
import club.minnced.discord.webhook.WebhookClient;
import club.minnced.discord.webhook.WebhookClientBuilder;
import club.minnced.discord.webhook.receive.ReadonlyMessage;
import club.minnced.discord.webhook.send.AllowedMentions;
import club.minnced.discord.webhook.send.WebhookMessage;
import club.minnced.discord.webhook.util.ThreadPools;
import net.essentialsx.discord.EssentialsDiscord;
import okhttp3.OkHttpClient;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
public class WrappedWebhookClient {
private final static Logger logger = EssentialsDiscord.getWrappedLogger();
private final static MethodHandle queueGetter;
static {
MethodHandle queueGetter1;
try {
final Field queueField = WebhookClient.class.getDeclaredField("queue");
queueField.setAccessible(true);
queueGetter1 = MethodHandles.lookup().unreflectGetter(queueField);
} catch (NoSuchFieldException | IllegalAccessException e) {
logger.log(Level.SEVERE, "Could not acquire queue handle", e);
queueGetter1 = null;
}
queueGetter = queueGetter1;
}
private final WebhookClient webhookClient;
private final ScheduledExecutorService executorService;
private final BlockingQueue<?> webhookQueue;
public WrappedWebhookClient(final long id, final String token, final OkHttpClient client) {
webhookClient = new WebhookClientBuilder(id, token)
.setWait(false)
.setAllowedMentions(AllowedMentions.none())
.setHttpClient(client)
.setExecutorService(executorService = ThreadPools.getDefaultPool(id, null, true))
.build();
BlockingQueue<?> queue = null;
try {
queue = queueGetter == null ? null : (BlockingQueue<?>) queueGetter.invoke(webhookClient);
} catch (Throwable e) {
e.printStackTrace();
}
webhookQueue = queue;
}
public CompletableFuture<ReadonlyMessage> send(WebhookMessage message) {
return webhookClient.send(message);
}
public boolean isShutdown() {
return webhookClient.isShutdown();
}
public void abandonRequests() {
if (webhookQueue != null) {
webhookQueue.clear();
}
}
public void close() {
// This call should close the executor service as well
webhookClient.close();
if (executorService.isTerminated()) {
return;
}
try {
if (!executorService.awaitTermination(5, TimeUnit.SECONDS)) {
throw new InterruptedException("ExecutorService did not terminate in time.");
}
} catch (InterruptedException e) {
logger.log(Level.WARNING, "Webhook (ID: " + webhookClient.getId() + ") took longer than expected to shutdown, this may have caused some problems.", e);
}
}
}
@@ -111,6 +111,8 @@ console:
# This is useful if you want to ignore certain messages from the console.
# Can also be a list of regex patterns in addition to a single regex pattern.
console-filter: ""
# The amount of minutes of delay before console messages sent to Discord should be skipped.
skip-delay: 2
# Configure which Discord channels different messages will be sent to.
# You can either use the names of the channels listed above or just the id of a channel.
@@ -68,12 +68,7 @@ public class AccountLinkManager implements IEssentialsModule, DiscordLinkService
public boolean unlinkAccount(InteractionMember member) {
Preconditions.checkNotNull(member, "member cannot be null");
if (!isLinked(member.getId())) {
return false;
}
removeAccount(member, DiscordLinkStatusChangeEvent.Cause.UNSYNC_API);
return true;
return isLinked(member.getId()) && removeAccount(member, DiscordLinkStatusChangeEvent.Cause.UNSYNC_API);
}
public boolean removeAccount(final InteractionMember member, final DiscordLinkStatusChangeEvent.Cause cause) {
@@ -82,10 +77,11 @@ public class AccountLinkManager implements IEssentialsModule, DiscordLinkService
ensureAsync(() -> {
final IUser user = ess.getEss().getUser(uuid);
ensureSync(() -> ess.getServer().getPluginManager().callEvent(new DiscordLinkStatusChangeEvent(user, member, member.getId(), false, cause)));
roleSyncManager.unSync(uuid, member.getId());
});
return true;
}
ensureAsync(() -> roleSyncManager.unSync(uuid, member.getId()));
return false;
}
@@ -106,9 +102,10 @@ public class AccountLinkManager implements IEssentialsModule, DiscordLinkService
if (storage.remove(user.getBase().getUniqueId())) {
ess.getApi().getMemberById(id).thenAccept(member -> ensureSync(() ->
ess.getServer().getPluginManager().callEvent(new DiscordLinkStatusChangeEvent(user, member, id, false, cause))));
ensureAsync(() -> roleSyncManager.unSync(user.getBase().getUniqueId(), id));
return true;
}
ensureAsync(() -> roleSyncManager.unSync(user.getBase().getUniqueId(), id));
return false;
}
Loaded 100 of 116 files, more files were not shown because too many files have changed in this diff. Show more