diff --git a/.gitignore b/.gitignore index 80b89d99f..5821cc5da 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,9 @@ build/ /configuration/hypixel_bedwars_lobby/ /configuration/hypixel_murder_mystery_lobby/ /configuration/hypixel_skywars_lobby/ +/configuration/skyblock/garden/ *.polar +/configuration/*.schem ### Logs ### /configuration/logs/ @@ -52,7 +54,6 @@ build/ .gradle/ /server/proxy/logs/ /server/proxy/lang/ -/server/proxy/ViaLoader/ /server/proxy/plugins/ /server/proxy/forwarding.secret /server/proxy/velocity.toml diff --git a/README.md b/README.md index c3257dc5d..3036e87ca 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [Discord](https://discord.swofty.net) -A 1.21.11 Minestom-based recreation of Hypixel SkyBlock with a properly abstracted, scalable microservices architecture. +A 26.1.2 Minestom-based recreation of Hypixel SkyBlock with a properly abstracted, scalable microservices architecture. > **Note**: This implementation is under active development and is not yet production-ready. diff --git a/anticheat/README.md b/anticheat/README.md index 7861f0368..979394636 100644 --- a/anticheat/README.md +++ b/anticheat/README.md @@ -2,14 +2,14 @@ [](https://discord.gg/atlasmc) -An advanced prediction-based anticheat for both Minestom and Spigot/Bukkit servers. Features comprehensive packet tracking, movement prediction with physics simulation, and lag compensation. +An advanced prediction-based anticheat for Minestom servers. Features comprehensive packet tracking, movement prediction +with physics simulation, and lag compensation. ## Table of contents * [Features](#features) * [Getting Started](#getting-started) * [Minestom Loader](#minestom-loader) -* [Spigot Loader](#spigot-loader) * [API Usage](#api-usage) * [Custom Modifiers](#custom-modifiers) * [Player Data Storage](#player-data-storage) @@ -47,12 +47,12 @@ An advanced prediction-based anticheat for both Minestom and Spigot/Bukkit serve ### Cross-Platform Support - Full Minestom support with native packet API -- Full Spigot/Bukkit support via ProtocolLib - Unified packet abstraction layer - Platform-specific scheduler managers ## Getting Started -SwoftyAnticheat requires Java 17+ and either Minestom or Spigot/Bukkit with ProtocolLib. + +SwoftyAnticheat requires Java 25+ and Minestom. ## Minestom Loader To use SwoftyAnticheat with Minestom, create a new instance of the MinestomLoader and initialize the anticheat: @@ -67,24 +67,6 @@ SwoftyAnticheat.start(); // Do this after MinecraftServer#init() The MinestomLoader automatically registers all packet listeners using Minestom's native packet API. -## Spigot Loader -To use SwoftyAnticheat with Spigot/Bukkit, you need ProtocolLib installed. Then create a SpigotLoader instance: - -```java -public class YourPlugin extends JavaPlugin { - @Override - public void onEnable() { - SpigotLoader spigotLoader = new SpigotLoader(this); - - SwoftyAnticheat.loader(spigotLoader); - SwoftyAnticheat.values(new SwoftyValues()); - SwoftyAnticheat.start(); - } -} -``` - -The SpigotLoader uses ProtocolLib to intercept and process all relevant packets. - ## API Usage SwoftyAnticheat provides a comprehensive API for extending the anticheat with custom functionality. diff --git a/anticheat/build.gradle.kts b/anticheat/build.gradle.kts index 0663661ab..817f4426d 100644 --- a/anticheat/build.gradle.kts +++ b/anticheat/build.gradle.kts @@ -34,8 +34,6 @@ dependencies { implementation(libs.tinylog.api) implementation(libs.tinylog.impl) - compileOnly(libs.spigot.api) - compileOnly(libs.protocollib) } diff --git a/anticheat/src/main/java/net/swofty/anticheat/event/packet/UseEntityPacket.java b/anticheat/src/main/java/net/swofty/anticheat/event/packet/UseEntityPacket.java index 1fda7bdc0..3231a25e3 100644 --- a/anticheat/src/main/java/net/swofty/anticheat/event/packet/UseEntityPacket.java +++ b/anticheat/src/main/java/net/swofty/anticheat/event/packet/UseEntityPacket.java @@ -1,6 +1,7 @@ package net.swofty.anticheat.event.packet; import lombok.Getter; +import net.minestom.server.entity.PlayerHand; import net.swofty.anticheat.math.Pos; import java.util.UUID; @@ -8,27 +9,13 @@ @Getter public class UseEntityPacket extends SwoftyPacket { private final int entityId; - private final Type type; private final Pos targetPosition; - private final Hand hand; - private final boolean sneaking; + private final PlayerHand hand; - public UseEntityPacket(UUID uuid, int entityId, Type type, Pos targetPosition, Hand hand, boolean sneaking) { + public UseEntityPacket(UUID uuid, int entityId, Pos targetPosition, PlayerHand hand) { super(uuid); this.entityId = entityId; - this.type = type; this.targetPosition = targetPosition; this.hand = hand; - this.sneaking = sneaking; - } - - public enum Type { - INTERACT, - ATTACK, - INTERACT_AT - } - - public enum Hand { - MAIN_HAND, OFF_HAND } } diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerPingResponsePacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerPingResponsePacket.java index af160e333..3d18aef73 100644 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerPingResponsePacket.java +++ b/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerPingResponsePacket.java @@ -2,6 +2,7 @@ import net.minestom.server.network.packet.client.common.ClientPongPacket; import net.swofty.anticheat.engine.SwoftyPlayer; +import net.swofty.anticheat.event.packet.PingResponsePacket; import net.swofty.anticheat.event.packet.RequestPingPacket; import net.swofty.anticheat.event.packet.SwoftyPacket; import net.swofty.anticheat.loader.LoaderPacketHandler; @@ -13,7 +14,7 @@ public class MinestomHandlerPingResponsePacket @Override public SwoftyPacket buildSwoftyPacket(UUID uuid, ClientPongPacket packet) { - return new net.swofty.anticheat.event.packet.PingResponsePacket( + return new PingResponsePacket( SwoftyPlayer.players.get(uuid), packet.id() ); diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerUseEntityPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerUseEntityPacket.java index 6ce01e200..6b68ed98e 100644 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerUseEntityPacket.java +++ b/anticheat/src/main/java/net/swofty/anticheat/loader/minestom/packets/MinestomHandlerUseEntityPacket.java @@ -1,6 +1,5 @@ package net.swofty.anticheat.loader.minestom.packets; -import net.minestom.server.entity.PlayerHand; import net.minestom.server.network.packet.client.play.ClientInteractEntityPacket; import net.swofty.anticheat.event.packet.SwoftyPacket; import net.swofty.anticheat.event.packet.UseEntityPacket; @@ -14,43 +13,11 @@ public class MinestomHandlerUseEntityPacket @Override public SwoftyPacket buildSwoftyPacket(UUID uuid, ClientInteractEntityPacket packet) { - ClientInteractEntityPacket.Type type = packet.type(); - - UseEntityPacket.Type swoftyType; - UseEntityPacket.Hand hand = null; - Pos targetPos = null; - - switch (type) { - case ClientInteractEntityPacket.Interact(PlayerHand playerHand) -> { - swoftyType = UseEntityPacket.Type.INTERACT; - hand = playerHand == PlayerHand.MAIN - ? UseEntityPacket.Hand.MAIN_HAND - : UseEntityPacket.Hand.OFF_HAND; - } - case ClientInteractEntityPacket.Attack attack -> swoftyType = UseEntityPacket.Type.ATTACK; - case ClientInteractEntityPacket.InteractAt interactAt -> { - swoftyType = UseEntityPacket.Type.INTERACT_AT; - - targetPos = new Pos( - interactAt.targetX(), - interactAt.targetY(), - interactAt.targetZ() - ); - - hand = interactAt.hand() == PlayerHand.MAIN - ? UseEntityPacket.Hand.MAIN_HAND - : UseEntityPacket.Hand.OFF_HAND; - } - default -> throw new IllegalStateException("Unknown interact type: " + type.getClass()); - } - return new UseEntityPacket( uuid, packet.targetId(), - swoftyType, - targetPos, - hand, - packet.sneaking() + Pos.fromVec(packet.location()), + packet.hand() ); } diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/SpigotLoader.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/SpigotLoader.java deleted file mode 100644 index 99c39bc53..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/SpigotLoader.java +++ /dev/null @@ -1,183 +0,0 @@ -package net.swofty.anticheat.loader.spigot; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import net.swofty.anticheat.event.SwoftyEventHandler; -import net.swofty.anticheat.event.events.AnticheatPacketEvent; -import net.swofty.anticheat.event.packet.*; -import net.swofty.anticheat.loader.Loader; -import net.swofty.anticheat.loader.LoaderPacketHandler; -import net.swofty.anticheat.loader.managers.SwoftySchedulerManager; -import net.swofty.anticheat.loader.spigot.packets.*; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -public class SpigotLoader extends Loader { - private final Plugin plugin; - private final ProtocolManager protocolManager; - private final Map packetTypeMap = new HashMap<>(); - - public SpigotLoader(Plugin plugin) { - this.plugin = plugin; - this.protocolManager = ProtocolLibrary.getProtocolManager(); - } - - @Override - public SwoftySchedulerManager getSchedulerManager() { - return new SpigotSchedulerManager(plugin); - } - - @Override - public List getOnlinePlayers() { - List players = new ArrayList<>(); - Bukkit.getOnlinePlayers().forEach(player -> players.add(player.getUniqueId())); - return players; - } - - @Override - public void onInitialize() { - // Register packet handlers - registerPacketHandler(PositionAndRotationPacket.class, - new SpigotHandlerPositionAndRotationPacket()); - registerPacketHandler(PositionPacket.class, - new SpigotHandlerPositionPacket()); - registerPacketHandler(RotationPacket.class, - new SpigotHandlerRotationPacket()); - registerPacketHandler(RequestPingPacket.class, - new SpigotHandlerPingRequestPacket()); - registerPacketHandler(PingResponsePacket.class, - new SpigotHandlerPingResponsePacket()); - registerPacketHandler(EntityActionPacket.class, - new SpigotHandlerEntityActionPacket()); - registerPacketHandler(AbilitiesPacket.class, - new SpigotHandlerAbilitiesPacket()); - registerPacketHandler(HeldItemChangePacket.class, - new SpigotHandlerHeldItemChangePacket()); - registerPacketHandler(BlockDigPacket.class, - new SpigotHandlerBlockDigPacket()); - registerPacketHandler(BlockPlacePacket.class, - new SpigotHandlerBlockPlacePacket()); - registerPacketHandler(UseEntityPacket.class, - new SpigotHandlerUseEntityPacket()); - registerPacketHandler(WindowClickPacket.class, - new SpigotHandlerWindowClickPacket()); - registerPacketHandler(AnimationPacket.class, - new SpigotHandlerAnimationPacket()); - registerPacketHandler(SteerVehiclePacket.class, - new SpigotHandlerSteerVehiclePacket()); - - // Map PacketTypes to handlers for Spigot - packetTypeMap.put(PacketType.Play.Client.POSITION, getPacketHandler(PositionPacket.class)); - packetTypeMap.put(PacketType.Play.Client.POSITION_LOOK, getPacketHandler(PositionAndRotationPacket.class)); - packetTypeMap.put(PacketType.Play.Client.LOOK, getPacketHandler(RotationPacket.class)); - packetTypeMap.put(PacketType.Play.Server.PING, getPacketHandler(RequestPingPacket.class)); - packetTypeMap.put(PacketType.Play.Client.PONG, getPacketHandler(PingResponsePacket.class)); - packetTypeMap.put(PacketType.Play.Client.ENTITY_ACTION, getPacketHandler(EntityActionPacket.class)); - packetTypeMap.put(PacketType.Play.Client.ABILITIES, getPacketHandler(AbilitiesPacket.class)); - packetTypeMap.put(PacketType.Play.Client.HELD_ITEM_SLOT, getPacketHandler(HeldItemChangePacket.class)); - packetTypeMap.put(PacketType.Play.Client.BLOCK_DIG, getPacketHandler(BlockDigPacket.class)); - packetTypeMap.put(PacketType.Play.Client.BLOCK_PLACE, getPacketHandler(BlockPlacePacket.class)); - packetTypeMap.put(PacketType.Play.Client.USE_ENTITY, getPacketHandler(UseEntityPacket.class)); - packetTypeMap.put(PacketType.Play.Client.WINDOW_CLICK, getPacketHandler(WindowClickPacket.class)); - packetTypeMap.put(PacketType.Play.Client.ARM_ANIMATION, getPacketHandler(AnimationPacket.class)); - packetTypeMap.put(PacketType.Play.Client.STEER_VEHICLE, getPacketHandler(SteerVehiclePacket.class)); - - // Listen for all incoming client packets - protocolManager.addPacketListener(new PacketAdapter(plugin, - PacketType.Play.Client.POSITION, - PacketType.Play.Client.POSITION_LOOK, - PacketType.Play.Client.LOOK, - PacketType.Play.Client.ENTITY_ACTION, - PacketType.Play.Client.ABILITIES, - PacketType.Play.Client.HELD_ITEM_SLOT, - PacketType.Play.Client.BLOCK_DIG, - PacketType.Play.Client.BLOCK_PLACE, - PacketType.Play.Client.USE_ENTITY, - PacketType.Play.Client.WINDOW_CLICK, - PacketType.Play.Client.ARM_ANIMATION, - PacketType.Play.Client.STEER_VEHICLE) { - @Override - public void onPacketReceiving(PacketEvent event) { - PacketContainer packet = event.getPacket(); - UUID playerId = event.getPlayer().getUniqueId(); - - LoaderPacketHandler handler = packetTypeMap.get(packet.getType()); - if (handler == null) return; - - SwoftyPacket swoftyPacket = handler.buildSwoftyPacket(playerId, packet); - if (swoftyPacket == null) return; - - SwoftyEventHandler.callEvent(new AnticheatPacketEvent(swoftyPacket)); - } - }); - - // Listen for pong packets (ping response) - protocolManager.addPacketListener(new PacketAdapter(plugin, - PacketType.Play.Client.PONG) { - @Override - public void onPacketReceiving(PacketEvent event) { - PacketContainer packet = event.getPacket(); - UUID playerId = event.getPlayer().getUniqueId(); - - LoaderPacketHandler handler = packetTypeMap.get(packet.getType()); - if (handler == null) return; - - SwoftyPacket swoftyPacket = handler.buildSwoftyPacket(playerId, packet); - if (swoftyPacket == null) return; - - SwoftyEventHandler.callEvent(new AnticheatPacketEvent(swoftyPacket)); - } - }); - - // Listen for outgoing packets (ping requests) - protocolManager.addPacketListener(new PacketAdapter(plugin, - PacketType.Play.Server.PING) { - @Override - public void onPacketSending(PacketEvent event) { - PacketContainer packet = event.getPacket(); - UUID playerId = event.getPlayer().getUniqueId(); - - LoaderPacketHandler handler = packetTypeMap.get(packet.getType()); - if (handler == null) return; - - SwoftyPacket swoftyPacket = handler.buildSwoftyPacket(playerId, packet); - if (swoftyPacket == null) return; - - SwoftyEventHandler.callEvent(new AnticheatPacketEvent(swoftyPacket)); - } - }); - } - - @Override - public void sendPacket(UUID uuid, SwoftyPacket packet) { - Player player = Bukkit.getPlayer(uuid); - if (player == null) return; - - try { - PacketContainer container = (PacketContainer) getPacketHandler(packet).buildLoaderPacket(uuid, packet); - protocolManager.sendServerPacket(player, container); - } catch (Exception e) { - plugin.getLogger().severe("Error sending packet " + packet.getClass().getSimpleName() + " to " + uuid); - e.printStackTrace(); - } - } - - @Override - public void sendMessage(UUID uuid, String message) { - Player player = Bukkit.getPlayer(uuid); - if (player == null) return; - - player.sendMessage(message); - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/SpigotSchedulerManager.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/SpigotSchedulerManager.java deleted file mode 100644 index 8254ae9af..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/SpigotSchedulerManager.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.swofty.anticheat.loader.spigot; - -import net.swofty.anticheat.loader.managers.SwoftySchedulerManager; -import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitTask; - -import java.util.HashMap; -import java.util.Map; - -public class SpigotSchedulerManager extends SwoftySchedulerManager { - private final Plugin plugin; - private final Map tasks = new HashMap<>(); - private int nextId = 0; - - public SpigotSchedulerManager(Plugin plugin) { - this.plugin = plugin; - } - - @Override - public int scheduleDelayedTask(Runnable runnable, int delay) { - int id = nextId++; - - BukkitTask task = Bukkit.getScheduler().runTaskLater(plugin, runnable, delay); - tasks.put(id, task); - - return id; - } - - @Override - public int scheduleRepeatingTask(Runnable runnable, int delay, int period) { - int id = nextId++; - - BukkitTask task = Bukkit.getScheduler().runTaskTimer(plugin, runnable, delay, period); - tasks.put(id, task); - - return id; - } - - @Override - public void cancelTask(int taskId) { - BukkitTask task = tasks.remove(taskId); - if (task != null) task.cancel(); - } - - @Override - public void cancelAllTasks() { - tasks.values().forEach(BukkitTask::cancel); - tasks.clear(); - } -} \ No newline at end of file diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerAbilitiesPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerAbilitiesPacket.java deleted file mode 100644 index 2465621fb..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerAbilitiesPacket.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.event.packet.AbilitiesPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerAbilitiesPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return AbilitiesPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - byte flags = packet.getBytes().read(0); - boolean invulnerable = (flags & 0x01) != 0; - boolean flying = (flags & 0x02) != 0; - boolean allowFlight = (flags & 0x04) != 0; - boolean creativeMode = (flags & 0x08) != 0; - - float flySpeed = packet.getFloat().size() > 0 ? packet.getFloat().read(0) : 0.05f; - float walkSpeed = packet.getFloat().size() > 1 ? packet.getFloat().read(1) : 0.1f; - - return new AbilitiesPacket(uuid, invulnerable, flying, allowFlight, creativeMode, flySpeed, walkSpeed); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerAnimationPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerAnimationPacket.java deleted file mode 100644 index ac8ec526d..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerAnimationPacket.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.EnumWrappers; -import net.swofty.anticheat.event.packet.AnimationPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerAnimationPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return AnimationPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - EnumWrappers.Hand hand = packet.getHands().size() > 0 ? - packet.getHands().read(0) : EnumWrappers.Hand.MAIN_HAND; - - AnimationPacket.Hand handType = hand == EnumWrappers.Hand.MAIN_HAND ? - AnimationPacket.Hand.MAIN_HAND : AnimationPacket.Hand.OFF_HAND; - - return new AnimationPacket(uuid, handType); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerBlockDigPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerBlockDigPacket.java deleted file mode 100644 index 22f55cad0..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerBlockDigPacket.java +++ /dev/null @@ -1,63 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.EnumWrappers; -import net.swofty.anticheat.event.packet.BlockDigPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; -import net.swofty.anticheat.math.Pos; - -import java.util.UUID; - -public class SpigotHandlerBlockDigPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return BlockDigPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - EnumWrappers.PlayerDigType digType = packet.getPlayerDigTypes().read(0); - BlockPosition blockPos = packet.getBlockPositionModifier().read(0); - EnumWrappers.Direction direction = packet.getDirections().read(0); - int sequence = packet.getIntegers().size() > 0 ? packet.getIntegers().read(0) : 0; - - BlockDigPacket.Status status = mapStatus(digType); - BlockDigPacket.Direction dir = mapDirection(direction); - Pos position = new Pos(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - - return new BlockDigPacket(uuid, status, position, dir, sequence); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } - - private BlockDigPacket.Status mapStatus(EnumWrappers.PlayerDigType digType) { - return switch (digType) { - case START_DESTROY_BLOCK -> BlockDigPacket.Status.STARTED_DIGGING; - case ABORT_DESTROY_BLOCK -> BlockDigPacket.Status.CANCELLED_DIGGING; - case STOP_DESTROY_BLOCK -> BlockDigPacket.Status.FINISHED_DIGGING; - case DROP_ALL_ITEMS -> BlockDigPacket.Status.DROP_ITEM_STACK; - case DROP_ITEM -> BlockDigPacket.Status.DROP_ITEM; - case RELEASE_USE_ITEM -> BlockDigPacket.Status.UPDATE_HELD_ITEM; - case SWAP_HELD_ITEMS -> BlockDigPacket.Status.SWAP_ITEM_IN_HAND; - }; - } - - private BlockDigPacket.Direction mapDirection(EnumWrappers.Direction direction) { - return switch (direction) { - case DOWN -> BlockDigPacket.Direction.DOWN; - case UP -> BlockDigPacket.Direction.UP; - case NORTH -> BlockDigPacket.Direction.NORTH; - case SOUTH -> BlockDigPacket.Direction.SOUTH; - case WEST -> BlockDigPacket.Direction.WEST; - case EAST -> BlockDigPacket.Direction.EAST; - }; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerBlockPlacePacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerBlockPlacePacket.java deleted file mode 100644 index 1e8ea2cf2..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerBlockPlacePacket.java +++ /dev/null @@ -1,58 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.EnumWrappers; -import net.swofty.anticheat.event.packet.BlockPlacePacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; -import net.swofty.anticheat.math.Pos; - -import java.util.UUID; - -public class SpigotHandlerBlockPlacePacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return BlockPlacePacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - EnumWrappers.Hand hand = packet.getHands().read(0); - BlockPosition blockPos = packet.getBlockPositionModifier().read(0); - EnumWrappers.Direction direction = packet.getDirections().read(0); - - float cursorX = packet.getFloat().size() > 0 ? packet.getFloat().read(0) : 0.5f; - float cursorY = packet.getFloat().size() > 1 ? packet.getFloat().read(1) : 0.5f; - float cursorZ = packet.getFloat().size() > 2 ? packet.getFloat().read(2) : 0.5f; - - boolean insideBlock = packet.getBooleans().size() > 0 && packet.getBooleans().read(0); - int sequence = packet.getIntegers().size() > 0 ? packet.getIntegers().read(0) : 0; - - BlockPlacePacket.Hand handType = hand == EnumWrappers.Hand.MAIN_HAND ? - BlockPlacePacket.Hand.MAIN_HAND : BlockPlacePacket.Hand.OFF_HAND; - BlockPlacePacket.Direction dir = mapDirection(direction); - Pos position = new Pos(blockPos.getX(), blockPos.getY(), blockPos.getZ()); - - return new BlockPlacePacket(uuid, handType, position, dir, cursorX, cursorY, cursorZ, insideBlock, sequence); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } - - private BlockPlacePacket.Direction mapDirection(EnumWrappers.Direction direction) { - return switch (direction) { - case DOWN -> BlockPlacePacket.Direction.DOWN; - case UP -> BlockPlacePacket.Direction.UP; - case NORTH -> BlockPlacePacket.Direction.NORTH; - case SOUTH -> BlockPlacePacket.Direction.SOUTH; - case WEST -> BlockPlacePacket.Direction.WEST; - case EAST -> BlockPlacePacket.Direction.EAST; - }; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerEntityActionPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerEntityActionPacket.java deleted file mode 100644 index c49b09a05..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerEntityActionPacket.java +++ /dev/null @@ -1,47 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.event.packet.EntityActionPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerEntityActionPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return EntityActionPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - int actionId = packet.getIntegers().read(1); - int jumpBoost = packet.getIntegers().read(2); - - EntityActionPacket.Action action = mapAction(actionId); - return new EntityActionPacket(uuid, action, jumpBoost); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } - - private EntityActionPacket.Action mapAction(int actionId) { - return switch (actionId) { - case 0 -> EntityActionPacket.Action.START_SNEAKING; - case 1 -> EntityActionPacket.Action.STOP_SNEAKING; - case 2 -> EntityActionPacket.Action.LEAVE_BED; - case 3 -> EntityActionPacket.Action.START_SPRINTING; - case 4 -> EntityActionPacket.Action.STOP_SPRINTING; - case 5 -> EntityActionPacket.Action.START_JUMP_WITH_HORSE; - case 6 -> EntityActionPacket.Action.STOP_JUMP_WITH_HORSE; - case 7 -> EntityActionPacket.Action.OPEN_HORSE_INVENTORY; - case 8 -> EntityActionPacket.Action.START_FLYING_WITH_ELYTRA; - default -> EntityActionPacket.Action.STOP_SNEAKING; - }; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerHeldItemChangePacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerHeldItemChangePacket.java deleted file mode 100644 index 5d5db11de..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerHeldItemChangePacket.java +++ /dev/null @@ -1,29 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.event.packet.HeldItemChangePacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerHeldItemChangePacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return HeldItemChangePacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - int slot = packet.getIntegers().read(0); - return new HeldItemChangePacket(uuid, slot); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPingRequestPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPingRequestPacket.java deleted file mode 100644 index aa6ac361c..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPingRequestPacket.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.event.packet.RequestPingPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerPingRequestPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return RequestPingPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - // Not used for outgoing packets in this case - return null; - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - if (!(swoftyPacket instanceof RequestPingPacket pingPacket)) return null; - - PacketContainer packet = new PacketContainer(PacketType.Play.Server.PING); - packet.getIntegers().write(0, pingPacket.getRequestId()); - - return packet; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPingResponsePacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPingResponsePacket.java deleted file mode 100644 index a6eac9836..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPingResponsePacket.java +++ /dev/null @@ -1,30 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.engine.SwoftyPlayer; -import net.swofty.anticheat.event.packet.PingResponsePacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerPingResponsePacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return PingResponsePacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - int pingId = packet.getIntegers().read(0); - return new PingResponsePacket(SwoftyPlayer.players.get(uuid), pingId); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPositionAndRotationPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPositionAndRotationPacket.java deleted file mode 100644 index 854b73269..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPositionAndRotationPacket.java +++ /dev/null @@ -1,39 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.engine.SwoftyPlayer; -import net.swofty.anticheat.event.packet.PositionAndRotationPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; -import net.swofty.anticheat.math.Pos; - -import java.util.UUID; - -public class SpigotHandlerPositionAndRotationPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return PositionAndRotationPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - double x = packet.getDoubles().read(0); - double y = packet.getDoubles().read(1); - double z = packet.getDoubles().read(2); - float yaw = packet.getFloat().read(0); - float pitch = packet.getFloat().read(1); - boolean onGround = packet.getBooleans().read(0); - - Pos position = new Pos(x, y, z, yaw, pitch); - return new PositionAndRotationPacket(SwoftyPlayer.players.get(uuid), position, onGround); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - // Not needed for client packets - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPositionPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPositionPacket.java deleted file mode 100644 index bcf9f8c7d..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerPositionPacket.java +++ /dev/null @@ -1,34 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.engine.SwoftyPlayer; -import net.swofty.anticheat.event.packet.PositionPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerPositionPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return PositionPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - double x = packet.getDoubles().read(0); - double y = packet.getDoubles().read(1); - double z = packet.getDoubles().read(2); - boolean onGround = packet.getBooleans().read(0); - - return new PositionPacket(SwoftyPlayer.players.get(uuid), x, y, z, onGround); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerRotationPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerRotationPacket.java deleted file mode 100644 index b9fc087fd..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerRotationPacket.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.engine.SwoftyPlayer; -import net.swofty.anticheat.event.packet.RotationPacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerRotationPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return RotationPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - float yaw = packet.getFloat().read(0); - float pitch = packet.getFloat().read(1); - boolean onGround = packet.getBooleans().read(0); - - return new RotationPacket(SwoftyPlayer.players.get(uuid), yaw, pitch, onGround); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerSteerVehiclePacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerSteerVehiclePacket.java deleted file mode 100644 index 8768069b5..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerSteerVehiclePacket.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.event.packet.SteerVehiclePacket; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerSteerVehiclePacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return SteerVehiclePacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - float sideways = packet.getFloat().read(0); - float forward = packet.getFloat().read(1); - - byte flags = packet.getBytes().read(0); - boolean jump = (flags & 0x01) != 0; - boolean unmount = (flags & 0x02) != 0; - - return new SteerVehiclePacket(uuid, sideways, forward, jump, unmount); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerUseEntityPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerUseEntityPacket.java deleted file mode 100644 index 7a8cf5d61..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerUseEntityPacket.java +++ /dev/null @@ -1,57 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.EnumWrappers; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.event.packet.UseEntityPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; -import net.swofty.anticheat.math.Pos; -import org.bukkit.util.Vector; - -import java.util.UUID; - -public class SpigotHandlerUseEntityPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return UseEntityPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - int entityId = packet.getIntegers().read(0); - EnumWrappers.EntityUseAction action = packet.getEntityUseActions().read(0); - - UseEntityPacket.Type type = mapType(action); - EnumWrappers.Hand hand = packet.getHands().size() > 0 ? - packet.getHands().read(0) : EnumWrappers.Hand.MAIN_HAND; - - UseEntityPacket.Hand handType = hand == EnumWrappers.Hand.MAIN_HAND ? - UseEntityPacket.Hand.MAIN_HAND : UseEntityPacket.Hand.OFF_HAND; - - Pos targetPos = null; - if (packet.getVectors().size() > 0) { - Vector vec = packet.getVectors().read(0); - targetPos = new Pos(vec.getX(), vec.getY(), vec.getZ()); - } - - boolean sneaking = packet.getBooleans().size() > 0 && packet.getBooleans().read(0); - - return new UseEntityPacket(uuid, entityId, type, targetPos, handType, sneaking); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } - - private UseEntityPacket.Type mapType(EnumWrappers.EntityUseAction action) { - return switch (action) { - case INTERACT -> UseEntityPacket.Type.INTERACT; - case ATTACK -> UseEntityPacket.Type.ATTACK; - case INTERACT_AT -> UseEntityPacket.Type.INTERACT_AT; - }; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerWindowClickPacket.java b/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerWindowClickPacket.java deleted file mode 100644 index 15e62bdbf..000000000 --- a/anticheat/src/main/java/net/swofty/anticheat/loader/spigot/packets/SpigotHandlerWindowClickPacket.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.swofty.anticheat.loader.spigot.packets; - -import com.comphenix.protocol.events.PacketContainer; -import net.swofty.anticheat.event.packet.SwoftyPacket; -import net.swofty.anticheat.event.packet.WindowClickPacket; -import net.swofty.anticheat.loader.LoaderPacketHandler; - -import java.util.UUID; - -public class SpigotHandlerWindowClickPacket extends LoaderPacketHandler { - - @Override - public Class getHandledPacketClass() { - return WindowClickPacket.class; - } - - @Override - public SwoftyPacket buildSwoftyPacket(UUID uuid, Object loaderPacket) { - if (!(loaderPacket instanceof PacketContainer packet)) return null; - - int windowId = packet.getIntegers().read(0); - int stateId = packet.getIntegers().size() > 1 ? packet.getIntegers().read(1) : 0; - int slot = packet.getIntegers().size() > 2 ? packet.getIntegers().read(2) : 0; - int button = packet.getIntegers().size() > 3 ? packet.getIntegers().read(3) : 0; - int clickTypeId = packet.getIntegers().size() > 4 ? packet.getIntegers().read(4) : 0; - - WindowClickPacket.ClickType clickType = mapClickType(clickTypeId); - - return new WindowClickPacket(uuid, windowId, stateId, slot, button, clickType); - } - - @Override - public Object buildLoaderPacket(UUID uuid, SwoftyPacket swoftyPacket) { - return null; - } - - private WindowClickPacket.ClickType mapClickType(int type) { - return switch (type) { - case 0 -> WindowClickPacket.ClickType.PICKUP; - case 1 -> WindowClickPacket.ClickType.QUICK_MOVE; - case 2 -> WindowClickPacket.ClickType.SWAP; - case 3 -> WindowClickPacket.ClickType.CLONE; - case 4 -> WindowClickPacket.ClickType.THROW; - case 5 -> WindowClickPacket.ClickType.QUICK_CRAFT; - case 6 -> WindowClickPacket.ClickType.PICKUP_ALL; - default -> WindowClickPacket.ClickType.PICKUP; - }; - } -} diff --git a/anticheat/src/main/java/net/swofty/anticheat/math/Pos.java b/anticheat/src/main/java/net/swofty/anticheat/math/Pos.java index 68868c4b8..3da263717 100644 --- a/anticheat/src/main/java/net/swofty/anticheat/math/Pos.java +++ b/anticheat/src/main/java/net/swofty/anticheat/math/Pos.java @@ -1,6 +1,7 @@ package net.swofty.anticheat.math; import lombok.AllArgsConstructor; +import net.minestom.server.coordinate.Vec; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -65,6 +66,10 @@ public float pitch() { return withView(pos.yaw(), pos.pitch()); } + public static @NotNull Pos fromVec(@NotNull Vec vec) { + return new Pos(vec.x(), vec.y(), vec.z()); + } + public static @NotNull Pos fromPoint(@NotNull Point point) { if (point instanceof Pos pos) return pos; return new Pos(point.x(), point.y(), point.z()); diff --git a/build.gradle.kts b/build.gradle.kts index f80468c61..e53f00d3d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,3 @@ -import org.gradle.api.artifacts.VersionCatalog -import org.gradle.api.artifacts.VersionCatalogsExtension -import org.gradle.kotlin.dsl.getByType - plugins { base java @@ -12,6 +8,10 @@ plugins { group = "net.swofty" version = "1.0" +repositories { + mavenCentral() +} + val libsCatalog: VersionCatalog = extensions.getByType().named("libs") subprojects { @@ -25,6 +25,7 @@ subprojects { maven("https://repo.viaversion.com") maven("https://jitpack.io") maven("https://repo.lucko.me/") + maven("https://repo.nexomc.com/releases") } java { diff --git a/commons/build.gradle.kts b/commons/build.gradle.kts index 828815d35..a944abf34 100644 --- a/commons/build.gradle.kts +++ b/commons/build.gradle.kts @@ -21,6 +21,7 @@ dependencies { implementation(libs.mongodb.bson) implementation(libs.tinylog.api) implementation(libs.tinylog.impl) + implementation(libs.zstd.jni) compileOnly(libs.minestom) { exclude(group = "org.jboss.shrinkwrap.resolver", module = "shrinkwrap-resolver-depchain") diff --git a/commons/src/codegen/java/net/swofty/codegen/ItemTypeGenerator.java b/commons/src/codegen/java/net/swofty/codegen/ItemTypeGenerator.java index 7d1b1ab3e..7456685f3 100644 --- a/commons/src/codegen/java/net/swofty/codegen/ItemTypeGenerator.java +++ b/commons/src/codegen/java/net/swofty/codegen/ItemTypeGenerator.java @@ -1,19 +1,23 @@ package net.swofty.codegen; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.JavaFile; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.TypeSpec; +import com.palantir.javapoet.ClassName; +import com.palantir.javapoet.JavaFile; +import com.palantir.javapoet.MethodSpec; +import com.palantir.javapoet.TypeSpec; import org.yaml.snakeyaml.Yaml; +import javax.lang.model.element.Modifier; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.TreeMap; import java.util.stream.Stream; -import javax.lang.model.element.Modifier; - public class ItemTypeGenerator { static void main(String[] args) throws Exception { if (args.length < 2) { diff --git a/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java b/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java index cb7ae1bf5..ec70d756b 100644 --- a/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java +++ b/commons/src/generated/java/net/swofty/commons/skyblock/item/ItemType.java @@ -876,15 +876,15 @@ public enum ItemType { DIAMOND_BLOCK(Material.DIAMOND_BLOCK, Rarity.COMMON), - DIAMOND_BOOTS(Material.DIAMOND_BOOTS, Rarity.RARE), + DIAMOND_BOOTS(Material.DIAMOND_BOOTS, Rarity.UNCOMMON), - DIAMOND_CHESTPLATE(Material.DIAMOND_CHESTPLATE, Rarity.RARE), + DIAMOND_CHESTPLATE(Material.DIAMOND_CHESTPLATE, Rarity.UNCOMMON), - DIAMOND_HELMET(Material.DIAMOND_HELMET, Rarity.RARE), + DIAMOND_HELMET(Material.DIAMOND_HELMET, Rarity.UNCOMMON), DIAMOND_HOE(Material.DIAMOND_HOE, Rarity.COMMON), - DIAMOND_LEGGINGS(Material.DIAMOND_LEGGINGS, Rarity.RARE), + DIAMOND_LEGGINGS(Material.DIAMOND_LEGGINGS, Rarity.UNCOMMON), DIAMOND_MAGMAFISH(Material.PLAYER_HEAD, Rarity.COMMON), diff --git a/commons/src/main/java/net/swofty/commons/ChatUtility.java b/commons/src/main/java/net/swofty/commons/ChatUtility.java index 0b60cf6ca..54d179aa0 100644 --- a/commons/src/main/java/net/swofty/commons/ChatUtility.java +++ b/commons/src/main/java/net/swofty/commons/ChatUtility.java @@ -2,6 +2,7 @@ import lombok.Getter; +import java.util.ArrayList; import java.util.List; public class ChatUtility { @@ -152,6 +153,41 @@ public static String getCenterSpaces(String message) { return sb.toString(); } + public static List wrap(String message) { + return wrap(message, 240); + } + + public static List wrap(String message, int maxPxWidth) { + List lines = new ArrayList<>(); + + if (message == null || message.isEmpty()) { + return lines; + } + + StringBuilder currentLine = new StringBuilder(); + + for (String word : message.split(" ")) { + String candidate = currentLine.isEmpty() + ? word + : currentLine + " " + word; + + if (getLength(candidate) <= maxPxWidth) { + currentLine = new StringBuilder(candidate); + } else { + if (!currentLine.isEmpty()) { + lines.add(currentLine.toString()); + } + currentLine = new StringBuilder(word); + } + } + + if (!currentLine.isEmpty()) { + lines.add(currentLine.toString()); + } + + return lines; + } + public static String stripTokens(String input) { return input.replaceAll("§.", ""); } diff --git a/commons/src/main/java/net/swofty/commons/CustomWorlds.java b/commons/src/main/java/net/swofty/commons/CustomWorlds.java index 9bc2afd8d..7e18f2a75 100644 --- a/commons/src/main/java/net/swofty/commons/CustomWorlds.java +++ b/commons/src/main/java/net/swofty/commons/CustomWorlds.java @@ -20,6 +20,7 @@ public enum CustomWorlds { BEDWARS_LOBBY("hypixel_bedwars_lobby"), MURDER_MYSTERY_LOBBY("hypixel_murder_mystery_lobby"), SKYWARS_LOBBY("hypixel_skywars_lobby"), + MAIN_LOBBY("hypixel_main_lobby"), ; private final String folderName; diff --git a/commons/src/main/java/net/swofty/commons/LobbyDestination.java b/commons/src/main/java/net/swofty/commons/LobbyDestination.java new file mode 100644 index 000000000..9250dc25d --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/LobbyDestination.java @@ -0,0 +1,121 @@ +package net.swofty.commons; + +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Locale; +import java.util.Set; + +public enum LobbyDestination { + BEDWARS( + ServerType.BEDWARS_LOBBY, + Set.of("bw", "bedwars"), + Set.of(ServerType.BEDWARS_LOBBY, ServerType.BEDWARS_GAME, ServerType.BEDWARS_CONFIGURATOR) + ), + SKYWARS( + ServerType.SKYWARS_LOBBY, + Set.of("sw", "skywars"), + Set.of(ServerType.SKYWARS_LOBBY, ServerType.SKYWARS_GAME, ServerType.SKYWARS_CONFIGURATOR) + ), + MURDER_MYSTERY( + ServerType.MURDER_MYSTERY_LOBBY, + Set.of("mm", "murder", "murdermystery", "murder_mystery", "mystery"), + Set.of(ServerType.MURDER_MYSTERY_LOBBY, ServerType.MURDER_MYSTERY_GAME, ServerType.MURDER_MYSTERY_CONFIGURATOR) + ), + SKYBLOCK( + ServerType.SKYBLOCK_HUB, + Set.of("sb", "skyblock", "hub"), + Set.of(ServerType.PROTOTYPE_LOBBY) + ), + PROTOTYPE( + ServerType.PROTOTYPE_LOBBY, + Set.of("prototype", "proto", "ptl"), + Set.of(ServerType.PROTOTYPE_LOBBY, ServerType.REPLAY_VIEWER) + ), + MAIN_LOBBY( + ServerType.MAIN_LOBBY, + Set.of("main"), + Set.of(ServerType.MAIN_LOBBY) + ), + RAVENGARD( + ServerType.RAVENGARD_LOBBY, + Set.of("ravengard", "rg"), + Set.of(ServerType.RAVENGARD_LOBBY) + ); + + private final ServerType destination; + private final Set aliases; + private final Set sourceTypes; + + LobbyDestination(ServerType destination, Set aliases, Set sourceTypes) { + this.destination = destination; + this.aliases = aliases; + this.sourceTypes = sourceTypes; + } + + public ServerType destination() { + return destination; + } + + public static @Nullable ServerType resolveFromAlias(String alias) { + String normalized = normalize(alias); + if (normalized.isEmpty()) { + return null; + } + + for (LobbyDestination value : values()) { + if (value.aliases.contains(normalized)) { + return value.destination; + } + } + + return null; + } + + public static ServerType resolveDefaultDestination(@Nullable ServerType currentType) { + if (currentType == null) { + return ServerType.PROTOTYPE_LOBBY; + } + + for (LobbyDestination value : values()) { + if (value.handlesSource(currentType)) { + return value.destination; + } + } + + return ServerType.PROTOTYPE_LOBBY; + } + + public static @Nullable ServerType resolveDestination(@Nullable String alias, @Nullable ServerType currentType) { + if (alias != null && !alias.isBlank()) { + return resolveFromAlias(alias); + } + return resolveDefaultDestination(currentType); + } + + public static Set allAliases() { + Set all = new LinkedHashSet<>(); + Arrays.stream(values()).forEach(value -> all.addAll(value.aliases)); + return all; + } + + private boolean handlesSource(ServerType sourceType) { + if (this == SKYBLOCK) { + return sourceType.isSkyBlock(); + } + return sourceTypes.contains(sourceType); + } + + private static String normalize(String value) { + if (value == null) { + return ""; + } + + return value + .toLowerCase(Locale.ROOT) + .replace("_", "") + .replace("-", "") + .replace(" ", ""); + } +} diff --git a/commons/src/main/java/net/swofty/commons/MinecraftVersion.java b/commons/src/main/java/net/swofty/commons/MinecraftVersion.java index 3bf3d1843..0f00c64c7 100644 --- a/commons/src/main/java/net/swofty/commons/MinecraftVersion.java +++ b/commons/src/main/java/net/swofty/commons/MinecraftVersion.java @@ -56,6 +56,8 @@ public enum MinecraftVersion { MINECRAFT_1_21_9(773, new String[]{"1.21.9"}), MINECRAFT_1_21_10(773, new String[]{"1.21.10"}), MINECRAFT_1_21_11(774, new String[]{"1.21.11"}), + MINERAFT_26_1(775, new String[]{"26.1", "26.1.1", "26.1.2"}), + ; private final int protocol; diff --git a/commons/src/main/java/net/swofty/commons/SentryWriter.java b/commons/src/main/java/net/swofty/commons/SentryWriter.java deleted file mode 100644 index 7a3e07459..000000000 --- a/commons/src/main/java/net/swofty/commons/SentryWriter.java +++ /dev/null @@ -1,93 +0,0 @@ -package net.swofty.commons; - -import java.util.Collection; -import java.util.Collections; -import java.util.Map; - -import io.sentry.Sentry; -import io.sentry.SentryLogLevel; -import org.tinylog.Level; -import org.tinylog.core.ConfigurationParser; -import org.tinylog.core.LogEntry; -import org.tinylog.core.LogEntryValue; -import org.tinylog.provider.InternalLogger; -import org.tinylog.writers.AbstractFormatPatternWriter; - - -public final class SentryWriter extends AbstractFormatPatternWriter { - - private final Level errorLevel; - - public SentryWriter() { - this(Collections.emptyMap()); - } - - /** - * @param properties - * Configuration for writer - */ - public SentryWriter(final Map properties) { - super(properties); - - // Set the default level for stderr logging - Level levelStream = Level.WARN; - - // Check stream property - String stream = getStringValue("stream"); - if (stream != null) { - // Check whether we have the err@LEVEL syntax - String[] streams = stream.split("@", 2); - if (streams.length == 2) { - levelStream = ConfigurationParser.parse(streams[1], levelStream); - if (!streams[0].equals("err")) { - InternalLogger.log(Level.ERROR, "Stream with level must be \"err\", \"" + streams[0] + "\" is an invalid name"); - } - stream = null; - } - } - - if (stream == null) { - errorLevel = levelStream; - } else if ("err".equalsIgnoreCase(stream)) { - errorLevel = Level.TRACE; - } else if ("out".equalsIgnoreCase(stream)) { - errorLevel = Level.OFF; - } else { - InternalLogger.log(Level.ERROR, "Stream must be \"out\" or \"err\", \"" + stream + "\" is an invalid stream name"); - errorLevel = levelStream; - } - } - - @Override - public Collection getRequiredLogEntryValues() { - Collection logEntryValues = super.getRequiredLogEntryValues(); - logEntryValues.add(LogEntryValue.LEVEL); - return logEntryValues; - } - - @Override - public void write(final LogEntry logEntry) { - SentryLogLevel sentryLevel; - try { - sentryLevel = SentryLogLevel.valueOf(logEntry.getLevel().name()); - } catch (IllegalArgumentException e) { - sentryLevel = SentryLogLevel.INFO; - } - - Sentry.logger().log(sentryLevel, render(logEntry)); - if (logEntry.getLevel().ordinal() < errorLevel.ordinal()) { - System.out.print(render(logEntry)); - } else { - System.err.print(render(logEntry)); - } - } - - @Override - public void flush() { - } - - @Override - public void close() { - } - -} \ No newline at end of file diff --git a/commons/src/main/java/net/swofty/commons/ServerType.java b/commons/src/main/java/net/swofty/commons/ServerType.java index 971b4fac1..6c1dba5f4 100644 --- a/commons/src/main/java/net/swofty/commons/ServerType.java +++ b/commons/src/main/java/net/swofty/commons/ServerType.java @@ -21,6 +21,7 @@ public enum ServerType { PROTOTYPE_LOBBY(false), BEDWARS_LOBBY(false), BEDWARS_GAME(false), + MAIN_LOBBY(false), BEDWARS_CONFIGURATOR(false), MURDER_MYSTERY_LOBBY(false), MURDER_MYSTERY_GAME(false), @@ -28,7 +29,8 @@ public enum ServerType { SKYWARS_LOBBY(false), SKYWARS_GAME(false), SKYWARS_CONFIGURATOR(false), - RAVENGARD_LOBBY(false) + RAVENGARD_LOBBY(false), + REPLAY_VIEWER(false) ; private final boolean isSkyBlock; diff --git a/commons/src/main/java/net/swofty/commons/ServiceType.java b/commons/src/main/java/net/swofty/commons/ServiceType.java index 8dfd259b0..28be2540c 100644 --- a/commons/src/main/java/net/swofty/commons/ServiceType.java +++ b/commons/src/main/java/net/swofty/commons/ServiceType.java @@ -10,7 +10,9 @@ public enum ServiceType { DARK_AUCTION, ORCHESTRATOR, FRIEND, + REPLAY, PUNISHMENT, ELECTION, + GUILD, ; } diff --git a/commons/src/main/java/net/swofty/commons/StringUtility.java b/commons/src/main/java/net/swofty/commons/StringUtility.java index 2c7b36e98..d1d82b67a 100644 --- a/commons/src/main/java/net/swofty/commons/StringUtility.java +++ b/commons/src/main/java/net/swofty/commons/StringUtility.java @@ -266,7 +266,7 @@ public static String getTextFromComponent(Component component) { } public static String getAuctionSetupFormattedTime(long millis) { - return formatTimeLeft(millis).replaceAll(" ", "") + return formatTimeLeft(millis).replace(" ", "") .replaceAll("s$", ""); } @@ -435,6 +435,25 @@ public static String ntify(int i) { }; } + /** + * Capitalizes the first letter of each word in the input string and lowercases the rest of the letters in each word. + * @param input The string to capitalize. + * @return The input string with the first letter of each word capitalized and the rest lowercased. If the input is null or empty, it returns the input as is. + */ + public static String capitalizeSentence(String input) { + if (input == null || input.isEmpty()) { + return input; + } + String[] words = input.split(" "); + StringBuilder capitalized = new StringBuilder(); + for (String word : words) { + if (!word.isEmpty()) { + capitalized.append(capitalize(word)).append(" "); + } + } + return capitalized.toString().trim(); + } + public static long parseDuration(String duration) { long totalMillis = 0; Pattern pattern = Pattern.compile("(\\d+)([dhms])"); diff --git a/commons/src/main/java/net/swofty/commons/Tuple.java b/commons/src/main/java/net/swofty/commons/Tuple.java index d60768db6..222ab32f3 100644 --- a/commons/src/main/java/net/swofty/commons/Tuple.java +++ b/commons/src/main/java/net/swofty/commons/Tuple.java @@ -1,5 +1,10 @@ package net.swofty.commons; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter public class Tuple { private A key; private B value; @@ -9,19 +14,4 @@ public Tuple(A key, B value) { this.value = value; } - public void setKey(A key) { - this.key = key; - } - - public void setValue(B value) { - this.value = value; - } - - public A getKey() { - return key; - } - - public B getValue() { - return value; - } } diff --git a/commons/src/main/java/net/swofty/commons/VersionConst.java b/commons/src/main/java/net/swofty/commons/VersionConst.java new file mode 100644 index 000000000..51389c30c --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/VersionConst.java @@ -0,0 +1,7 @@ +package net.swofty.commons; + +public class VersionConst { + + public static String BED_WARS_VERSION = "1.11.1"; + +} diff --git a/commons/src/main/java/net/swofty/commons/bedwars/BedWarsDreamRotation.java b/commons/src/main/java/net/swofty/commons/bedwars/BedWarsDreamRotation.java new file mode 100644 index 000000000..d526ed85c --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/bedwars/BedWarsDreamRotation.java @@ -0,0 +1,77 @@ +package net.swofty.commons.bedwars; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.temporal.ChronoUnit; +import java.time.temporal.TemporalAdjusters; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class BedWarsDreamRotation { + private static final LocalDate EPOCH_WEEK = LocalDate.of(2026, 1, 1).with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + private static final List MODES = List.of( + new DreamMode("One Block", BedWarsGameType.ONE_BLOCK, BedWarsGameType.ONE_BLOCK), + new DreamMode("Rush V2", BedWarsGameType.RUSH_DOUBLES, BedWarsGameType.RUSH_FOURS), + new DreamMode("Ultimate V2", BedWarsGameType.ULTIMATE_DOUBLES, BedWarsGameType.ULTIMATE_FOURS), + new DreamMode("Swappage", BedWarsGameType.SWAPPAGE_DOUBLES, BedWarsGameType.SWAPPAGE_FOURS), + new DreamMode("Castle V2", BedWarsGameType.CASTLE, BedWarsGameType.CASTLE), + new DreamMode("Voidless", BedWarsGameType.VOIDLESS_DOUBLES, BedWarsGameType.VOIDLESS_FOURS), + new DreamMode("Armed", BedWarsGameType.ARMED_DOUBLES, BedWarsGameType.ARMED_FOURS), + new DreamMode("Lucky V2", BedWarsGameType.LUCKY_BLOCK_DOUBLES, BedWarsGameType.LUCKY_BLOCK_FOURS) + ); + + public static RotationEntry current(LocalDate date) { + return entryFor(date, 0); + } + + public static RotationEntry entryFor(LocalDate date, int weekOffset) { + LocalDate weekStart = weekStart(date).plusWeeks(weekOffset); + DreamMode mode = modeForWeek(weekStart); + return new RotationEntry(mode, weekStart, weekStart.plusDays(7), weekOffset); + } + + public static List upcoming(LocalDate date, int count) { + List entries = new ArrayList<>(); + for (int i = 0; i < count; i++) { + entries.add(entryFor(date, i)); + } + return entries; + } + + public static List modes() { + return MODES; + } + + private static LocalDate weekStart(LocalDate date) { + return date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + } + + private static DreamMode modeForWeek(LocalDate weekStart) { + long week = ChronoUnit.WEEKS.between(EPOCH_WEEK, weekStart); + List shuffled = new ArrayList<>(MODES); + long seed = 0x6A09E667F3BCC909L ^ (week / MODES.size()) * 0x9E3779B97F4A7C15L; + Collections.shuffle(shuffled, new Random(seed)); + return shuffled.get(Math.floorMod((int) week, shuffled.size())); + } + + public record DreamMode(String displayName, BedWarsGameType doublesType, BedWarsGameType foursType) { + public BedWarsGameType preferredQueueType() { + if (doublesType.isLuckyBlock()) { + return doublesType; + } + return doublesType.getMapCompatibilityType(); + } + } + + public record RotationEntry(DreamMode mode, LocalDate startsAt, LocalDate endsAt, int weekOffset) { + public boolean current() { + return weekOffset == 0; + } + } +} diff --git a/commons/src/main/java/net/swofty/commons/bedwars/BedWarsGameType.java b/commons/src/main/java/net/swofty/commons/bedwars/BedWarsGameType.java new file mode 100644 index 000000000..2865cf322 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/bedwars/BedWarsGameType.java @@ -0,0 +1,209 @@ +package net.swofty.commons.bedwars; + +import lombok.Getter; +import net.minestom.server.item.Material; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; + +@Getter +public enum BedWarsGameType { + ONE_EIGHT(0, "Solo", 1, 8, List.of( + "Fight against 7 other players!", + "Destroy enemy beds to stop them", + "from respawning!", + "Protect your bed from destruction!" + )), + TWO_EIGHT(1, "Doubles", 2, 8, List.of( + "Team up with 1 other player to", + "defeat 7 enemy teams!", + "Destroy enemy beds to stop them", + "from respawning!", + "Protect your bed from destruction!" + )), + FOUR_THREE(2, "3v3v3v3", 3, 4, List.of( + "Team up with 2 other players to", + "defeat 3 other groups of players!", + "Destroy enemy beds to stop them", + "from respawning!", + "Protect your bed from destruction!" + )), + FOUR_FOUR(3, "4v4v4v4", 4, 4, List.of( + "Team up with 3 other players to", + "defeat 3 other groups of players!", + "Destroy enemy beds to stop them", + "from respawning!", + "Protect your bed from destruction!" + )), + TWO_FOUR(4, "4v4", 4, 2, List.of( + "4v4 is the classic Bed Wars", + "everyone knows and loves, but with", + "only 1 enemy team!" + )), + + // dream + ULTIMATE_DOUBLES(5, "Ultimate V2 Doubles", 2, 8, List.of(), true), + ULTIMATE_FOURS(6, "Ultimate V2 4v4v4v4", 4, 4, List.of(), true), + SWAPPAGE_DOUBLES(7, "Swappage Doubles", 2, 8, List.of("Use the Swap to change ownership", "between beds! Chaos ensues."), true), + SWAPPAGE_FOURS(8, "Swappage 4v4v4v4", 4, 4, List.of("Use the Swap to change ownership", "between beds! Chaos ensues."), true), + RUSH_DOUBLES(9, "Rush V2 Doubles", 2, 8, List.of(), true), + RUSH_FOURS(10, "Rush V2 4v4v4v4", 4, 4, List.of(), true), + VOIDLESS_DOUBLES(11, "Voidless", 2, 8, List.of(), true), + VOIDLESS_FOURS(12, "Voidless", 4, 4, List.of(), true), + ARMED_DOUBLES(12, "Armed", 2, 8, List.of(), true), + ARMED_FOURS(12, "Armed", 4, 4, List.of(), true), + CASTLE(9, "Castle", 40, 2, List.of(), true), + ONE_BLOCK(20, "One Block", 1, 8, List.of( + "Every few seconds brings a new", + "surprise! Use these items to defend", + "your bed or destroy enemy beds." + ), true), + LUCKY_BLOCK_DOUBLES(21, "Lucky V2 Doubles", 2, 8, List.of( + "Find Lucky Blocks on your island", + "generator and open them for", + "chaotic rewards." + ), true), + LUCKY_BLOCK_FOURS(22, "Lucky Blocks V2 4v4v4v4", 4, 4, List.of( + "Find Lucky Blocks on your island", + "generator and open them for", + "chaotic rewards." + ), true); + + private final int id; + private final String displayName; + private final int teamSize; + private final int teams; + private final List description; + private final boolean dream; + private final Material icon; + + BedWarsGameType(int id, String displayName, int teamSize, int teams, List description) { + this.id = id; + this.displayName = displayName; + this.teamSize = teamSize; + this.teams = teams; + this.description = description; + this.dream = false; + this.icon = Material.RED_BED; + } + + BedWarsGameType(int id, String displayName, int teamSize, int teams, List description, boolean dream) { + this.id = id; + this.displayName = displayName; + this.teamSize = teamSize; + this.teams = teams; + this.description = description; + this.dream = dream; + this.icon = switch (this) { + case RUSH_DOUBLES, RUSH_FOURS -> Material.ENDER_EYE; + case ULTIMATE_DOUBLES, ULTIMATE_FOURS -> Material.NETHER_STAR; + case CASTLE -> Material.STONE_BRICKS; + case VOIDLESS_DOUBLES, VOIDLESS_FOURS -> Material.BEDROCK; + case ARMED_DOUBLES, ARMED_FOURS -> Material.DIAMOND_HOE; + case SWAPPAGE_DOUBLES, SWAPPAGE_FOURS -> Material.END_PORTAL_FRAME; + default -> Material.RED_BED; + }; + } + + public int maxPlayers() { + return teamSize * teams; + } + + @Nullable + public static BedWarsGameType from(@NotNull String field) { + for (BedWarsGameType type : values()) { + if (type.name().equalsIgnoreCase(field)) { + return type; + } + } + + return switch (field.toUpperCase()) { + case "SOLO" -> ONE_EIGHT; + case "DOUBLES" -> TWO_EIGHT; + case "TRIPLES", "THREE_THREE_THREE_THREE" -> FOUR_THREE; + case "QUADS", "FOUR_FOUR_FOUR_FOUR" -> FOUR_FOUR; + case "FOUR_FOUR" -> TWO_FOUR; + default -> null; + }; + } + + @Nullable + public static BedWarsGameType fromDisplayName(String displayName) { + for (BedWarsGameType type : values()) { + if (type.displayName.equalsIgnoreCase(displayName)) { + return type; + } + } + return null; + } + + @Nullable + public static BedWarsGameType fromId(int id) { + for (BedWarsGameType type : values()) { + if (type.id == id) { + return type; + } + } + return null; + } + + public boolean isDoublesSolo() { + return this == ONE_EIGHT || this == TWO_EIGHT || this == ULTIMATE_DOUBLES || this == LUCKY_BLOCK_DOUBLES; + } + + public boolean isLuckyBlock() { + return this == LUCKY_BLOCK_DOUBLES || this == LUCKY_BLOCK_FOURS; + } + + public boolean isOneBlock() { + return this == ONE_BLOCK; + } + + public boolean isSwappage() { + return this == SWAPPAGE_DOUBLES || this == SWAPPAGE_FOURS; + } + + public boolean allowsPersistentProgress() { + return !dream; + } + + public String getGameStartTitleKey() { + return isSwappage() ? "bedwars.game_start.swappage_title" : "bedwars.game_start.title"; + } + + public String getGameStartDescriptionKey() { + return isSwappage() ? "bedwars.game_start.swappage_description" : "bedwars.game_start.normal_description"; + } + + public BedWarsGameType getMapCompatibilityType() { + if (this == ONE_BLOCK) return this; + if (!dream) return this; + return switch (teamSize) { + case 1 -> ONE_EIGHT; + case 2 -> TWO_EIGHT; + case 3 -> FOUR_THREE; + case 4 -> teams == 2 ? TWO_FOUR : FOUR_FOUR; + default -> this; + }; + } + + // if you would do the enum names correctly, you could just use name() basically + public String getQueueModeDisplayName() { + return switch (this) { + case ONE_EIGHT -> "Eight One"; + case TWO_EIGHT -> "Eight Two"; + case FOUR_THREE -> "Four Three"; + case TWO_FOUR -> "Four Four"; + case ONE_BLOCK -> "Eight One Oneblock"; + default -> displayName; + }; + } + + public static List getDreamTypes() { + return Arrays.stream(BedWarsGameType.values()) + .filter(type -> type.dream) + .toList(); + } +} diff --git a/commons/src/main/java/net/swofty/commons/bedwars/BedwarsGameType.java b/commons/src/main/java/net/swofty/commons/bedwars/BedwarsGameType.java deleted file mode 100644 index 166738b3f..000000000 --- a/commons/src/main/java/net/swofty/commons/bedwars/BedwarsGameType.java +++ /dev/null @@ -1,65 +0,0 @@ -package net.swofty.commons.bedwars; - -import lombok.Getter; -import org.jetbrains.annotations.Nullable; - -@Getter -public enum BedwarsGameType { - SOLO(0, "Solo", 1, 8), - DOUBLES(1, "Doubles", 2, 8), - THREE_THREE_THREE_THREE(2, "3v3v3v3", 3, 4), - FOUR_FOUR_FOUR_FOUR(3, "4v4v4v4", 4, 4), - FOUR_FOUR(4, "4v4", 4, 2), - ULTIMATE_DOUBLES(5, "Ultimate", 2, 8), - ULTIMATE_FOURS(6, "Ultimate", 4, 4); - - private final int id; - private final String displayName; - private final int teamSize; - private final int teams; - - BedwarsGameType(int id, String displayName, int teamSize, int teams) { - this.id = id; - this.displayName = displayName; - this.teamSize = teamSize; - this.teams = teams; - } - - public int maxPlayers() { - return teamSize * teams; - } - - @Nullable - public static BedwarsGameType from(String field) { - for (BedwarsGameType type : values()) { - if (type.name().equalsIgnoreCase(field)) { - return type; - } - } - return null; - } - - @Nullable - public static BedwarsGameType fromDisplayName(String displayName) { - for (BedwarsGameType type : values()) { - if (type.displayName.equalsIgnoreCase(displayName)) { - return type; - } - } - return null; - } - - @Nullable - public static BedwarsGameType fromId(int id) { - for (BedwarsGameType type : values()) { - if (type.id == id) { - return type; - } - } - return null; - } - - public boolean isDoublesSolo() { - return this == SOLO || this == DOUBLES || this == ULTIMATE_DOUBLES; - } -} diff --git a/commons/src/main/java/net/swofty/commons/bedwars/BedwarsLeaderboardMode.java b/commons/src/main/java/net/swofty/commons/bedwars/BedwarsLeaderboardMode.java index c5103279d..b8bfe95a5 100644 --- a/commons/src/main/java/net/swofty/commons/bedwars/BedwarsLeaderboardMode.java +++ b/commons/src/main/java/net/swofty/commons/bedwars/BedwarsLeaderboardMode.java @@ -23,22 +23,22 @@ public enum BedwarsLeaderboardMode { this.displayName = displayName; } - private static final List CORE_MODES = Arrays.asList( - BedwarsGameType.SOLO, - BedwarsGameType.DOUBLES, - BedwarsGameType.THREE_THREE_THREE_THREE, - BedwarsGameType.FOUR_FOUR_FOUR_FOUR + private static final List CORE_MODES = Arrays.asList( + BedWarsGameType.ONE_EIGHT, + BedWarsGameType.TWO_EIGHT, + BedWarsGameType.FOUR_THREE, + BedWarsGameType.FOUR_FOUR ); - public boolean includes(BedwarsGameType gameType) { + public boolean includes(BedWarsGameType gameType) { return switch (this) { case ALL -> true; case CORE -> CORE_MODES.contains(gameType); - case SOLO -> gameType == BedwarsGameType.SOLO; - case DOUBLES -> gameType == BedwarsGameType.DOUBLES; - case THREE_THREE -> gameType == BedwarsGameType.THREE_THREE_THREE_THREE; - case FOUR_FOUR_FOUR -> gameType == BedwarsGameType.FOUR_FOUR_FOUR_FOUR; - case FOUR_FOUR -> gameType == BedwarsGameType.FOUR_FOUR; + case SOLO -> gameType == BedWarsGameType.ONE_EIGHT; + case DOUBLES -> gameType == BedWarsGameType.TWO_EIGHT; + case THREE_THREE -> gameType == BedWarsGameType.FOUR_THREE; + case FOUR_FOUR_FOUR -> gameType == BedWarsGameType.FOUR_FOUR; + case FOUR_FOUR -> gameType == BedWarsGameType.TWO_FOUR; }; } @@ -63,13 +63,14 @@ public static BedwarsLeaderboardMode fromKey(String key) { return ALL; } - public static BedwarsLeaderboardMode fromGameType(BedwarsGameType gameType) { + public static BedwarsLeaderboardMode fromGameType(BedWarsGameType gameType) { return switch (gameType) { - case SOLO -> SOLO; - case DOUBLES, ULTIMATE_DOUBLES -> DOUBLES; - case THREE_THREE_THREE_THREE -> THREE_THREE; - case FOUR_FOUR_FOUR_FOUR, ULTIMATE_FOURS -> FOUR_FOUR_FOUR; - case FOUR_FOUR -> FOUR_FOUR; + case ONE_EIGHT -> SOLO; + case TWO_EIGHT, ULTIMATE_DOUBLES -> DOUBLES; + case FOUR_THREE -> THREE_THREE; + case FOUR_FOUR, ULTIMATE_FOURS -> FOUR_FOUR_FOUR; + case TWO_FOUR -> FOUR_FOUR; + case null, default -> null; }; } } diff --git a/commons/src/main/java/net/swofty/commons/bedwars/BedwarsLevelColor.java b/commons/src/main/java/net/swofty/commons/bedwars/BedwarsLevelColor.java deleted file mode 100644 index 56f1b0845..000000000 --- a/commons/src/main/java/net/swofty/commons/bedwars/BedwarsLevelColor.java +++ /dev/null @@ -1,49 +0,0 @@ -package net.swofty.commons.bedwars; - -import lombok.Getter; - -import java.util.List; - -@Getter -public enum BedwarsLevelColor { - NONE(0, "§7", "✫"), - IRON(100, "§f", "✫"), - GOLD(200, "§6", "✫"), - DIAMOND(300, "§b", "✫"), - EMERALD(400, "§a", "✫"), - SAPPHIRE(500, "§b", "✫"), - RUBY(600, "§c", "✫"), - CRYSTAL(700, "§d", "✫"), - OPAL(800, "§8", "✫"), - AMETHYST(900, "§5", "✫"), - RAINBOW(1000, "§e", "✫"); - - private final int levelThreshold; - private final String color; - private final String icon; - - BedwarsLevelColor(int levelThreshold, String color, String icon) { - this.levelThreshold = levelThreshold; - this.color = color; - this.icon = icon; - } - - public static BedwarsLevelColor getByLevel(int level) { - for (BedwarsLevelColor levelColor : List.of(values()).reversed()) { - if (level >= levelColor.getLevelThreshold()) { - return levelColor; - } - } - return NONE; - } - - public static String constructLevelBrackets(int level) { - BedwarsLevelColor levelColor = getByLevel(level); - return String.format("%s[%s%s]", levelColor.getColor(), level, levelColor.getIcon()); - } - - public static String constructLevelString(int level) { - BedwarsLevelColor levelColor = getByLevel(level); - return String.format("%s%s%s", levelColor.getColor(), level, levelColor.getIcon()); - } -} diff --git a/commons/src/main/java/net/swofty/commons/bedwars/map/BedWarsMapsConfig.java b/commons/src/main/java/net/swofty/commons/bedwars/map/BedWarsMapsConfig.java index 21cf6404c..513a6fe2b 100644 --- a/commons/src/main/java/net/swofty/commons/bedwars/map/BedWarsMapsConfig.java +++ b/commons/src/main/java/net/swofty/commons/bedwars/map/BedWarsMapsConfig.java @@ -2,7 +2,11 @@ import lombok.Getter; import lombok.Setter; -import net.swofty.commons.bedwars.BedwarsGameType; +import net.minestom.server.item.Material; +import net.swofty.commons.bedwars.BedWarsGameType; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.commons.mc.Vec3i; +import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Map; @@ -23,18 +27,18 @@ public static class MapEntry { @Getter @Setter public static class MapConfiguration { - private List types; + private List types; private GeneratorSpeed generatorSpeed; private MapBounds bounds; private Map teams; private MapLocations locations; - private Map global_generator; + private Map globalGenerator; @Getter @Setter public static class MapLocations { - private Position waiting; - private Position spectator; + private HypixelPosition waiting; + private HypixelPosition spectator; } @Getter @@ -45,57 +49,70 @@ public static class MapBounds { private MinMax z; } - @Getter @Setter public static class GlobalGenerator { - private int amount; - private int max; - private List locations; + private List locations; // maybe Vec3i } } } - public record Position(double x, double y, double z) { + public record TwoBlockPosition(Vec3i feet, Vec3i head) { } - public record PitchYawPosition(double x, double y, double z, float pitch, float yaw) { + public record MinMax(double min, double max) { } - public record TwoBlockPosition(Position feet, Position head) { - } - - public record MinMax(double min, double max) { + public enum GlobalGeneratorKey { + IRON, GOLD, DIAMOND, EMERALD } public enum TeamKey { - RED("Red", "§c", 0xFF0000), - BLUE("Blue", "§9", 0x5555FF), - GREEN("Green", "§a", 0x55FF55), - YELLOW("Yellow", "§e", 0xFFFF55), - AQUA("Aqua", "§b", 0x00AAAA), - WHITE("White", "§f", 0xFFFFFF), - PINK("Pink", "§d", 0xFF55FF), - GRAY("Gray", "§7", 0xAAAAAA); + RED("Red", "§c", 0xFF5555, Material.RED_BED, Material.RED_WOOL), + BLUE("Blue", "§9", 0x5555FF, Material.BLUE_BED, Material.BLUE_BED), + GREEN("Green", "§a", 0x55FF55, Material.LIME_BED, Material.LIME_WOOL), + YELLOW("Yellow", "§e", 0xFFFF55, Material.YELLOW_BED, Material.YELLOW_WOOL), + AQUA("Aqua", "§b", 0x00AAAA, Material.LIGHT_BLUE_BED, Material.LIGHT_BLUE_WOOL), + WHITE("White", "§f", 0xFFFFFF, Material.WHITE_BED, Material.WHITE_WOOL), + PINK("Pink", "§d", 0xFF55FF, Material.PINK_BED, Material.PINK_WOOL), + GRAY("Gray", "§7", 0xAAAAAA, Material.GRAY_BED, Material.GRAY_WOOL), + ; @Getter private final String name; private final String chatColor; - private final int armorColor; + private final int rgb; + @NotNull + private final Material bedMaterial; + @NotNull + private final Material woolMaterial; - TeamKey(String name, String chatColor, int rbg) { + TeamKey(@NotNull String name, @NotNull String chatColor, int rgb, @NotNull Material bedMaterial, @NotNull Material woolMaterial) { this.name = name; this.chatColor = chatColor; - this.armorColor = rbg; + this.rgb = rgb; + this.bedMaterial = bedMaterial; + this.woolMaterial = woolMaterial; + } + + @NotNull + public String chatColor() { + return chatColor; } public int rgb() { - return armorColor; + return rgb; } - public String chatColor() { - return chatColor; + @NotNull + public Material bedMaterial() { + return bedMaterial; + } + + @NotNull + public Material woolMaterial() { + return woolMaterial; } } @@ -139,11 +156,11 @@ public int getGoldDelaySeconds() { @Setter public static class MapTeam { private Shops shop; - private PitchYawPosition spawn; + private HypixelPosition spawn; private TwoBlockPosition bed; - private Position generator; + private HypixelPosition generator; - public record Shops(PitchYawPosition item, PitchYawPosition team) { + public record Shops(HypixelPosition item, HypixelPosition team) { } } diff --git a/commons/src/main/java/net/swofty/commons/game/Game.java b/commons/src/main/java/net/swofty/commons/game/Game.java deleted file mode 100644 index b189bfbb3..000000000 --- a/commons/src/main/java/net/swofty/commons/game/Game.java +++ /dev/null @@ -1,52 +0,0 @@ -package net.swofty.commons.game; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import net.swofty.commons.ServerType; -import org.json.JSONObject; - -import java.util.List; -import java.util.UUID; - -@Setter -@Getter -@NoArgsConstructor -@AllArgsConstructor -public class Game { - private List involvedPlayers; - private List disconnectedPlayers; - private UUID gameId; - private ServerType type; - private String map; - private String gameTypeName; // e.g., "CLASSIC", "SOLO", "DOUBLE_UP" - - public JSONObject toJSON() { - JSONObject json = new JSONObject(); - json.put("gameId", gameId.toString()); - json.put("type", type.name()); - json.put("map", map); - json.put("gameTypeName", gameTypeName != null ? gameTypeName : ""); - List players = involvedPlayers.stream().map(UUID::toString).toList(); - json.put("players", players); - List disconnected = disconnectedPlayers != null - ? disconnectedPlayers.stream().map(UUID::toString).toList() - : List.of(); - json.put("disconnectedPlayers", disconnected); - return json; - } - - public static Game fromJSON(JSONObject json) { - Game game = new Game(); - game.gameId = UUID.fromString(json.getString("gameId")); - game.type = ServerType.valueOf(json.getString("type")); - game.map = json.getString("map"); - game.gameTypeName = json.optString("gameTypeName", null); - game.involvedPlayers = json.getJSONArray("players").toList().stream().map(obj -> UUID.fromString(obj.toString())).toList(); - game.disconnectedPlayers = json.has("disconnectedPlayers") - ? json.getJSONArray("disconnectedPlayers").toList().stream().map(obj -> UUID.fromString(obj.toString())).toList() - : List.of(); - return game; - } -} diff --git a/commons/src/main/java/net/swofty/commons/game/GameObject.java b/commons/src/main/java/net/swofty/commons/game/GameObject.java new file mode 100644 index 000000000..57998f21d --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/game/GameObject.java @@ -0,0 +1,55 @@ +package net.swofty.type.game.game; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.ServerType; +import org.json.JSONObject; + +import java.util.List; +import java.util.UUID; + +@Setter +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class GameObject { + private List involvedPlayers; + private List disconnectedPlayers; + private UUID gameId; + private ServerType type; + private String map; + private String gameTypeName; // e.g., "CLASSIC", "SOLO", "DOUBLE_UP" + private boolean acceptingJoins = true; + + public JSONObject toJSON() { + JSONObject json = new JSONObject(); + json.put("gameId", gameId.toString()); + json.put("type", type.name()); + json.put("map", map); + json.put("gameTypeName", gameTypeName != null ? gameTypeName : ""); + json.put("acceptingJoins", acceptingJoins); + List players = involvedPlayers.stream().map(UUID::toString).toList(); + json.put("players", players); + List disconnected = disconnectedPlayers != null + ? disconnectedPlayers.stream().map(UUID::toString).toList() + : List.of(); + json.put("disconnectedPlayers", disconnected); + return json; + } + + public static GameObject fromJSON(JSONObject json) { + GameObject game = new GameObject(); + game.gameId = UUID.fromString(json.getString("gameId")); + game.type = ServerType.valueOf(json.getString("type")); + game.map = json.getString("map"); + game.gameTypeName = json.optString("gameTypeName", null); + game.acceptingJoins = json.optBoolean("acceptingJoins", true); + game.involvedPlayers = json.getJSONArray("players").toList().stream().map(obj -> UUID.fromString(obj.toString())).toList(); + game.disconnectedPlayers = json.has("disconnectedPlayers") + ? json.getJSONArray("disconnectedPlayers").toList().stream().map(obj -> UUID.fromString(obj.toString())).toList() + : List.of(); + return game; + } +} diff --git a/commons/src/main/java/net/swofty/commons/guild/GuildData.java b/commons/src/main/java/net/swofty/commons/guild/GuildData.java new file mode 100644 index 000000000..8dbed6134 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/GuildData.java @@ -0,0 +1,247 @@ +package net.swofty.commons.guild; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.Serializer; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor(force = true) +public class GuildData { + private final UUID guildId; + private String name; + private String tag; + private String tagColor; + private final List members; + private final List ranks; + private long totalGexp; + private int level; + private String motd; + private String description; + private String discordLink; + private boolean listedInFinder; + private boolean slowChat; + private boolean everyoneMuted; + private long everyoneMutedExpiry; + private long createdAt; + private List auditLog = new ArrayList<>(); + private long dailyGexp; + private int dailyWins; + private String dailyProgressDate = LocalDate.now().toString(); + private boolean onlineMode; + + public static final int MAX_MEMBERS = 125; + private static final int MAX_CUSTOM_RANKS = 3; + private static final int TAG_UNLOCK_LEVEL = 5; + + private static final long[] LEVEL_THRESHOLDS = { + 100000, 150000, 250000, 500000, 750000, + 1000000, 1250000, 1500000, 2000000, 2500000, + 2500000, 3000000, 3000000, 3500000, 4000000, + 4500000, 5000000, 5500000, 6000000, 6500000, + 7000000, 7500000, 8000000, 8500000, 9000000, + 10000000, 11000000, 12000000, 13000000, 14000000 + }; + + public GuildData(UUID guildId, String name, UUID masterUuid) { + this.guildId = guildId; + this.name = name; + this.tag = ""; + this.tagColor = "§7"; + this.members = new ArrayList<>(); + this.ranks = new ArrayList<>(List.of( + GuildRank.guildMaster(), + GuildRank.officer(), + GuildRank.member() + )); + this.totalGexp = 0; + this.level = 0; + this.motd = ""; + this.description = ""; + this.discordLink = ""; + this.listedInFinder = true; + this.slowChat = false; + this.everyoneMuted = false; + this.everyoneMutedExpiry = 0; + this.createdAt = System.currentTimeMillis(); + + this.members.add(new GuildMember(masterUuid, "Guild Master", System.currentTimeMillis())); + } + + @JsonCreator + private GuildData(@JsonProperty("guildId") UUID guildId, @JsonProperty("name") String name, @JsonProperty("tag") String tag, @JsonProperty("tagColor") String tagColor, + @JsonProperty("members") List members, @JsonProperty("ranks") List ranks, + @JsonProperty("totalGexp") long totalGexp, @JsonProperty("level") int level, @JsonProperty("motd") String motd, @JsonProperty("description") String description, + @JsonProperty("discordLink") String discordLink, @JsonProperty("listedInFinder") boolean listedInFinder, @JsonProperty("slowChat") boolean slowChat, + @JsonProperty("everyoneMuted") boolean everyoneMuted, @JsonProperty("everyoneMutedExpiry") long everyoneMutedExpiry, @JsonProperty("createdAt") long createdAt, + @JsonProperty("auditLog") List auditLog, @JsonProperty("dailyGexp") Long dailyGexp, + @JsonProperty("dailyWins") Integer dailyWins, @JsonProperty("dailyProgressDate") String dailyProgressDate, + @JsonProperty("onlineMode") Boolean onlineMode) { + this.guildId = guildId; + this.name = name; + this.tag = tag; + this.tagColor = tagColor; + this.members = members; + this.ranks = ranks; + this.totalGexp = totalGexp; + this.level = level; + this.motd = motd; + this.description = description; + this.discordLink = discordLink; + this.listedInFinder = listedInFinder; + this.slowChat = slowChat; + this.everyoneMuted = everyoneMuted; + this.everyoneMutedExpiry = everyoneMutedExpiry; + this.createdAt = createdAt; + this.auditLog = auditLog != null ? auditLog : new ArrayList<>(); + this.dailyGexp = dailyGexp != null ? dailyGexp : 0; + this.dailyWins = dailyWins != null ? dailyWins : 0; + this.dailyProgressDate = dailyProgressDate != null ? dailyProgressDate : LocalDate.now().toString(); + this.onlineMode = onlineMode != null && onlineMode; + } + + @JsonIgnore + public UUID getMasterUuid() { + return members.stream() + .filter(m -> m.getRankName().equals("Guild Master")) + .map(GuildMember::getUuid) + .findFirst() + .orElseThrow(); + } + + public GuildMember getMember(UUID uuid) { + return members.stream() + .filter(m -> m.getUuid().equals(uuid)) + .findFirst() + .orElse(null); + } + + public GuildRank getRank(String name) { + return ranks.stream() + .filter(r -> r.getName().equalsIgnoreCase(name)) + .findFirst() + .orElse(null); + } + + public GuildRank getMemberRank(UUID uuid) { + GuildMember member = getMember(uuid); + if (member == null) return null; + return getRank(member.getRankName()); + } + + @JsonIgnore + public boolean isFull() { + return members.size() >= MAX_MEMBERS; + } + + @JsonIgnore + public boolean canAddCustomRank() { + long customCount = ranks.stream().filter(r -> !r.isDefault()).count(); + return customCount < MAX_CUSTOM_RANKS; + } + + @JsonIgnore + public boolean canSetTag() { + return level >= TAG_UNLOCK_LEVEL; + } + + @JsonIgnore + public int getMaxTagLength() { + if (level >= 50) return 7; + return 5; + } + + @JsonIgnore + public boolean canUseSpecialTagChars() { + return level >= 65; + } + + @JsonIgnore + public List getAllMemberUuids() { + return members.stream().map(GuildMember::getUuid).toList(); + } + + public void addGexp(long amount) { + this.totalGexp += amount; + recalculateLevel(); + } + + public void resetDailyProgressIfNeeded() { + String today = LocalDate.now().toString(); + if (!today.equals(dailyProgressDate)) { + dailyProgressDate = today; + dailyGexp = 0; + dailyWins = 0; + } + } + + public void addDailyGexp(long amount) { + resetDailyProgressIfNeeded(); + dailyGexp += amount; + } + + public void addDailyWin() { + resetDailyProgressIfNeeded(); + dailyWins++; + } + + public void addAuditLog(String entry) { + auditLog.addFirst(entry); + if (auditLog.size() > 500) auditLog.subList(500, auditLog.size()).clear(); + } + + public long getGexpForLevel(int targetLevel) { + if (targetLevel <= 0) return 0; + int idx = Math.min(targetLevel - 1, LEVEL_THRESHOLDS.length - 1); + return LEVEL_THRESHOLDS[idx]; + } + + private void recalculateLevel() { + long accumulated = 0; + int newLevel = 0; + for (int i = 0; i < 200; i++) { + long needed = getGexpForLevel(i + 1); + accumulated += needed; + if (totalGexp >= accumulated) { + newLevel = i + 1; + } else { + break; + } + } + this.level = newLevel; + } + + public GuildRank getNextRankUp(GuildRank currentRank) { + return ranks.stream() + .filter(r -> r.getPriority() < currentRank.getPriority()) + .max(Comparator.comparingInt(GuildRank::getPriority)) + .orElse(null); + } + + public GuildRank getNextRankDown(GuildRank currentRank) { + return ranks.stream() + .filter(r -> r.getPriority() > currentRank.getPriority()) + .min(Comparator.comparingInt(GuildRank::getPriority)) + .orElse(null); + } + + @JsonIgnore + public Serializer getSerializer() { + return getStaticSerializer(); + } + + public static Serializer getStaticSerializer() { + return new JacksonSerializer<>(GuildData.class); + } +} diff --git a/commons/src/main/java/net/swofty/commons/guild/GuildEvent.java b/commons/src/main/java/net/swofty/commons/guild/GuildEvent.java new file mode 100644 index 000000000..72f427d1b --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/GuildEvent.java @@ -0,0 +1,180 @@ +package net.swofty.commons.guild; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.Serializer; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public abstract class GuildEvent { + private GuildData guild; + + public GuildEvent(GuildData guild) { + this.guild = guild; + } + + @SuppressWarnings({"rawtypes", "unchecked"}) + @JsonIgnore + public Serializer getSerializer() { + return (Serializer) new JacksonSerializer<>(getClass()); + } + + @JsonIgnore + public List getParticipants() { + return guild != null ? guild.getAllMemberUuids() : List.of(); + } + + public static @NonNull GuildEvent findFromType(String className) { + String[] packageNames = { + "net.swofty.commons.guild.events", + "net.swofty.commons.guild.events.response" + }; + + for (String packageName : packageNames) { + try { + Class clazz = Class.forName(packageName + "." + className); + return createDummyInstance(clazz); + } catch (Exception e) { + // Try next package + } + } + + throw new RuntimeException("Failed to find guild event class: " + className + " in " + Arrays.toString(packageNames)); + } + + @SuppressWarnings("unchecked") + private static GuildEvent createDummyInstance(Class clazz) throws Exception { + String className = clazz.getSimpleName(); + + switch (className) { + case "GuildCreateRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, String.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), ""); + } + case "GuildInviteRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, UUID.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), UUID.randomUUID()); + } + case "GuildAcceptInviteRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, UUID.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), UUID.randomUUID()); + } + case "GuildLeaveRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class); + return (GuildEvent) c.newInstance(UUID.randomUUID()); + } + case "GuildKickRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, UUID.class, String.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), UUID.randomUUID(), ""); + } + case "GuildDisbandRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class); + return (GuildEvent) c.newInstance(UUID.randomUUID()); + } + case "GuildPromoteRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, UUID.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), UUID.randomUUID()); + } + case "GuildDemoteRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, UUID.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), UUID.randomUUID()); + } + case "GuildTransferRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, UUID.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), UUID.randomUUID()); + } + case "GuildChatRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, String.class, boolean.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), "", false); + } + case "GuildSettingRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, String.class, String.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), "", ""); + } + case "GuildMuteRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, String.class, long.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), "", 0L); + } + case "GuildUnmuteRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, String.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), ""); + } + case "GuildSetRankRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, UUID.class, String.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), UUID.randomUUID(), ""); + } + case "GuildProgressRequestEvent" -> { + var c = clazz.getDeclaredConstructor(UUID.class, long.class, boolean.class); + return (GuildEvent) c.newInstance(UUID.randomUUID(), 0L, false); + } + case "GuildCreatedResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID()); + } + case "GuildInviteSentResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, UUID.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), UUID.randomUUID()); + } + case "GuildMemberJoinedResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID()); + } + case "GuildMemberLeftResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID()); + } + case "GuildMemberKickedResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, UUID.class, String.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), UUID.randomUUID(), ""); + } + case "GuildDisbandedResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID()); + } + case "GuildRankChangedResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, UUID.class, String.class, String.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), UUID.randomUUID(), "", ""); + } + case "GuildTransferredResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, UUID.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), UUID.randomUUID()); + } + case "GuildChatResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, String.class, boolean.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), "", false); + } + case "GuildSettingChangedResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, String.class, String.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), "", ""); + } + case "GuildMuteChangedResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, String.class, long.class, boolean.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), "", 0L, false); + } + case "GuildInviteExpiredResponseEvent" -> { + var dummy = new GuildData(UUID.randomUUID(), "dummy", UUID.randomUUID()); + var c = clazz.getDeclaredConstructor(GuildData.class, UUID.class, UUID.class); + return (GuildEvent) c.newInstance(dummy, UUID.randomUUID(), UUID.randomUUID()); + } + default -> throw new IllegalArgumentException("Unknown guild event class: " + className); + } + } +} diff --git a/commons/src/main/java/net/swofty/commons/guild/GuildMember.java b/commons/src/main/java/net/swofty/commons/guild/GuildMember.java new file mode 100644 index 000000000..d926fc317 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/GuildMember.java @@ -0,0 +1,63 @@ +package net.swofty.commons.guild; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.Serializer; + +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor(force = true) +public class GuildMember { + private final UUID uuid; + private String rankName; + private long joinedAt; + private long weeklyGexp; + private long totalGexp; + private long lastLogin; + private boolean notificationsEnabled; + private long mutedUntil; + private boolean guildChatEnabled = true; + + public GuildMember(UUID uuid, String rankName, long joinedAt) { + this.uuid = uuid; + this.rankName = rankName; + this.joinedAt = joinedAt; + this.weeklyGexp = 0; + this.totalGexp = 0; + this.lastLogin = System.currentTimeMillis(); + this.notificationsEnabled = true; + this.mutedUntil = 0; + } + + @JsonCreator + public GuildMember(@JsonProperty("uuid") UUID uuid, @JsonProperty("rankName") String rankName, @JsonProperty("joinedAt") long joinedAt, @JsonProperty("weeklyGexp") long weeklyGexp, + @JsonProperty("totalGexp") long totalGexp, @JsonProperty("lastLogin") long lastLogin, @JsonProperty("notificationsEnabled") boolean notificationsEnabled, + @JsonProperty("mutedUntil") long mutedUntil, @JsonProperty("guildChatEnabled") Boolean guildChatEnabled) { + this.uuid = uuid; + this.rankName = rankName; + this.joinedAt = joinedAt; + this.weeklyGexp = weeklyGexp; + this.totalGexp = totalGexp; + this.lastLogin = lastLogin; + this.notificationsEnabled = notificationsEnabled; + this.mutedUntil = mutedUntil; + this.guildChatEnabled = guildChatEnabled == null || guildChatEnabled; + } + + @JsonIgnore + public boolean isMuted() { + return mutedUntil > System.currentTimeMillis(); + } + + public static Serializer serializer() { + return new JacksonSerializer<>(GuildMember.class); + } +} diff --git a/commons/src/main/java/net/swofty/commons/guild/GuildPermission.java b/commons/src/main/java/net/swofty/commons/guild/GuildPermission.java new file mode 100644 index 000000000..c0db8e63c --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/GuildPermission.java @@ -0,0 +1,16 @@ +package net.swofty.commons.guild; + +public enum GuildPermission { + INVITE, + KICK, + PROMOTE, + DEMOTE, + MODIFY_MOTD, + MODIFY_TAG, + MODIFY_SETTINGS, + OFFICER_CHAT, + MUTE_MEMBERS, + MODIFY_DISCORD, + MODIFY_DESCRIPTION, + MODIFY_GAMES +} diff --git a/commons/src/main/java/net/swofty/commons/guild/GuildRank.java b/commons/src/main/java/net/swofty/commons/guild/GuildRank.java new file mode 100644 index 000000000..f9e204c6b --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/GuildRank.java @@ -0,0 +1,70 @@ +package net.swofty.commons.guild; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.Serializer; + +import java.util.EnumSet; +import java.util.Set; + +@Getter +@Setter +@NoArgsConstructor +public class GuildRank implements Comparable { + private String name; + private int priority; + private boolean isDefault; + private Set permissions; + + @JsonCreator + public GuildRank(@JsonProperty("name") String name, @JsonProperty("priority") int priority, + @JsonProperty("default") @JsonAlias("isDefault") boolean isDefault, + @JsonProperty("permissions") Set permissions) { + this.name = name; + this.priority = priority; + this.isDefault = isDefault; + this.permissions = permissions; + } + + public boolean hasPermission(GuildPermission permission) { + return permissions.contains(permission); + } + + public boolean isHigherThan(GuildRank other) { + return this.priority < other.priority; + } + + @Override + public int compareTo(GuildRank other) { + return Integer.compare(this.priority, other.priority); + } + + public static GuildRank guildMaster() { + return new GuildRank("Guild Master", 0, true, + EnumSet.allOf(GuildPermission.class)); + } + + public static GuildRank officer() { + return new GuildRank("Officer", 1, true, + EnumSet.of( + GuildPermission.INVITE, + GuildPermission.KICK, + GuildPermission.OFFICER_CHAT, + GuildPermission.MUTE_MEMBERS + )); + } + + public static GuildRank member() { + return new GuildRank("Member", 100, true, + EnumSet.noneOf(GuildPermission.class)); + } + + public static Serializer serializer() { + return new JacksonSerializer<>(GuildRank.class); + } +} diff --git a/commons/src/main/java/net/swofty/commons/guild/GuildResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/GuildResponseEvent.java new file mode 100644 index 000000000..ea04fc64e --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/GuildResponseEvent.java @@ -0,0 +1,10 @@ +package net.swofty.commons.guild; + +import lombok.NoArgsConstructor; + +@NoArgsConstructor +public abstract class GuildResponseEvent extends GuildEvent { + public GuildResponseEvent(GuildData guild) { + super(guild); + } +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildAcceptInviteRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildAcceptInviteRequestEvent.java new file mode 100644 index 000000000..727f686f8 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildAcceptInviteRequestEvent.java @@ -0,0 +1,30 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildAcceptInviteRequestEvent extends GuildEvent { + @NotNull + private UUID accepter; + @NotNull + private UUID inviter; + + public GuildAcceptInviteRequestEvent(@NotNull UUID accepter, @NotNull UUID inviter) { + super(null); + this.accepter = accepter; + this.inviter = inviter; + } + + @Override + public List getParticipants() { + return List.of(accepter, inviter); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildChatRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildChatRequestEvent.java new file mode 100644 index 000000000..2fa7d5833 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildChatRequestEvent.java @@ -0,0 +1,32 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildChatRequestEvent extends GuildEvent { + @NotNull + private UUID sender; + @NotNull + private String message; + private boolean officerChat; + + public GuildChatRequestEvent(@NotNull UUID sender, @NotNull String message, boolean officerChat) { + super(null); + this.sender = sender; + this.message = message; + this.officerChat = officerChat; + } + + @Override + public List getParticipants() { + return List.of(sender); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildCreateRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildCreateRequestEvent.java new file mode 100644 index 000000000..9a3ef8fb9 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildCreateRequestEvent.java @@ -0,0 +1,35 @@ +package net.swofty.commons.guild.events; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +@Getter +public class GuildCreateRequestEvent extends GuildEvent { + @NotNull + private UUID creator; + @NotNull + private String guildName; + + @JsonCreator + public GuildCreateRequestEvent( + @JsonProperty("creator") final @NotNull UUID creator, + @JsonProperty("guildName") final @NotNull String guildName + ) { + super(null); + this.creator = Objects.requireNonNull(creator, "creator"); + this.guildName = Objects.requireNonNull(guildName, "guildName"); + } + + @Override + public List getParticipants() { + return List.of(creator); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildDemoteRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildDemoteRequestEvent.java new file mode 100644 index 000000000..199023045 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildDemoteRequestEvent.java @@ -0,0 +1,30 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildDemoteRequestEvent extends GuildEvent { + @NotNull + private UUID demoter; + @NotNull + private UUID target; + + public GuildDemoteRequestEvent(@NotNull UUID demoter, @NotNull UUID target) { + super(null); + this.demoter = demoter; + this.target = target; + } + + @Override + public List getParticipants() { + return List.of(demoter, target); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildDisbandRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildDisbandRequestEvent.java new file mode 100644 index 000000000..8086aab99 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildDisbandRequestEvent.java @@ -0,0 +1,27 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildDisbandRequestEvent extends GuildEvent { + @NotNull + private UUID disbander; + + public GuildDisbandRequestEvent(@NotNull UUID disbander) { + super(null); + this.disbander = disbander; + } + + @Override + public List getParticipants() { + return List.of(disbander); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildInviteRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildInviteRequestEvent.java new file mode 100644 index 000000000..94cd99305 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildInviteRequestEvent.java @@ -0,0 +1,28 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildInviteRequestEvent extends GuildEvent { + private @NotNull UUID inviter; + private @NotNull UUID invitee; + + public GuildInviteRequestEvent(@NotNull UUID inviter, @NotNull UUID invitee) { + super(null); + this.inviter = inviter; + this.invitee = invitee; + } + + @Override + public List getParticipants() { + return List.of(inviter, invitee); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildKickRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildKickRequestEvent.java new file mode 100644 index 000000000..ba48f2d2a --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildKickRequestEvent.java @@ -0,0 +1,33 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildKickRequestEvent extends GuildEvent { + @NotNull + private UUID kicker; + @NotNull + private UUID target; + @NotNull + private String reason; + + public GuildKickRequestEvent(@NotNull UUID kicker, @NotNull UUID target, @NotNull String reason) { + super(null); + this.kicker = kicker; + this.target = target; + this.reason = reason; + } + + @Override + public List getParticipants() { + return List.of(kicker, target); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildLeaveRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildLeaveRequestEvent.java new file mode 100644 index 000000000..b6db83201 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildLeaveRequestEvent.java @@ -0,0 +1,27 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildLeaveRequestEvent extends GuildEvent { + @NotNull + private UUID leaver; + + public GuildLeaveRequestEvent(@NotNull UUID leaver) { + super(null); + this.leaver = leaver; + } + + @Override + public List getParticipants() { + return List.of(leaver); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildMuteRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildMuteRequestEvent.java new file mode 100644 index 000000000..e6d6406e7 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildMuteRequestEvent.java @@ -0,0 +1,31 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildMuteRequestEvent extends GuildEvent { + @NotNull + private UUID muter; + private String target; // TODO: UUID + private long duration; + + public GuildMuteRequestEvent(@NotNull UUID muter, String target, long duration) { + super(null); + this.muter = muter; + this.target = target; + this.duration = duration; + } + + @Override + public List getParticipants() { + return List.of(muter); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildProgressRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildProgressRequestEvent.java new file mode 100644 index 000000000..a1a9d8ce5 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildProgressRequestEvent.java @@ -0,0 +1,26 @@ +package net.swofty.commons.guild.events; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildProgressRequestEvent extends GuildEvent { + private UUID player; + private long gexp; + private boolean win; + + @JsonCreator + public GuildProgressRequestEvent(@JsonProperty("player") UUID player, @JsonProperty("gexp") long gexp, + @JsonProperty("win") boolean win) { + super(null); + this.player = player; + this.gexp = gexp; + this.win = win; + } +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildPromoteRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildPromoteRequestEvent.java new file mode 100644 index 000000000..625c29a24 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildPromoteRequestEvent.java @@ -0,0 +1,30 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildPromoteRequestEvent extends GuildEvent { + @NotNull + private UUID promoter; + @NotNull + private UUID target; + + public GuildPromoteRequestEvent(@NotNull UUID promoter, @NotNull UUID target) { + super(null); + this.promoter = promoter; + this.target = target; + } + + @Override + public List getParticipants() { + return List.of(promoter, target); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildSetRankRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildSetRankRequestEvent.java new file mode 100644 index 000000000..c8e8df87e --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildSetRankRequestEvent.java @@ -0,0 +1,33 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildSetRankRequestEvent extends GuildEvent { + @NotNull + private UUID setter; + @NotNull + private UUID target; + @NotNull + private String rankName; + + public GuildSetRankRequestEvent(@NotNull UUID setter, @NotNull UUID target, @NotNull String rankName) { + super(null); + this.setter = setter; + this.target = target; + this.rankName = rankName; + } + + @Override + public List getParticipants() { + return List.of(setter, target); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildSettingRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildSettingRequestEvent.java new file mode 100644 index 000000000..c685d6cae --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildSettingRequestEvent.java @@ -0,0 +1,31 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildSettingRequestEvent extends GuildEvent { + @NotNull + private UUID changer; + private String setting; + private String value; + + public GuildSettingRequestEvent(@NotNull UUID changer, String setting, String value) { + super(null); + this.changer = changer; + this.setting = setting; + this.value = value; + } + + @Override + public List getParticipants() { + return List.of(changer); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildTransferRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildTransferRequestEvent.java new file mode 100644 index 000000000..a387225f7 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildTransferRequestEvent.java @@ -0,0 +1,30 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildTransferRequestEvent extends GuildEvent { + @NotNull + private UUID currentOwner; + @NotNull + private UUID newOwner; + + public GuildTransferRequestEvent(@NotNull UUID currentOwner, @NotNull UUID newOwner) { + super(null); + this.currentOwner = currentOwner; + this.newOwner = newOwner; + } + + @Override + public List getParticipants() { + return List.of(currentOwner, newOwner); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/GuildUnmuteRequestEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/GuildUnmuteRequestEvent.java new file mode 100644 index 000000000..bff8c00cc --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/GuildUnmuteRequestEvent.java @@ -0,0 +1,30 @@ +package net.swofty.commons.guild.events; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildUnmuteRequestEvent extends GuildEvent { + @NotNull + private UUID actor; + @NotNull + private String target; // TODO: UUID + + public GuildUnmuteRequestEvent(@NotNull UUID actor, @NotNull String target) { + super(null); + this.actor = actor; + this.target = target; + } + + @Override + public List getParticipants() { + return List.of(actor); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildChatResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildChatResponseEvent.java new file mode 100644 index 000000000..a7d504a07 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildChatResponseEvent.java @@ -0,0 +1,24 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildChatResponseEvent extends GuildResponseEvent { + private UUID sender; + private String message; + private boolean officerChat; + + public GuildChatResponseEvent(GuildData guild, UUID sender, String message, boolean officerChat) { + super(guild); + this.sender = sender; + this.message = message; + this.officerChat = officerChat; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildCreatedResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildCreatedResponseEvent.java new file mode 100644 index 000000000..d32e76120 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildCreatedResponseEvent.java @@ -0,0 +1,20 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildCreatedResponseEvent extends GuildResponseEvent { + private UUID creator; + + public GuildCreatedResponseEvent(GuildData guild, UUID creator) { + super(guild); + this.creator = creator; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildDisbandedResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildDisbandedResponseEvent.java new file mode 100644 index 000000000..342c0bd0d --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildDisbandedResponseEvent.java @@ -0,0 +1,20 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildDisbandedResponseEvent extends GuildResponseEvent { + private UUID disbander; + + public GuildDisbandedResponseEvent(GuildData guild, UUID disbander) { + super(guild); + this.disbander = disbander; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildInviteExpiredResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildInviteExpiredResponseEvent.java new file mode 100644 index 000000000..ed5797a42 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildInviteExpiredResponseEvent.java @@ -0,0 +1,28 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildInviteExpiredResponseEvent extends GuildResponseEvent { + private UUID inviter; + private UUID invitee; + + public GuildInviteExpiredResponseEvent(GuildData guild, UUID inviter, UUID invitee) { + super(guild); + this.inviter = inviter; + this.invitee = invitee; + } + + @Override + public List getParticipants() { + return List.of(inviter, invitee); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildInviteSentResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildInviteSentResponseEvent.java new file mode 100644 index 000000000..3ae47f0ab --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildInviteSentResponseEvent.java @@ -0,0 +1,30 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildInviteSentResponseEvent extends GuildResponseEvent { + private UUID inviter; + private UUID invitee; + + public GuildInviteSentResponseEvent(GuildData guild, UUID inviter, UUID invitee) { + super(guild); + this.inviter = inviter; + this.invitee = invitee; + } + + @Override + public List getParticipants() { + List participants = new java.util.ArrayList<>(getGuild().getAllMemberUuids()); + if (!participants.contains(invitee)) participants.add(invitee); + return participants; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberJoinedResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberJoinedResponseEvent.java new file mode 100644 index 000000000..f90e2697d --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberJoinedResponseEvent.java @@ -0,0 +1,20 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildMemberJoinedResponseEvent extends GuildResponseEvent { + private UUID joiner; + + public GuildMemberJoinedResponseEvent(GuildData guild, UUID joiner) { + super(guild); + this.joiner = joiner; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberKickedResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberKickedResponseEvent.java new file mode 100644 index 000000000..928c7be2c --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberKickedResponseEvent.java @@ -0,0 +1,32 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildMemberKickedResponseEvent extends GuildResponseEvent { + private UUID kicker; + private UUID kicked; + private String reason; + + public GuildMemberKickedResponseEvent(GuildData guild, UUID kicker, UUID kicked, String reason) { + super(guild); + this.kicker = kicker; + this.kicked = kicked; + this.reason = reason; + } + + @Override + public List getParticipants() { + List participants = new java.util.ArrayList<>(getGuild().getAllMemberUuids()); + if (!participants.contains(kicked)) participants.add(kicked); + return participants; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberLeftResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberLeftResponseEvent.java new file mode 100644 index 000000000..58d7ff561 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMemberLeftResponseEvent.java @@ -0,0 +1,28 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.List; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildMemberLeftResponseEvent extends GuildResponseEvent { + private UUID leaver; + + public GuildMemberLeftResponseEvent(GuildData guild, UUID leaver) { + super(guild); + this.leaver = leaver; + } + + @Override + public List getParticipants() { + List participants = new java.util.ArrayList<>(getGuild().getAllMemberUuids()); + if (!participants.contains(leaver)) participants.add(leaver); + return participants; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMuteChangedResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMuteChangedResponseEvent.java new file mode 100644 index 000000000..a5d6d7d18 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildMuteChangedResponseEvent.java @@ -0,0 +1,26 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildMuteChangedResponseEvent extends GuildResponseEvent { + private UUID muter; + private String target; + private long duration; + private boolean unmute; + + public GuildMuteChangedResponseEvent(GuildData guild, UUID muter, String target, long duration, boolean unmute) { + super(guild); + this.muter = muter; + this.target = target; + this.duration = duration; + this.unmute = unmute; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildRankChangedResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildRankChangedResponseEvent.java new file mode 100644 index 000000000..0f96c66d8 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildRankChangedResponseEvent.java @@ -0,0 +1,26 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildRankChangedResponseEvent extends GuildResponseEvent { + private UUID changer; + private UUID target; + private String fromRank; + private String toRank; + + public GuildRankChangedResponseEvent(GuildData guild, UUID changer, UUID target, String fromRank, String toRank) { + super(guild); + this.changer = changer; + this.target = target; + this.fromRank = fromRank; + this.toRank = toRank; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildSettingChangedResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildSettingChangedResponseEvent.java new file mode 100644 index 000000000..e1e242123 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildSettingChangedResponseEvent.java @@ -0,0 +1,24 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildSettingChangedResponseEvent extends GuildResponseEvent { + private UUID changer; + private String setting; + private String value; + + public GuildSettingChangedResponseEvent(GuildData guild, UUID changer, String setting, String value) { + super(guild); + this.changer = changer; + this.setting = setting; + this.value = value; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/guild/events/response/GuildTransferredResponseEvent.java b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildTransferredResponseEvent.java new file mode 100644 index 000000000..1404bea20 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/guild/events/response/GuildTransferredResponseEvent.java @@ -0,0 +1,22 @@ +package net.swofty.commons.guild.events.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildResponseEvent; + +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class GuildTransferredResponseEvent extends GuildResponseEvent { + private UUID oldOwner; + private UUID newOwner; + + public GuildTransferredResponseEvent(GuildData guild, UUID oldOwner, UUID newOwner) { + super(guild); + this.oldOwner = oldOwner; + this.newOwner = newOwner; + } + +} diff --git a/commons/src/main/java/net/swofty/commons/mc/HypixelPosition.java b/commons/src/main/java/net/swofty/commons/mc/HypixelPosition.java new file mode 100644 index 000000000..b2ea837a2 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/mc/HypixelPosition.java @@ -0,0 +1,36 @@ +package net.swofty.commons.mc; + + +public record HypixelPosition(double x, double y, double z, float yaw, float pitch) { + + public static HypixelPosition ZERO = new HypixelPosition(0, 0, 0); + + public HypixelPosition(double x, double y, double z) { + this(x, y, z, 0, 0); + } + + public HypixelPosition sub(double x, double y, double z) { + return new HypixelPosition(this.x - x, this.y - y, this.z - z, yaw, pitch); + } + + public HypixelPosition sub(double value) { + return sub(value, value, value); + } + + public HypixelPosition sub(HypixelPosition other) { + return sub(other.x, other.y, other.z); + } + + public HypixelPosition add(double x, double y, double z) { + return new HypixelPosition(this.x + x, this.y + y, this.z + z, yaw, pitch); + } + + public HypixelPosition add(double value) { + return add(value, value, value); + } + + public HypixelPosition add(HypixelPosition other) { + return add(other.x, other.y, other.z); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/mc/Vec3i.java b/commons/src/main/java/net/swofty/commons/mc/Vec3i.java new file mode 100644 index 000000000..e60e92d66 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/mc/Vec3i.java @@ -0,0 +1,42 @@ +package net.swofty.commons.mc; + + +import net.minestom.server.coordinate.BlockVec; + +public record Vec3i(int x, int y, int z) { + + public static Vec3i ZERO = new Vec3i(0, 0, 0); + + public Vec3i sub(int x, int y, int z) { + return new Vec3i(this.x - x, this.y - y, this.z - z); + } + + public Vec3i sub(int value) { + return sub(value, value, value); + } + + public Vec3i sub(Vec3i other) { + return sub(other.x, other.y, other.z); + } + + public Vec3i add(int x, int y, int z) { + return new Vec3i(this.x + x, this.y + y, this.z + z); + } + + public Vec3i add(int value) { + return add(value, value, value); + } + + public Vec3i add(Vec3i other) { + return add(other.x, other.y, other.z); + } + + public HypixelPosition asHypixelPosition() { + return new HypixelPosition(x, y, z); + } + + public BlockVec asBlockVec() { + return new BlockVec(x, y, z); + } + +} diff --git a/commons/src/main/java/net/swofty/commons/murdermystery/map/MurderMysteryMapsConfig.java b/commons/src/main/java/net/swofty/commons/murdermystery/map/MurderMysteryMapsConfig.java index 5ac83982d..d5f50b25f 100644 --- a/commons/src/main/java/net/swofty/commons/murdermystery/map/MurderMysteryMapsConfig.java +++ b/commons/src/main/java/net/swofty/commons/murdermystery/map/MurderMysteryMapsConfig.java @@ -2,6 +2,7 @@ import lombok.Getter; import lombok.Setter; +import net.swofty.commons.mc.HypixelPosition; import net.swofty.commons.murdermystery.MurderMysteryGameType; import java.util.List; @@ -24,25 +25,19 @@ public static class MapEntry { public static class MapConfiguration { private List types; private MapLocations locations; - private List goldSpawns; - private List playerSpawns; + private List goldSpawns; + private List playerSpawns; private List killRegions; @Getter @Setter public static class MapLocations { - private PitchYawPosition waiting; + private HypixelPosition waiting; } } } - public record Position(double x, double y, double z) { - } - - public record PitchYawPosition(double x, double y, double z, float pitch, float yaw) { - } - - public record KillRegion(String name, Position min, Position max) { + public record KillRegion(String name, HypixelPosition min, HypixelPosition max) { public boolean isComplete() { return min != null && max != null; } diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/game/ViewReplayPushProtocol.java b/commons/src/main/java/net/swofty/commons/protocol/objects/game/ViewReplayPushProtocol.java new file mode 100644 index 000000000..3a5fda2c8 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/game/ViewReplayPushProtocol.java @@ -0,0 +1,18 @@ +package net.swofty.commons.protocol.objects.game; + +import net.swofty.commons.protocol.ServicePushProtocol; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public class ViewReplayPushProtocol + extends ServicePushProtocol { + + public ViewReplayPushProtocol() { + super(Request.class, Response.class); + } + + public record Request(UUID uuid, String replayId, @Nullable String shareCode) {} + + public record Response(boolean success) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/guild/GetGuildProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/GetGuildProtocolObject.java new file mode 100644 index 000000000..f69b60ec5 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/GetGuildProtocolObject.java @@ -0,0 +1,26 @@ +package net.swofty.commons.protocol.objects.guild; + +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +import java.util.UUID; + +public class GetGuildProtocolObject extends ProtocolObject { + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(GetGuildMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(GetGuildResponse.class); + } + + public record GetGuildMessage(UUID memberUUID) { + } + + public record GetGuildResponse(GuildData guild) { + } +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/guild/GuildEventPushProtocol.java b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/GuildEventPushProtocol.java new file mode 100644 index 000000000..fad402299 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/GuildEventPushProtocol.java @@ -0,0 +1,27 @@ +package net.swofty.commons.protocol.objects.guild; + +import net.swofty.commons.protocol.ServicePushProtocol; + +import java.util.List; +import java.util.UUID; + +public class GuildEventPushProtocol + extends ServicePushProtocol { + + public GuildEventPushProtocol() { + super(Request.class, Response.class); + } + + public record Request(String eventType, String eventData, List participants) { + } + + public record Response(boolean success, List playersHandled, String error) { + public static Response success(List playersHandled) { + return new Response(true, playersHandled, null); + } + + public static Response failure(String error) { + return new Response(false, List.of(), error); + } + } +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/guild/IsPlayerInGuildProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/IsPlayerInGuildProtocolObject.java new file mode 100644 index 000000000..fe3e23826 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/IsPlayerInGuildProtocolObject.java @@ -0,0 +1,25 @@ +package net.swofty.commons.protocol.objects.guild; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +import java.util.UUID; + +public class IsPlayerInGuildProtocolObject extends ProtocolObject { + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(IsPlayerInGuildMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(IsPlayerInGuildResponse.class); + } + + public record IsPlayerInGuildMessage(UUID playerUUID) { + } + + public record IsPlayerInGuildResponse(boolean isInGuild) { + } +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/guild/SendGuildEventToServiceProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/SendGuildEventToServiceProtocolObject.java new file mode 100644 index 000000000..b98d5f680 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/guild/SendGuildEventToServiceProtocolObject.java @@ -0,0 +1,23 @@ +package net.swofty.commons.protocol.objects.guild; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +public class SendGuildEventToServiceProtocolObject extends ProtocolObject { + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(SendGuildEventToServiceMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(SendGuildEventToServiceResponse.class); + } + + public record SendGuildEventToServiceMessage(String eventType, String eventData) { + } + + public record SendGuildEventToServiceResponse(boolean success) { + } +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/orchestrator/GameHeartbeatProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/orchestrator/GameHeartbeatProtocolObject.java index ac9519f78..51ec53dda 100644 --- a/commons/src/main/java/net/swofty/commons/protocol/objects/orchestrator/GameHeartbeatProtocolObject.java +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/orchestrator/GameHeartbeatProtocolObject.java @@ -1,18 +1,19 @@ package net.swofty.commons.protocol.objects.orchestrator; import net.swofty.commons.ServerType; -import net.swofty.commons.game.Game; import net.swofty.commons.protocol.JacksonSerializer; import net.swofty.commons.protocol.ProtocolObject; import net.swofty.commons.protocol.Serializer; +import net.swofty.type.game.game.GameObject; import java.util.List; +import java.util.Objects; import java.util.UUID; import org.jetbrains.annotations.Nullable; public class GameHeartbeatProtocolObject extends ProtocolObject - { + { @Override public Serializer getSerializer() { @@ -24,7 +25,36 @@ public Serializer getReturnSerializer() { return new JacksonSerializer<>(HeartbeatResponse.class); } - public record HeartbeatMessage(UUID uuid, String shortName, ServerType type, int maxPlayers, int onlinePlayers, List games) { } + public record HeartbeatMessage( + UUID uuid, + String shortName, + ServerType type, + int maxPlayers, + int onlinePlayers, + List games, + List mapAdvertisements, + Integer remainingGameSlots + ) { + public HeartbeatMessage { + Objects.requireNonNull(uuid, "uuid"); + Objects.requireNonNull(shortName, "shortName"); + Objects.requireNonNull(type, "type"); + games = games != null ? List.copyOf(games) : List.of(); + mapAdvertisements = mapAdvertisements != null ? List.copyOf(mapAdvertisements) : List.of(); + } + + public HeartbeatMessage(UUID uuid, String shortName, ServerType type, int maxPlayers, int onlinePlayers, List games) { + this(uuid, shortName, type, maxPlayers, onlinePlayers, games, List.of(), null); + } + } + + public record MapAdvertisement(String mapId, String mapName, List supportedModes) { + public MapAdvertisement { + Objects.requireNonNull(mapId, "mapId"); + Objects.requireNonNull(mapName, "mapName"); + supportedModes = supportedModes != null ? List.copyOf(supportedModes) : List.of(); + } + } public record HeartbeatResponse(boolean success, @Nullable String error) { } } diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ChooseReplayProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ChooseReplayProtocolObject.java new file mode 100644 index 000000000..e68c53756 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ChooseReplayProtocolObject.java @@ -0,0 +1,32 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public class ChooseReplayProtocolObject extends ProtocolObject + { + + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(ChooseReplayMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(ChooseReplayResponse.class); + } + + public record ChooseReplayMessage(UUID player, String replayId, @Nullable String shareCode) { + public ChooseReplayMessage(UUID player, String replayId) { + this(player, replayId, null); + } + } + + public record ChooseReplayResponse(boolean error) { + } +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayDataBatchProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayDataBatchProtocolObject.java new file mode 100644 index 000000000..0775616ff --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayDataBatchProtocolObject.java @@ -0,0 +1,33 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +import java.util.UUID; + +public class ReplayDataBatchProtocolObject extends ProtocolObject< + ReplayDataBatchProtocolObject.BatchMessage, + ReplayDataBatchProtocolObject.BatchResponse> { + + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(BatchMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(BatchResponse.class); + } + + public record BatchMessage( + UUID replayId, + int batchIndex, + int startTick, + int endTick, + int recordableCount, + byte[] compressedData + ) {} + + public record BatchResponse(boolean success, long bytesReceived) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayEndProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayEndProtocolObject.java new file mode 100644 index 000000000..0bffecacb --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayEndProtocolObject.java @@ -0,0 +1,35 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +import java.util.UUID; + +public class ReplayEndProtocolObject extends ProtocolObject< + ReplayEndProtocolObject.EndMessage, + ReplayEndProtocolObject.EndResponse> { + + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(EndMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(EndResponse.class); + } + + public record EndMessage( + UUID replayId, + long endTime, + int durationTicks + ) {} + + public record EndResponse( + boolean success, + long totalBytes, + long compressedBytes, + boolean available + ) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayListProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayListProtocolObject.java new file mode 100644 index 000000000..ebfcff4ba --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayListProtocolObject.java @@ -0,0 +1,46 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.ServerType; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ReplayListProtocolObject extends ProtocolObject< + ReplayListProtocolObject.ListRequest, + ReplayListProtocolObject.ListResponse> { + + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(ListRequest.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(ListResponse.class); + } + + public record ListRequest(UUID playerId, int limit, ServerType filterType) {} + + public record ListResponse(boolean success, List replays) {} + + public record ReplaySummary( + UUID replayId, + String gameId, + ServerType serverType, + String serverId, + String gameTypeName, + String mapName, + long startTime, + long endTime, + int durationTicks, + int playerCount, + Map players, + String winnerId, + String winnerType, + long dataSize + ) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayLoadProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayLoadProtocolObject.java new file mode 100644 index 000000000..752256b66 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayLoadProtocolObject.java @@ -0,0 +1,65 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.ServerType; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ReplayLoadProtocolObject extends ProtocolObject< + ReplayLoadProtocolObject.LoadRequest, + ReplayLoadProtocolObject.LoadResponse> { + + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(LoadRequest.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(LoadResponse.class); + } + + public record LoadRequest(UUID replayId) {} + + public record LoadResponse( + boolean success, + String errorMessage, + ReplayMetadata metadata, + List dataChunks + ) {} + + public record ReplayMetadata( + UUID replayId, + String gameId, + ServerType serverType, + String serverId, + String gameTypeName, + String mapName, + String mapHash, + int version, + long startTime, + long endTime, + int durationTicks, + Map players, + Map> teams, + Map teamInfo, + String winnerId, + String winnerType, + long dataSize, + double mapCenterX, + double mapCenterZ + ) {} + + public record TeamInfo(String name, String colorCode, int color) {} + + public record DataChunk( + int chunkIndex, + int startTick, + int endTick, + byte[] compressedData + ) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayMapLoadProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayMapLoadProtocolObject.java new file mode 100644 index 000000000..ae8144235 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayMapLoadProtocolObject.java @@ -0,0 +1,31 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +public class ReplayMapLoadProtocolObject extends ProtocolObject< + ReplayMapLoadProtocolObject.MapLoadRequest, + ReplayMapLoadProtocolObject.MapLoadResponse> { + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(MapLoadRequest.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(MapLoadResponse.class); + } + + public record MapLoadRequest(String mapHash) { + } + + public record MapLoadResponse( + boolean success, + boolean found, + String mapHash, + byte[] compressedData, + int uncompressedSize + ) { + } +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayMapUploadProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayMapUploadProtocolObject.java new file mode 100644 index 000000000..896f52662 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayMapUploadProtocolObject.java @@ -0,0 +1,28 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +public class ReplayMapUploadProtocolObject extends ProtocolObject< + ReplayMapUploadProtocolObject.MapUploadMessage, + ReplayMapUploadProtocolObject.MapUploadResponse> { + + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(MapUploadMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(MapUploadResponse.class); + } + + public record MapUploadMessage( + String mapHash, + String mapName, + byte[] compressedData + ) {} + + public record MapUploadResponse(boolean success, boolean alreadyExists) {} +} diff --git a/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayStartProtocolObject.java b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayStartProtocolObject.java new file mode 100644 index 000000000..22178e687 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/protocol/objects/replay/ReplayStartProtocolObject.java @@ -0,0 +1,45 @@ +package net.swofty.commons.protocol.objects.replay; + +import net.swofty.commons.ServerType; +import net.swofty.commons.protocol.JacksonSerializer; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.Serializer; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ReplayStartProtocolObject extends ProtocolObject< + ReplayStartProtocolObject.StartMessage, + ReplayStartProtocolObject.StartResponse> { + + @Override + public Serializer getSerializer() { + return new JacksonSerializer<>(StartMessage.class); + } + + @Override + public Serializer getReturnSerializer() { + return new JacksonSerializer<>(StartResponse.class); + } + + public record StartMessage( + UUID replayId, + String gameId, + ServerType serverType, + String serverId, + String gameTypeName, + String mapName, + String mapHash, + long startTime, + double mapCenterX, + double mapCenterZ, + Map players, + Map> teams, + Map teamInfo + ) {} + + public record StartResponse(boolean success, String message) {} + + public record TeamInfo(String name, String colorCode, int color) {} +} diff --git a/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayCompression.java b/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayCompression.java new file mode 100644 index 000000000..79d89db94 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayCompression.java @@ -0,0 +1,30 @@ +package net.swofty.commons.replay.protocol; + +import com.github.luben.zstd.Zstd; +import com.github.luben.zstd.ZstdException; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.io.IOException; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class ReplayCompression { + private static final int LEVEL = 3; + + public static byte[] compress(byte[] data) { + return Zstd.compress(data, LEVEL); + } + + public static byte[] decompress(byte[] compressedData) throws IOException { + long size = Zstd.getFrameContentSize(compressedData); + if (size <= 0 || size > Integer.MAX_VALUE) { + throw new IOException("Invalid zstd frame content size: " + size); + } + + try { + return Zstd.decompress(compressedData, (int) size); + } catch (ZstdException e) { + throw new IOException("Failed to decompress replay zstd payload", e); + } + } +} diff --git a/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayDataReader.java b/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayDataReader.java new file mode 100644 index 000000000..db35a3fe6 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayDataReader.java @@ -0,0 +1,274 @@ +package net.swofty.commons.replay.protocol; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.BitSet; +import java.util.UUID; + +/** + * Efficient binary reader for replay data. + * Counterpart to ReplayDataWriter. + */ +public class ReplayDataReader implements AutoCloseable { + private final DataInputStream in; + + public ReplayDataReader(byte[] data) { + this.in = new DataInputStream(new ByteArrayInputStream(data)); + } + + public ReplayDataReader(InputStream inputStream) { + this.in = new DataInputStream(inputStream); + } + + /** + * Reads a byte. + */ + public int readByte() throws IOException { + return in.readByte(); + } + + /** + * Reads an unsigned byte. + */ + public int readUnsignedByte() throws IOException { + return in.readUnsignedByte(); + } + + /** + * Reads a short (2 bytes). + */ + public short readShort() throws IOException { + return in.readShort(); + } + + /** + * Reads an int (4 bytes). + */ + public int readInt() throws IOException { + return in.readInt(); + } + + /** + * Reads a long (8 bytes). + */ + public long readLong() throws IOException { + return in.readLong(); + } + + /** + * Reads a float (4 bytes). + */ + public float readFloat() throws IOException { + return in.readFloat(); + } + + /** + * Reads a double (8 bytes). + */ + public double readDouble() throws IOException { + return in.readDouble(); + } + + /** + * Reads a boolean (1 byte). + */ + public boolean readBoolean() throws IOException { + return in.readBoolean(); + } + + /** + * Reads a string with length prefix. + */ + public String readString() throws IOException { + int length = readVarInt(); + byte[] bytes = new byte[length]; + in.readFully(bytes); + return new String(bytes, StandardCharsets.UTF_8); + } + + /** + * Reads a UUID (16 bytes). + */ + public UUID readUUID() throws IOException { + long mostSig = in.readLong(); + long leastSig = in.readLong(); + return new UUID(mostSig, leastSig); + } + + /** + * Reads an unsigned VarInt (1-5 bytes). + */ + public int readVarInt() throws IOException { + int result = 0; + int shift = 0; + int b; + do { + b = in.readUnsignedByte(); + result |= (b & 0x7F) << shift; + shift += 7; + } while ((b & 0x80) != 0); + return result; + } + + /** + * Reads a signed VarInt using ZigZag encoding. + */ + public int readSignedVarInt() throws IOException { + int raw = readVarInt(); + // ZigZag decode: (raw >>> 1) ^ -(raw & 1) + return (raw >>> 1) ^ -(raw & 1); + } + + /** + * Reads a VarLong (1-10 bytes). + */ + public long readVarLong() throws IOException { + long result = 0; + int shift = 0; + int b; + do { + b = in.readUnsignedByte(); + result |= (long) (b & 0x7F) << shift; + shift += 7; + } while ((b & 0x80) != 0); + return result; + } + + /** + * Reads a half-precision float (2 bytes). + */ + public float readHalfFloat() throws IOException { + return halfToFloat(in.readShort()); + } + + /** + * Reads block coordinates using SignedVarInts. + */ + public int[] readBlockCoords() throws IOException { + int x = readSignedVarInt(); + int y = readSignedVarInt() - 80; // Undo Y offset + int z = readSignedVarInt(); + return new int[]{x, y, z}; + } + + /** + * Reads a location (x, y, z, yaw, pitch). + */ + public double[] readLocation() throws IOException { + int xWhole = readSignedVarInt(); + int yWhole = readSignedVarInt(); + int zWhole = readSignedVarInt(); + + float xFrac = readHalfFloat(); + float yFrac = readHalfFloat(); + float zFrac = readHalfFloat(); + + float[] look = readCompressedLook(); + + return new double[]{ + xWhole + xFrac, + yWhole + yFrac, + zWhole + zFrac, + look[0], // yaw + look[1] // pitch + }; + } + + /** + * Reads compressed yaw and pitch from 3 bytes. + */ + public float[] readCompressedLook() throws IOException { + int b1 = in.readUnsignedByte(); + int b2 = in.readUnsignedByte(); + int b3 = in.readUnsignedByte(); + + int packed = (b1 << 16) | (b2 << 8) | b3; + int yawBits = (packed >> 10) & 0x3FF; + int pitchBits = packed & 0x3FF; + + // Convert back from radians * 160 to degrees + float yaw = (float) (yawBits / 160.0 * 180.0 / Math.PI); + float pitch = (float) (pitchBits / 160.0 * 180.0 / Math.PI); + + return new float[]{yaw, pitch}; + } + + /** + * Reads a byte array with length prefix. + */ + public byte[] readBytes() throws IOException { + int length = readVarInt(); + byte[] bytes = new byte[length]; + in.readFully(bytes); + return bytes; + } + + /** + * Reads raw bytes. + */ + public byte[] readRawBytes(int length) throws IOException { + byte[] bytes = new byte[length]; + in.readFully(bytes); + return bytes; + } + + /** + * Reads a BitSet from bytes. + */ + public BitSet readBitSet(int numBits) throws IOException { + int numBytes = (numBits + 7) / 8; + byte[] bytes = new byte[numBytes]; + in.readFully(bytes); + return BitSet.valueOf(bytes); + } + + /** + * Returns available bytes to read. + */ + public int available() throws IOException { + return in.available(); + } + + /** + * Skips bytes. + */ + public void skip(int n) throws IOException { + in.skipBytes(n); + } + + @Override + public void close() throws IOException { + in.close(); + } + + /** + * Converts IEEE 754 half-precision to float. + */ + private static float halfToFloat(short half) { + int h = half & 0xFFFF; + int sign = (h >>> 15) & 0x1; + int exp = (h >>> 10) & 0x1F; + int mantissa = h & 0x3FF; + + if (exp == 0) { + if (mantissa == 0) { + return sign == 0 ? 0.0f : -0.0f; + } + // Subnormal number + float result = mantissa / 1024.0f * (float) Math.pow(2, -14); + return sign == 0 ? result : -result; + } else if (exp == 31) { + if (mantissa == 0) { + return sign == 0 ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY; + } + return Float.NaN; + } + + // Normal number + float result = (1.0f + mantissa / 1024.0f) * (float) Math.pow(2, exp - 15); + return sign == 0 ? result : -result; + } +} diff --git a/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayDataWriter.java b/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayDataWriter.java new file mode 100644 index 000000000..d9ff9da30 --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/replay/protocol/ReplayDataWriter.java @@ -0,0 +1,270 @@ +package net.swofty.commons.replay.protocol; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * Efficient binary writer for replay data. + * Supports VarInts, SignedVarInts, half-precision floats, and other optimized formats. + */ +public class ReplayDataWriter implements AutoCloseable { + private final DataOutputStream out; + private final ByteArrayOutputStream buffer; + + public ReplayDataWriter() { + this.buffer = new ByteArrayOutputStream(4096); + this.out = new DataOutputStream(buffer); + } + + public ReplayDataWriter(OutputStream outputStream) { + this.buffer = null; + this.out = new DataOutputStream(outputStream); + } + + /** + * Writes a byte. + */ + public void writeByte(int value) throws IOException { + out.writeByte(value); + } + + /** + * Writes a short (2 bytes). + */ + public void writeShort(int value) throws IOException { + out.writeShort(value); + } + + /** + * Writes an int (4 bytes). + */ + public void writeInt(int value) throws IOException { + out.writeInt(value); + } + + /** + * Writes a long (8 bytes). + */ + public void writeLong(long value) throws IOException { + out.writeLong(value); + } + + /** + * Writes a float (4 bytes). + */ + public void writeFloat(float value) throws IOException { + out.writeFloat(value); + } + + /** + * Writes a double (8 bytes). + */ + public void writeDouble(double value) throws IOException { + out.writeDouble(value); + } + + /** + * Writes a boolean (1 byte). + */ + public void writeBoolean(boolean value) throws IOException { + out.writeBoolean(value); + } + + /** + * Writes a string with length prefix. + */ + public void writeString(String value) throws IOException { + byte[] bytes = value.getBytes(java.nio.charset.StandardCharsets.UTF_8); + writeVarInt(bytes.length); + out.write(bytes); + } + + /** + * Writes a UUID (16 bytes). + */ + public void writeUUID(java.util.UUID uuid) throws IOException { + out.writeLong(uuid.getMostSignificantBits()); + out.writeLong(uuid.getLeastSignificantBits()); + } + + /** + * Writes an unsigned VarInt (1-5 bytes). + * More efficient for small positive numbers. + */ + public void writeVarInt(int value) throws IOException { + while ((value & ~0x7F) != 0) { + out.writeByte((value & 0x7F) | 0x80); + value >>>= 7; + } + out.writeByte(value); + } + + /** + * Writes a signed VarInt using ZigZag encoding. + * Efficient for small values (both positive and negative). + * Values -64 to 63 fit in 1 byte. + * Values -8192 to 8191 fit in 2 bytes. + */ + public void writeSignedVarInt(int value) throws IOException { + // ZigZag encoding: (value << 1) ^ (value >> 31) + writeVarInt((value << 1) ^ (value >> 31)); + } + + /** + * Writes a VarLong (1-10 bytes). + */ + public void writeVarLong(long value) throws IOException { + while ((value & ~0x7FL) != 0) { + out.writeByte((int) ((value & 0x7F) | 0x80)); + value >>>= 7; + } + out.writeByte((int) value); + } + + /** + * Writes a half-precision float (2 bytes). + * Reduced precision but half the storage. + */ + public void writeHalfFloat(float value) throws IOException { + out.writeShort(floatToHalf(value)); + } + + /** + * Writes block coordinates using SignedVarInts. + * Assumes coordinates are relative to map center. + */ + public void writeBlockCoords(int x, int y, int z) throws IOException { + writeSignedVarInt(x); + writeSignedVarInt(y + 80); // Offset Y to be closer to 0 + writeSignedVarInt(z); + } + + /** + * Writes a location (x, y, z, yaw, pitch) efficiently. + * Uses half-precision for fractional parts and compressed yaw/pitch. + */ + public void writeLocation(double x, double y, double z, float yaw, float pitch) throws IOException { + // Store whole part as SignedVarInt + writeSignedVarInt((int) x); + writeSignedVarInt((int) y); + writeSignedVarInt((int) z); + + // Store fractional parts as half-precision + writeHalfFloat((float) (x - (int) x)); + writeHalfFloat((float) (y - (int) y)); + writeHalfFloat((float) (z - (int) z)); + + // Write yaw/pitch compressed into 3 bytes + writeCompressedLook(yaw, pitch); + } + + /** + * Writes yaw and pitch compressed into 3 bytes. + * 10 bits for yaw, 10 bits for pitch. + */ + public void writeCompressedLook(float yaw, float pitch) throws IOException { + // Normalize to [0, 360) + yaw = ((yaw % 360) + 360) % 360; + pitch = ((pitch % 360) + 360) % 360; + + // Convert to radians, multiply by factor, take whole part + // Factor 160 fits in 10 bits (0-1023) for [0, 2π] + int yawBits = (int) (yaw * Math.PI / 180.0 * 160) & 0x3FF; + int pitchBits = (int) (pitch * Math.PI / 180.0 * 160) & 0x3FF; + + // Pack into 3 bytes (20 bits used, 4 bits unused) + int packed = (yawBits << 10) | pitchBits; + out.writeByte((packed >> 16) & 0xFF); + out.writeByte((packed >> 8) & 0xFF); + out.writeByte(packed & 0xFF); + } + + /** + * Writes a byte array with length prefix. + */ + public void writeBytes(byte[] bytes) throws IOException { + writeVarInt(bytes.length); + out.write(bytes); + } + + /** + * Writes raw bytes without length prefix. + */ + public void writeRawBytes(byte[] bytes) throws IOException { + out.write(bytes); + } + + /** + * Writes a BitSet as bytes. + */ + public void writeBitSet(java.util.BitSet bitSet, int numBits) throws IOException { + int numBytes = (numBits + 7) / 8; + byte[] bytes = bitSet.toByteArray(); + for (int i = 0; i < numBytes; i++) { + out.writeByte(i < bytes.length ? bytes[i] : 0); + } + } + + /** + * Gets the written data as a byte array. + */ + public byte[] toByteArray() { + if (buffer == null) { + throw new IllegalStateException("Cannot get byte array when writing to external stream"); + } + return buffer.toByteArray(); + } + + /** + * Resets the internal buffer. + */ + public void reset() { + if (buffer != null) { + buffer.reset(); + } + } + + /** + * Gets the current size of written data. + */ + public int size() { + return buffer != null ? buffer.size() : -1; + } + + @Override + public void close() throws IOException { + out.close(); + } + + /** + * Converts a float to IEEE 754 half-precision format. + */ + private static short floatToHalf(float value) { + int bits = Float.floatToIntBits(value); + int sign = (bits >>> 16) & 0x8000; + int val = (bits & 0x7FFFFFFF) + 0x1000; + + if (val >= 0x47800000) { + if ((bits & 0x7FFFFFFF) >= 0x47800000) { + if (val < 0x7F800000) { + return (short) (sign | 0x7C00); + } + return (short) (sign | 0x7C00 | ((bits & 0x007FFFFF) >>> 13)); + } + return (short) (sign | 0x7BFF); + } + + if (val >= 0x38800000) { + return (short) (sign | ((val - 0x38000000) >>> 13)); + } + + if (val < 0x33000000) { + return (short) sign; + } + + val = (bits & 0x7FFFFFFF) >>> 23; + return (short) (sign | (((bits & 0x007FFFFF) | 0x00800000) + (0x00800000 >>> (val - 102)) >>> (126 - val))); + } +} diff --git a/commons/src/main/java/net/swofty/commons/scoreboard/ScoreboardData.java b/commons/src/main/java/net/swofty/commons/scoreboard/ScoreboardData.java new file mode 100644 index 000000000..2e8db3eef --- /dev/null +++ b/commons/src/main/java/net/swofty/commons/scoreboard/ScoreboardData.java @@ -0,0 +1,84 @@ +package net.swofty.commons.scoreboard; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +@Getter +public final class ScoreboardData { + private final String title; + private final List lines; + + private ScoreboardData(String title, List lines) { + this.title = title; + this.lines = List.copyOf(lines); + } + + public void forEachLine(Consumer consumer) { + lines.forEach(consumer); + } + + public boolean differs(ScoreboardData other) { + if (other == null) return true; + if (!title.equals(other.title)) return true; + if (lines.size() != other.lines.size()) return true; + for (int i = 0; i < lines.size(); i++) { + if (!lines.get(i).equals(other.lines.get(i))) { + return true; + } + } + return false; + } + + public record Line(String text, int score) { + public Line(String text) { + this(text, 0); + } + + public String plainText() { + return text.replaceAll("§[0-9a-fk-orA-FK-OR]", ""); + } + } + + public static Builder builder() { + return new Builder(); + } + + public static ScoreboardData of(String title, List lines) { + Builder builder = builder().title(title); + for (int i = 0; i < lines.size(); i++) { + builder.line(lines.get(i), lines.size() - i); + } + return builder.build(); + } + + public static class Builder { + private String title = ""; + private final List lines = new ArrayList<>(); + + public Builder title(String title) { + this.title = title != null ? title : ""; + return this; + } + + public Builder line(String text, int score) { + lines.add(new Line(text != null ? text : "", score)); + return this; + } + + public Builder line(String text) { + return line(text, 15 - lines.size()); + } + + public Builder clear() { + lines.clear(); + return this; + } + + public ScoreboardData build() { + return new ScoreboardData(title, lines); + } + } +} diff --git a/commons/src/main/java/net/swofty/commons/skyblock/item/attribute/attributes/ItemAttributePotionData.java b/commons/src/main/java/net/swofty/commons/skyblock/item/attribute/attributes/ItemAttributePotionData.java index 424521c0a..b7ee510e7 100644 --- a/commons/src/main/java/net/swofty/commons/skyblock/item/attribute/attributes/ItemAttributePotionData.java +++ b/commons/src/main/java/net/swofty/commons/skyblock/item/attribute/attributes/ItemAttributePotionData.java @@ -4,6 +4,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import net.swofty.commons.StringUtility; import net.swofty.commons.skyblock.item.attribute.ItemAttribute; import net.swofty.commons.skyblock.statistics.ItemStatistics; import org.jetbrains.annotations.Nullable; @@ -121,7 +122,7 @@ public String getFormattedDuration(int alchemyLevel) { */ public String getDisplayName() { String prefix = isSplash ? "Splash " : ""; - String levelRoman = toRoman(level); + String levelRoman = StringUtility.getAsRomanNumeral(level); return prefix + "Potion of " + formatEffectName(effectType) + " " + levelRoman; } @@ -129,7 +130,7 @@ public String getDisplayName() { * Get just the effect display (e.g., "Speed V") */ public String getEffectDisplay() { - return formatEffectName(effectType) + " " + toRoman(level); + return formatEffectName(effectType) + " " + StringUtility.getAsRomanNumeral(level); } /** @@ -151,17 +152,6 @@ private static String formatEffectName(String effectType) { return result.toString(); } - /** - * Convert integer to Roman numeral - */ - private static String toRoman(int level) { - String[] romans = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"}; - if (level >= 1 && level <= 10) { - return romans[level]; - } - return String.valueOf(level); - } - /** * Create a copy with updated level */ diff --git a/commons/src/main/java/net/swofty/commons/skywars/map/SkywarsMapsConfig.java b/commons/src/main/java/net/swofty/commons/skywars/map/SkywarsMapsConfig.java index a20cfb5e5..0eb2a2b39 100644 --- a/commons/src/main/java/net/swofty/commons/skywars/map/SkywarsMapsConfig.java +++ b/commons/src/main/java/net/swofty/commons/skywars/map/SkywarsMapsConfig.java @@ -2,6 +2,7 @@ import lombok.Getter; import lombok.Setter; +import net.swofty.commons.mc.HypixelPosition; import net.swofty.commons.skywars.SkywarsGameType; import java.util.List; @@ -23,7 +24,7 @@ public static class MapEntry { @Setter public static class MapConfiguration { private List types; - private PitchYawPosition center; + private HypixelPosition center; private List islands; private int voidY; private MapBounds bounds; @@ -34,16 +35,10 @@ public static class MapConfiguration { @Setter public static class IslandSpawn { private int teamId; - private PitchYawPosition cageCenter; + private HypixelPosition cageCenter; } - public record Position(double x, double y, double z) { - } - - public record PitchYawPosition(double x, double y, double z, float pitch, float yaw) { - } - - public record MapBounds(Position min, Position max) { + public record MapBounds(HypixelPosition min, HypixelPosition max) { public boolean isWithinBounds(double x, double y, double z) { if (min == null || max == null) return true; double minX = Math.min(min.x(), max.x()); diff --git a/configuration/PicoLimbo.jar b/configuration/PicoLimbo.jar index 612cc98c2..a4335b4bb 100644 Binary files a/configuration/PicoLimbo.jar and b/configuration/PicoLimbo.jar differ diff --git a/configuration/bedwars/cosmetics.yml b/configuration/bedwars/cosmetics.yml new file mode 100644 index 000000000..4a34d3e89 --- /dev/null +++ b/configuration/bedwars/cosmetics.yml @@ -0,0 +1,1398 @@ +gamemode: BEDWARS +categories: + PROJECTILE_TRAILS: + items: [ ] + + VICTORY_DANCES: + items: [ ] + + FINAL_KILL_EFFECTS: + items: [ ] + + SPRAYS: + defaultSelectionId: "hypixel_logo" + favoriteable: true + random: true + items: + - id: "hypixel_logo" + name: "Hypixel Logo" + material: PLAYER_HEAD + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/9XaTZbbIAwA4PV04ys0bL3ICRRuMTkJG05fI/4NjpGDrFf1dRbJTD6BMVJs//krGj/b/4dYYApyPCaQfk6Idzc+JzBrFvr2Tf4xfodfc2YXH/90xvE/cEf4x6wD7y0AiwEhTvlJfsB3vD7nJ/iBhz2vR/hZvietcuGT0AOTf9WvzqzEe53G0/3m1N58P/UF75ceg9/ZWt5h2V/iaX53a3N+ww/OPslvt5nCL489gR/3Sz3tLsnf8fP9rEOK5Fd88AeHNeb39MLf83Z4+GN+4gMcoNq3ybfWfKy5VL/WbYrKL/mTmk/0K97avp9492OqH/hGr/z0mmbxy+La89NLarp/zGc/89P9xDd6x1csvjHrunb4xlfBP+t5qf6Kceqrwh/lz/x39psMVO0rJt8kv85A1b7i843pTIGqfcXrYwJ61brgS18x+T58Ao7XBa/29ZfNf/gp0C5UPti7+svoYwZOB/RDvb/Tf6APOP7YbtzuA44/dTsHPrD424duCWx+brb6PvD5OP7cbHV94POxBSl6vbv97bMtZL7jW+bxW/Sb+pd4Zt+i39bfvCad/+LyLfqd+pvX5Oa/2MZf+/v917+oX3zz7wCtEq863z+45x+iv68/NvkvRh+iv69/gQerX4w+RH9ffxPvfNb9r6i/at9/A46fd//N9bfxwX335d7/U/1tfMArD/y+6vvIy/mBd77mr7+NH3nrWjRG31b+04fJvHVNKtEf+1fU3zz+PQ/RH/3U8Tsvuf62kXi4Mv5h3+582/B0fxk9AK2fd73EZ3/4ACxXx9/jL83/8Pqr/C5PX3/Lcm3++zx9/pfl0vgP+Cvn35XxH/FX1t/ggwqlf8jn8Y/G6OEv5/+YvzD/9PF/4C+Mn+znXi/HVz5x/eVeL90H+2L9Uccf+m/s9T74lPFT/NB/Q7zLtL1xp++vP8Wld7sP/vpfXPl3++CvP6YT724fr38WvZ6Mn3s9ofHHXU/Ot1bk/It+7PWk1l/s9YTWX+r1pHwQ9KHo9Y59w+UDFFbfXxl9GPFXw+VvgBb0HX/mr843XL6W9bWsr/8b/xdDxN8i8EI+/ha+K+JHXtCH3Bzf7qPu+dm+GfDDO/6rmZRP4Md9M+xT+Pm+JfGTfRv14Q14lh8uhBiaTvH9Ayhr188yTZ/k10HhSf464JPwLZ5f+9/FgO+LqbT/6x8Bk/N/30K+wedP3dzjE4ASPt759xmI+JiAn4L7/ZxA9/sHv18kABom+8+R3yoSEPG7CdzphwSsmO/LTH2v41Y/1rl8x+Vmv6q0Nl9/vhyLq/0U/9teo+G3BBaS36TwvT/af0wPad8ff0HfJ/HjpuEpEXgAfv4B6enjXABAAAA=" + - id: "creeper" + name: "Creeper" + material: CREEPER_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aWW7bMBAG4EfDfdEVqBPkJJIAHSUB9ChfvRL32cghrUTowqKJYyf+fs6Qopv6l7l1PI+/423DRriPtwHix5sC3FuF//54e//vHH+c/3r5z/f4r9cLypsbP+GfsvNfIcaWxs/4McQZwMHTtPQn6Fp/Vt+CfvhLdwK9Hybtbma69XsT1P1935Pu25/jMUBXAqWf8WHq84T9ngQ6n+jzMRh/mVoTFPzdDnuT0UGA5B+jKQHn70m3CfYdFn4m/pT7TQmgH+ab6XaQqUN/npcp9xsSAD8UfMeDTD33z5uLr0GqiDIB5xOe1X0Ad2vxXchaokug8AXc+vHmMvUlIP3fR9XU3exn6oMm1BMw61819Tm2nvogQ6OvK3xc+qIPtoLSB7UvFD7b+LgAvF8IIPgFPL/skAIwvr8kCxlQ/es671u57PMJqF8qvBAgrXzOLwbAfjzZ9f5Ell63H3XsT4KffZGpks8EyP2EowDMl/EuzsdD5wM9gTTOzD0+kbK3++CHUKmhz3VDUYCSvyF/kna6tBqv9tGQ/Dk8zNNqf8Tt1/vus8YnIXgf9b4SIIx6gJFUgfNJZyv+0XWdPyp8bmWVeLfqWnyp/iO+6qt1H0BR/xGvQZ1fwesF0F5/IaDFF/+DigaU/JHz63o6rzUNaPOrery0X+OXXnYwfjpZaw1Q+aQARX8Do+JL/xLo8meMaxtwlU91jU915vVXpx8K857fWYCsMd/gh6ub4MPvLTVA5aMA2dWV9XHWkr+ua81HBYCXdxKA1qrcACbA4YM/2ZOS4wX6DK7xkSfNnzteNKPcgANAJaD+NkvHy/v+SvyBaYB0vGQKbUhvA4YRF0A+XqLe5i/x96IrWYF4+mcDxOMl4KUAvO+fcCUFGAYaQDxe8s60+4vzYYBhwA05KOF4AXtikVYCDZC18/TR/mMaoND9eccUotoAGGDA70jYSAFg49OW5Duh8LNB2m8XQGnhxUeElVD3Qf3J/MECAE+Md4WwEumvgvECMCYWYeD8jT1eyK4Izyn5KQH2Uxfo/jOr9fGsuBc9PpHsLwvjH0ZahXT+6ypd7dmdIfr5/8kA35Trf/p8ABb/PEapADYBXQBG8s/HeR+3/zOOmh8TZAtA8FfeR2v/Ew6F7+4IO7DRhzsf4Z9fX0o/HoFZAwR/U/jz/BVGNUDyN4WPC8D49v5mf+r2wboL9+v9pdWHAaTdLgTA170Gny+AdK2pFABehNICMNf6Mxn5GcgsANEPZwNugHSxZfEZn8HYN0XfJpAXAOuh8Xg8JiHB8QxG9lOOfv/ADw0liE3YUAC6/t/yHW4HSBD3QcWPLw+UC0DCSYI8QM1v2QEi7hM82vx8BzT4LA6KoPVDEaQGtOFZggbfSH4HHhNkBVD5K/Z7cZ8gfmfVX0svwoCux+1Qz5+9BHZO/ZEPtX8O2W+qOxy161/d1+MkgN9Dap8GaMNBgI3Riz4pQDueEvB6g9+J2wCCXfe39/GlgOv878Mrvm3A+/j2MubV6W/p1yyd+vnWxQJR9H2CjgwZfoXfFmKD+jt+e4gcN1Ve5aMIhQxo5oon/ujwpRBM3asZun2cItwT3izs+VoAlb/JAVyEhId3Czv4Ih8XQEgD3rjqfuyq+oMAbDXA25V3Dd3mm4xPX/jH6MSv902GG8izvm40+G48n6kF4IGoN2Vo9/OZsydrm/9xnb+f9nf7qfL83BufrMPnq945evwrxz/sD+fZf58/nMMMd/ut15+/xnf9v9F3IZ5nGT7uGLYBz9/dX8sIAEAAAA==" + - id: "thanks" + name: "Thanks" + material: PLAYER_HEAD + texture: "3e1debc73231f8ed4b69d5c3ac1b1f18f3656a8988e23f2e1bdbc4e85f6d46a" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+2ZS5LkKAyG19UbroDnAnUDjtARw8KbuUVuMoIFZ2+QBJJ4+JFZXY7ptnoyy+ah70fIgHN+2Pfs3/e6f6TPcpmBhOvwIKB+XyTg2ijc/OXy+b/Sbv7Nv/k3/+bf/Jt/84+aTyb/fjPfewSXv9fwi938P5ofXuMPup3mh5A/vaeHxD/mfd/kB7K+5nEA/zv5LGCIDxs9T/AdOnGjukePT5lAyUAdxz2P89HPxMmjG71IRncMv5v/zs2dPNrgy4fhWPgPPH8bY3g0c//ggKSxJ/sK/hl71IA4kP1+/M8KONvhf3T+gKeL0itlFiRXjFfy45wPFQfUnYu/erznyRURHeO+gAP8esxKFz/JfRLgyHtUGEl8lV+WEM8XzW6bHDvixkgX2FppSp+900HLl83LtW+sMMlIVO0Zq6RleYkvThX1jJ3NoXmfRu8UvVC8D4GFLVi9yElol+RB/PWxJvMUPhUIvpwWn/FSACdAKOh9vgw0jVfjHcLxYsRHCVjKKTDejhq+T82yF0LCLiL5uK0kLgcDDXY7j/EHfpFV0gP5nQLND5ngyZVHHG7kZHAlCxzTqVs7L75sxMPdWPMLpPDpJhQdoiAIAaExidcnse5UwPy0YxZI+hR+pUkZSkKPTwJ6fGC8FKD57LblqzAoAQP8kB92+AufGr/C/GBehEDBz/9iGr7N/LU1LKJu5VLVw62sh2/gD9pjyxiRW//PCz5UIZhk65q+/stfq0nN8z3xc0l2B1XQDvwZU/hwBa1g+Ktqn91R07owKX4S8GwtBPwGw8t1FfVZQP4j6uEbhk/tjXRoEB9xWTY4AbiiuoN81WDKD4Wv8OAr82kCTFaBawane2knnDb+n7LdswjQ/PU5aU/jjzX/gB7rmkLtxE3H7wo6flB8MRjaoRYIgTGQ/mC4uL7IBwGqvuA7PizPSUAmG1PGH+ueEr6Ev66lXcf3wI/4/PH4K/4lPiViqWe84tPDF2sGmiwhigRs+BPcHl/gOT3IYJNM/2WyofyDgPieP8v/AT8xBL9pZMTq52mXTiuAxfFb4POWQ3wWQ73l+JqChq9iDgJwBcwKkO89jD/zI04B71gd38C6bNg/LaYaqOWIiD+rmSqg8hfaglJJoD2r4wubFISOPxFgcG+KFhYAg/HPGWB5wya+mIxD/LY+KKsKiG9zBjLfjvjN4yNwfcFAX2gNSzMn4er825KDLZ8ZcimoPvycHzYEEN/u8cXNEX5Q/HCab+nIPePrcHd81/DHAkpfO+DbzPdjvm/5rucHyfcsQBzgtvm0BA358Dqk/Td8p/ksANYOxK+b/HwMirz/isUoe++G2/Gb+dH7gVgwN/hR8z3ztb+AJYqv4hP09OAKap5n+cWJkDLlY4Oe3yxYYc7HKfhivtMCwgY/rYJ4EAOTb1ApNfWD1L35te9qtWv3ErfLb16g8baoat/8M8UJTJTi5c8WhQ6+J/GPthdAdyUuxR3tF94SnwRQM9/yWV/2FqfzT1lIuyHiCQ6eiZ3M4Q6S+RYr+FcfD3s52D98tBQ/C83zz0a+wYNKxwd/1MB64mPiRLgSL+DexQKmNhI/HH/ZjYkvLPOhu+DbAV9MX3IGgisf8fFVPgSz8kX8VZOqwHJC9cGf8kX8uT+ikK8sWMGXNuC3hF2+6FEGN2iYYyAgLd9q/O78t/zI/HFDrGAGyfCR+XUQ5/j1usR/gy+NqeWqCpPNjvPHmFFF1KMW449v8u0EryroAZPUJv6H+dZv1o6t41vJb2yH/5LVqPNS+q38EXGC/zb+zH4bfzri7+Ifs5t/8/9m/ufNv/k3/+Zfxf+8+Tf/r+SbvPdfx4ffY625mn/Z+nM1H+f/6vOf+chh+LzCYAI+fgFnIGINAEAAAA==" + - id: "diamond" + name: "Diamond" + material: DIAMOND + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "invisibility_potion" + name: "Invisibility Potion" + material: POTION + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/9WbS3LjOAyG1/HGV1C8zSIXcGmhmqUz7uJhuEDJzNWHBCi+xLckaxqupG13Wd+PHyApUc6f4dT4kD+fpwVKOA+PAszvkwSc68LfzJ+mffid9Z8mFLBNxAbjNX9bdPIp80mr2CBjC3+hL4XokdHv/+THW/mTxgO4AnqiN//J8BmbOH8336bNZCBfCeCcv48P6L7iy384ot/DBxsogBNesunnYD5iARgFFoFrvoo38VXVI9F6sHY+Ga9Yo41uBZ18D+5LYAf7n8AbAazpaK187b7E3e8WTc/fwIf/A19CkOcIwJdv4nN+u90DNnpwu5GAFgXtfIWX/LsnAV/fSMDR/NtNiHsshGgX0Nz/jL8k//V6BXD5juS/juZ/Sv7rpuLlh37vLXwZ83zzY57x/YPrr042NH8VxFdr4qn8I9df9hfwoeWA+/P5kXysP8/wJf5IPp71JQQs+GP5QCd+82sdM0f8gXwgvhQwz79hzHMHvo/PEvx2fAcfcvxGehdfrcHn8I0ALkQoYBbieL45/5V8zwL56i38iTqA+H5Ivpp7204/2/h00Z3hNy29XXxScCZfKTiNLy+92ZT3v01DOx93PE7hmy0nnuDDkf47e40pPms8+azlT5ODl0k6/Sc8Pl92hHbnWzyo9T81/8CyI4Uf24v/adOXl5+Q5HPVAbxpT7qCb7fZJ2V9lq+ufpr2pCW/8MADDWavlba+MnzOHQHFo5fzN05OeOaB+Axf/v9kPCh6W+0/zj3Y+iU+TGZbtKIDruUCyMey7uiNxxwfW2Dh0yezx76W83fWPc4q+Fx1Ce5Ol29SVafv8UWUbwQA12bhZ/PpXysE0LpjLj5EDI8CtAJng7507Os/VfkTnwNL0l0FYCXgGMyMw6GmALb94taHRfD4pQJUfElBnXNU4bUAx38aBumoKb857yzjjQBO3aL5Gf8r8qdptw7vOSA/hjNBLv8yn2l+HT4oAc5FeX7JfrrP5OMhEisBbLlJlRt/lfkzi1esfyNhRRgH9D0ytt1/RvgoG5x3SYPAi0HQlcsJqOPreYcoPz8/a7wrC8C2wFY+c9zXh0/yHRWugGwB8vylfuDgUULMf88GrADbhQ/kvs491nmODvPCN2ArXxh+ToAb1II4A232X6X/eEQxKT2PBxqwE18oflyAERLgH3oMFhqghg+avxKQrMVjxU8JKIw/L38Zl6wHFm74qD8joGb8U/mJL6MGTgLoVDhrQBVfeHyKLDowoJsf2v+4fF3SMe7NZzG+VJAQMY5jyN/kP4vzvy7mQc9R0Rfyx5356iRilb+j4GK1XOhOdIqfYJT5Uf8j+S+3wuP8FKPCf/D73+G72S/5WwGGnyZU9B8AxMYfqXDz/6IOjPBzAkp8SPAzsR9/oAZM8b9MHMUfhuW6Y813qeMY5fMd+LjjZNcftwG0Bc5Ll++0/wF8gzdPD+L7DejjXb4V8Hg8q8tfPv83F55x/sV0n+U/lQCxlD9/+Co+rPhO+VcNQPnT6lc4eKX/1oAxIiDaf3ojpCigavwRPxTgIL2x+EP4Xfiw5B8RkJh/RoNnm/nLpT2nFiAB7lwTBk3/ZiduFz7tJ1oHpIKYBLv2OBuBfCf+suuJAp4oIYyHHve29rzc/pX1DwSgiDCcZYc2IVXyvGRABZ9bBUbAim4UWPMlG39l47tq/g1LEMU/nwF+D/7g81GASOCfT+HhocL/Il8FVdMREFcgAjwU6ZV8FUZASkFAV2N/Vz43I+FXiEDD8savYQOUx34Tf6B1AGDi6gsfYh3qbXMDpArexKcS4N1n/aWTgG3xFX3Xw7e3v1df/lnwWJ/6I7bxSwKo7i10yf/u4Ku/t4jQmxLfxKe/+PDhPfQm/uQJMH90srRcXzTlr3WE0cvu4E+hCSfwQwEDlqY9rmrtb/bfFUBPe9iElwKu7fUftIJB27GN3zL/RGScy98UWP8T+STiQ9nwfUZgAT7+AzOgEFwAQAAA" + - id: "disco_pumpkin" + name: "Disco Pumpkin" + material: ORANGE_WOOL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3YW67kIAwE0B3mI5uxhNR7H02nQwwumwISZTSCn3s7r1M4L8i+z7XPZJvkl7/85d/ui8h9vkivL992j/891ED/yQCc7wdwDksHmOSf9hu6f/3f6IcbuD5hP+kfFXjNl6tdvwf8Zmvph1tkIf1r/15fgsb65V6sfxCRXweg+CAB3XEnAKefAWyQXr0OQPuCn4U9px0FMK7HV5WwPtPn2G+4E361EfZJvgzQ1f1xv1gf+yhQl4+ymA1cH56QHh8Wg/b3Yb88+g2+CnCPj54A/pGRb0M65b8GPnmxTPjl86fli+KrNSYAV/+qtfxaqffnfMV1+Ejx+eD+09ywD58GoV886r9/7amgffWH9rXnXArP+gga83WMx/1H3n9v+/K2H2Sq/bnxz9s+H2D3fC7A5x/12QC77zMBPlP+Xrde/+P7jQCGBr4dd1wu0uH8c8r/1KMO3G3H9xNgPf7+0NbB/F/A+z74EBP5xOcX4vtLpD/5/blJP+xzbfnLX/7ylz/WtsmWJtvyl7/8J/y/o7cX/WP4+H/4Iv1+usk/5wDdPtdYfsCnCvCYn3e8x/fWN/lGhMnuc36QoNX/XwZ3JcdfAeoo7d5//+n0Df9jbTFaelz9Dt85GwA1emf9G3gZAHd5s7swPiGHfrzThi5FzEe/ygA8n6vi+fXBnZ+u3+JVkNBv/XZ8ntcB/O7nJejysH4PrwIEfOTLGz4qQB9v30cBby4Awo+TgPfRzX4QoCxTj4/ugMAHCexZespXt5ZdMupLdT44fzNLQEUCXxew2sT4eluvAII2In0dxfWzATwtc76z+68UwAedhLwaJABfIj2lg0+Un5eXesMH5jdUjpYk8PGIVy86ykL7yTa9+ALOaZ7Vix5L5Ne3OPLLWKV/1HwLWl0ddVjdOdzx0Adld3Xon2NsaNbnyfVBAPAEyOtK3+v1sVL5eY31BanONnb8g/oMLs7atweXstfefMD1zx/WLlKCUyv5lrcrah6N/9Rt4D6DG75yYh6Ov5stAd+DYn7IT9DHlEKBPjD/SmUr/fwIgp22upl/9uHJzH/9d28NYz9OYHl3/k/yeP5P68H3Bwb3fBTB2S44NNU8n23LX/7yl7/8d/w/fCk/OQBAAAA=" + - id: "reveillon" + name: "Reveillon" + material: COOKED_CHICKEN + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3ZW3LjKhAG4K0Ilx5kzx705teUSxtgDTyasmfthztN0wjQJZ5T5a7MJDYK3y+EsKRw/q1vfetb3/rWt771rVr9XasP8x/3Tw9Q4c/2a/zJfpU/OcCH/Qb+TN8Jb7LOD0C7WY5aN0usX/YXXGf47yb59/wCnfrS17H+mu19SdUh/gNUwSfxUpBO/0FUo/8ElfuSZGWLj1Jk/jOvE/yQga/KRZ8KILt9IQSf51Wb9GXBl12+ENbX9U/7z8QPxwvj8d0mXzT4kvA7918mqCz4cwoGX5J+x/yTyJfH+ARPn399Pj4RPuz7hSHzcb2WBb4020qwtGzxwaJU81+UT+x/iKO+BPaphRD7ZICX5pt8+BL5M338n2v+y+/7Enx2ss9YuuOq3u/oM8KXO/xn4jPrwwimwO4P2H90+fj8T/1BfSlgKMxCzec+qopPV6fPS76AP5M+mYM1+opf84VYlpr/XGKA8B5jO31nLXV/WeZYPsjgAgyuKn44V4jL37qvC43/EAZgTcc+S/1Hynf5NoC+sx1Ht+yUfXcLzNiAjn+zj+ef6pa5W+9xfJVL+6+X9wfs49lIz7+ct77tVgNNPtvoU6X9v95X/zX5w3l+KYA2/SMQ468F2OPTAQya+qVV+CRfTc/c1zNabPXvuvb49oTWUrc/m1uzLj+M/9v64TZXlIo7Cfs2lLkcu+v1Jz5cW/Pj4zntB50xOoC+/03BWIx5Xyr/vd1XNmNCMJIv+Ez76oPP+3p1NT3fauV44A9CDPpffvj9/X/imxdMT3r1zQ7AOKo7i6qcVvBF0V+QD8846w/2CChfdvK3m/PFAb6ubn8J++8K+8vJfjj1KL7mu9rhhwBqpMfxfsc+fP6V+S7A8wBfiPt9HJNLj0f2/C3zn89xDEvgHl/t/d1MBZr3z9/yNdD63AfY5rtlxkxFAldv+pv0zNfzT914uGW4n1cBwioHluK0Ho/4kABddkN/nrf4cZEt+Q/ogwS6hsE8+DjEL+qpDyI8pfblEX7hwbubD3yWdBlfZv7FFuXhJvcpV/Af3i8EcD5PfdX/VRUVwLdcWvxwMlR9Dn1t6O9EANVkWmKTu8Ah/vIBVgI+lwJI5+sE3CNX90MW4AKaoF97CM3n1QDGH8fMj0q5xehNfjHAbP2BY0SPM83HAGL1+j/xCwHm2d125756UfPX7z8cH66/8wj6Tf8sISfTCZC86vJjAKpWfDgW6XRwP688BQP8egDkR+WCfdiU+qUAob3ZB3vpFgJqAHyy0D8fi3QlAE/9oKC9v8F1JzQBf+Tr1e67wrwNkLbF7sOteGcE0BwUWxmft9XJWgDYSoH2SJRaen2cIT1mRb4YYIsPaozHTHc2TSRvPnKplmni+zKEOeP7owJo/0b5YfNdY8DBuE9EAjv2+RFItj2GJwNckm+lLQ/Rk0Fd9/Ocx/C65zY/+8VD9Lxr8vjTZ8ohPB7aK7EY0ydKfwCqj+sV+cRqPE306nzEAGh/Qu9kPO1385yjcTRUaXRTP/uAmjbw6ZLrRppahRA/5Qdl2uRzgPkjXRuAyIcAupdNvA0AOuz0/Xht5lEAc6o1+Bd3k7qfdwEcbyJM1TL4Bfg7eOUzxqbg+z1aK7ix/uVdvumAgS7/VAtszEz8Pb49AHbou3zzK7uH3/txSjX69pPhAJ+jMzCh/B8yCD9Mlp38mh//knKyP4EegRF9kC3Z+ACfIx/sHvbxFofw/5Q/tfjTb/lx/p/p6wSxvyv0qTkPtjpGjykQX6pjpn2L/+PqQ/7PDxng/+X/B4cXqiAAQAAA" + - id: "christmas_tree" + name: "Christmas Tree" + material: SPRUCE_SAPLING + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "careful_santa" + name: "Careful Santa" + material: PLAYER_HEAD + texture: "14e424b1676feec3a3f8ebade9e7d6a6f71f7756a869f36f7df0fc182d436e" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "easter_eggs" + name: "Easter Eggs" + material: PLAYER_HEAD + texture: "b5dbec524a95dea4d4d5802c95b0cf5eafebd31a9876772716a4862d6c88a" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3YW5KrIBAG4K1E9zDZhabMTuDBh9QUaz+Kgt10NzRO1FSd9MuIuXw/Fw3O63VO3X39+DqJlPjz/fv90u5j/nT/fm33P4s/279f2/2UP9n/8h/BX+J/+c+Y/M/grxr9S3jyo/N/8c3FfNNcyUf/Gn5sGh9gt96H2oNP5f0fxD9j6fU9AcbVvzU3Vi8m6JPawc8BblMF/plWBV8XYAz+bakXy2cCUL4qQPBHrz8lXgzA8RUBRlC359J73ucD8Lw+wIgqx7MBJF4dgPElngkg89oA1lq9nwbI8boASC/yh/ggQolPAnjlsXx0ZwA712iV3cd+z/j++FHnq0c/CcB1H/nlAEvvlwivkt+2bXjXm3wbKvIv7LUtbo4gADf8u/1wZgja/D16H/Gb35V8HwGeKfshQA/NGt9aM3fZWO5Fzh+2AiuQu+AUvoVFeeRDmQSA7AOtgu1e0KUBbFqi72tI2k/JD5dwwbfLwK9lSADeI22t3yV+2nkSgPpmqtCYDrcJwPY8YeukgVgdDmBx98Nh1p/fEBrToeSP26IRfTL3dA3wvtX6yQ9Rh3zUZ9xQ+nM7LgAy9ysv+WzPQxjZFxcgWXpoCUa+S3jD5rB1/kC6nx6mvjj3KMBAfO+RG9Dkd1U+GXDSjj4ZAOYGCH1w+38wvNa3gr/MAD47zP4WoAdR+pTv8qPP+NwKqPc74HMcuwJEPz01+0yAop+t4FOQLImi3wFf133gFwJ4nw9A+U7dfW2AIfpSgg5WgYdDsvmZAAP0uQRdJ/nc8Au+GCDwr03I4HW+Bb6QYIj+i1JclaZf9tkLD/iqAIhv2RImgEYYAO+m0vjOSSwXxDlyu+fKLaXinVb3pQrgnDpAJT/5igBOHSDX/eXpZofvnDaA4/zwXBX+1gZwThvArT7Ym4VWkiO+2PrP6PlcAHeEj+xfX7y+vOZa3h9jDOL7zwn6+qVQFwKE1yQ/gokfv1TUQ4BfVJy9+XCxpX6cCuynGTBHfKmSRZ/zW+LLdZjfaHllgiP89ALIvRMQOr/4pekNgP9AeI3325wvfimVyyX4bdF/U0l+e6g/bQTXo4b4TG1+8w5/2YliX1kF3m/Dtmb4jTnYT3ehkZn4Po0w78H9Rnz1twB0+z2ftK3ZNoj88PO+7+C033c9ejP87Z2L/LeN8bd3GM5PH4hBZ2ep67kPhQjG5HyLfIP82Fn/+0OGP/DEX7q/w8e8W7f8dAwiv0xyugpx25jMQzfyTeLjDQ/jb+NAzmgDgGExqb+q0B98qpzG+vkARuThahvwytsVIJPDcP7wBJ2t7jj0M0Ngos5efG8oExPwKcyxfAzADoLZ6jDfGU0dx6sCHMkrAhzL//7m9Z27Oy3uK8/v3WBq9UyAP25xtbwQ4e97bD2fZHjTHr/Sz9a7/coAb+frEhzBqxMchKsyHGvLOc5zv/Wtb5FaNqEX85dFgBvyq/1LAsDnkCt8+Ox9SQK0FbxgIqh+bgTpufwkXtDPCiDzZwTI6aUA/wAjWecYAEAAAA==" + - id: "bunny_gg" + name: "Bunny GG" + material: PLAYER_HEAD + texture: "be50af50438affc65ce3b7a85b8e82cfbc3cab197c25d4a614230a2d1e0605d" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/8XaSdKbMBAF4A2wVnEDOIVPQRW+TK4fG4TUw2u1xOC/N0kZ0Pc0ILCT9zvWqmpGtZgVT4gXv3GpxtExfs64lR+A+Y6e+2YcjzXmcgO4PBxa+xzO5wAlPmyVr3E6r/23pZ/zaQK8ruxhGmWVAxh+SgH5ZTHmSTfhBCjyeyEe+Z8EuIGLPm0iNYN4egFr8Lo/Ch74Uict2v7c7C+Gr3U1AFXdl5cKf/H9oP1gBVB+AFejIVwNPbBKn53xwRTmC/leafAhf3TWD9RfqJ8DBK2va7z6+AAPAJj+b3uGv3A/JiCDdFzz3QpW3o3dH1jBuy/tJcpflL9GXwTYr181L/xh0H7i19hA8hfgr8gXHSC8CtDgL9AXZ42ZJwNA9m7gs3GmPGtZrhzh0+UjArCHR3P3A+aJv8IGUif2h9exhhxfdz8erPZhgOMY8tHwr8IPQW8c0kcD8BYvJHIAit1P0bA/p1dmHuAtAoy0yj4fNvpoxP6RoDAA4+j4wfLTki35MYE1AKOsKp/MVr5nLH9PgAdA8cIXyw9cxW5Zw/8mgDOgebEA8fTT8z87Jxsw7H8SoHsQ+KPvq3fYASbg/owGoMbX0w8uQgni5iUCuBMwXvf3BNJHAcb4QHR9ctEqLzBGIE1gaQbS9lXjv7OvEugRUD56jQH+WPbl08TwaRONA8Cv1f7qhLYToHvwSIHaAtPPnnsVfv8pYwDMAJ6vemL6/VZDcQa0H6Q/Kn8/4Ph9rDwH3CdfUGhTwfCP6c9tFfk+V14DVgDGpwDm8Df5XUdWIfdXzAdr+ulj3xv+zHdDDhBQAKFLf3R9NPvdoXdkOnWAkVYQvljm7T7lwdssr7SvhNdW4DajfJ1/zIUfQOgvdJuP6aWrzt/c489BPVBh5+dZ+DprBT90Xc+qFCBQXfs6Qjjry5tK9X2vnaffL/CS2S+v8OldwNujxCwqhJoEkGe+uAtpawW9NgL2c4BO3oW5LU9HEVQGx+c6C1CjowSh0RdHdHtlHiUgGUw/bwHlAK5ejGDwdAUO+yaEA9TpVoSA7z42AHIP+NQpHkc45R8j0KhvNZz02Tqcuf4vVo2/NVbhswCd2AXEt7NmP2Ww+eR3qehRxFf5cy+q4PNiR6HfNgBuDMPeToc89tMDueiDABrPZzM/hzBwmsDydQoTr/Zfr1bfWg7yNOnHBNd9EAKdIeYf+kiv8/uifcInnzb4pTO4j24AhLf45TOqfbEkKn33jGf775fvz4/6ve8fEVz/VLIqH1SpqZYMz/j1GfL5l59/P/W/zU9bXfPTVZ8VFnl9sxf9lGCaLvrfBHCzcfw9wvbplENMngx8Y7Pz/U+Cg+Wpzvg1vPLz4Lf5edm06Pv0Yj9HaPN55R9mbZ8lYEev+m9aBZ9E4Id/5+ME9T4MkP7jCPtXXsMn03Crv9Lf2pU/4SL8BT9GOOHTuuTPu28dvc8vDADz+dbwvD9v80999gL+kM+QxG+fGt8/Lvv9Nd9O0eqrzV8sPxLAauqU36f2RZLdTx9X+PKtoMV/+X4ei5oA5301/t9D8riboNrvD//Fe8kHROUzgZt8/jqC3k3KQ9CkK0987cLvRsUhaNOlwV8HzVcz+QMvCdDK01/Z4l/4H6nXLEAsHaBBPx7c6tce+Fo8TTCByFHhowYlB96Kp2IAa0ZIxROt9tyanATFEOkU2tgJ3wmAIrDDZmdqfXaV74uj53tfG8C2JT+lv1fA1KcXmD6aG9AP0CfdYeUXhsCys08amVjZevFk4Vu44i9WaRH8gKcJGvwb+cYAt3e/LcATfE7wZ35tgIN/bBE08M8sgj/wZ7Z9V/O3bkE5gOdPtw//XBuA+bfxuT+OP7OgN/o8gNv9tGJu9r0AD209KkDJjyf/SQCy+m73UwDXf2oWyAB8rP8vekH2AEAAAA==" + - id: "fireworks" + name: "Fireworks" + material: FIREWORK_ROCKET + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+2aSZLkIAxFD9Q30MKH8IZ7eMkCrt5IYp4MGFdGdaciyun0wPtIQmBnCfG1r33ta1/7hSY/LaBj6gcYvf7/AB8G/f+GFCmklCDlSA685goJ1cOQUd/jN46rV6ktqMp6/L6AduxVxP9RR8CH+Y6m7B7Qp97Tdj3dcwG+v17KJvwYn7k65idn3uc7ASq7RS3hoxbO0XuC5zn+I8Kb4vjma4ZPMVeeDElxmLUgfoyvOd00+tv0n4biAL19yVns5NKw/YhBCpQWlg/RKWiEgq7r8a94J8N7FQGEcddaAWCz2l/QTgTonDvr/Ho4wMnQ5tO0Cpp1dmJA3jPXtmJQ53ezAZwp7vxtBrQC40lXRmzjuSnN7lfUtRs4KYwaqAoQcBaHOs2hsQsG4Ck/OONq8bt4zgDTfVSg0QkmCpolGV+MCDotMhaA/ERQA809MWmnldEg9OC8VVVgBTAZHL+Bx9FmTfOfVvn0N1EHCwGOX8ND3rBfhebT0ISA099q+U18aqbHgOXPREA8EUAKKBkjfsBfV/0u63DFqx94NO0bBRcLYH7U+QbdmXLbsYxvKyAB6ACTC3Zc3LHRIFoEPRNwCmAZVzYsb4zisOT8Kw3teYI4TSW7aCa4RkuaW4XpFRWXiBOMBVAQpsqJrqxCp1SQ4Z6f0Sb5kB5YVGHZJ5rEzRj+5lDVkCLOYBh9RNOGrsDnPn+20ciYpgk7T6/g/p1D78XAnNlcZ0cADoTp917R6nNBANPpD/ki4h/3xPLbGt1sTPEDqr/gBDT5PTVLdELbjXAOcPjMq8XT7sPphz78HEDbhJ8HVRcClqu/G14Elvhx0LeYnyejtkuf53w/uO36XxrUdXgHNKJf4h/S/eOHOL0AafpU51e676y1XOnTA56418FCLL8oBT38jIAEH5a98iKu4Sd47wvsfpmADr8gIHnm48iTADgC/gihIH4bPy3gLL6xAOLLnI543ev+UgQs5bBqSIAEGoXmYJKGxF9FtMxpPkiDuKREPo5qWwHIaKLSjd5TM6vdj984sAYjgOdFIocr9Rv86B5ORiMBVwIp2vPb7TwJv+dbX6OVBajO968AHjwF0E8t1GN8CGIHgE2IGz7S4RnfdYCeRw1WUO/J/YmCOj9qYMrKcJ0EBPr5iaqAqwBWRd39fjPPL1KG+45wyXVQ+hp4tCrvM35GR19yBQrD35/v82c1GPifPzld8M9uR7wE8Ao6ow+W+JVJmyqdm3wOf/COH0bhBL8yaUtK5pxvFWyv/UUKICXix7OPrPIfvXkoaiYxob72eoOPMYjixlF2lbd8DKsW32cC4jYsENKVd7z8qN38nJ8lLzRW/i/yk2b87shz8A7/C8j6v3bfA3r6ffzG5/BuIzft70m9ZcCezFtvZRN/fdW0hc/rtxUVm/iL9I18p+Kz/O3tfS3Y4D8ovBUC5e0lAFnliTXHv6NCBhvC71IhKzaOH1FBP22PgVv8G3xHBZ9JFr0dcEPAGL4qIeMPsEv+OL6U4Ph6ii/X8enzhcfz0eOY50/Sd/On8Vv4coWv9Uf5uuRH5yx/WsAsvc5He5Wv7/nqPb7W2/lygq8b/Pw6egu4n69f4Y8OAZ3bdn5XQoG/468JaEgo6RG/uPoRv9ZgDR8ErPILbkNCnb7O73ErElr4O34hYJCbSmjSPb/EZ/x5brAO/pY/+D8RD/kV/P/EL/Cf5out/J6AKv7/4tfxTsC/ze/gfyH/L4qX+EsAQAAA" + - id: "year_of_the_dog" + name: "Year of the Dog" + material: BONE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3bW3LrIAwG4PUI76APffQCshQ/evXHF8xFEiA5CHdOoplOU5L4+8EYu7ksy6fXulf+y7Cwt904f5Jflp3F3tdHe8fez7ws1jLCz73nfXKAmPoUGzPxUAx+/n+mP+TAoz6abKN9QdMYf8yBh3x0/D1UX//rf33xw91e+V9XDfATy/Fl6kcGoOCrIyj8xIBaAFUEhQ9nCXxFAqk/+XINWJtA5l+4pvr5md4aeWUCgX+XFwVo+1p+CiUJ0PT9tryb8WyWKau3/Wza494zozGRessPIwnHQY890kD5RgKR706cWXVQC8tXE9T9ZOrtODPeMr8cQOBzGr1R5csJqv5U9tkANb8QoOYTPrJxKoCQLwRo+mh3Q/DpitDw2QAVn3Y/9/2pWDr+fICW7xwOANHHh+QA3488ALcktHwmQNnnhj/pOr1D4NMADZ9T2JX4bB/klwqaAeR+OvzSIKAPUPeT/Uowpg3aAe747J7gGs38nx9MpbtH4+MAJT/dfsGnjaAPIPNpVwf6m8T6/Phb+FRyR6YnfaYV+vnTfV8X4G/610MbPrf7+/vs8jvSZ+tpn6nevk7v7Wv1zn6yXelgGPmTdG/09LMNP+4LBj/+T/Jf+fsN+dWvQf+PZ+x/t0KA1fj7ltYrf2b+a3m9Xu0XHu381wN+EuDkxcPf6foHb1nc/e6+qKC3f+/cL/AXia8NcLf7f9bXBYD+vmYOgsJHSPX1zzt8R7/4Lm+N7+pLEoDKx9tvv/+l0/v71QSUn1W8/P1nGT9vZeMvy3xUjT8foeH1/l7ruv7OxTL36/wc/31t8zf9Gj/vjxXqFv71cAFu6stK4S8CH0DHd/bB1N8/AlPx/SJg6+/F+XERQk/xS1Vff0tAV/6zCOWqCVS+X3A3vOhTyFUD6Hx3dX/95QLwUE9/q92mAbLTIu8fMwOnUPubvIYRKFwVcLFPn9yn8c/ue/6uj+408fkdAAvQ+8b51ywZ4Tv6vDBH3/XD/MOzvuRXx0bh++enx18vX/T5+2sDcf0p8pmStYfzA2MKfX7NKfp5ezg9MZjSr/ElH1hf9v2TqlcMkOuZr/z+0dt+dnWwBlbo63jsk2uTQX7a+WxzmS/5/tktP2m4/AIW+9/PZyNFJYN6+8XLEsbPx4P3lXz8mFbIkHS0/P2/bn4YAHzeXbFn6l+fkyM72tw/O04vyDnf7/jkl2Fh79PrH79wcNIAQAAA" + - id: "year_of_the_pig" + name: "Year of the Pig" + material: CARROT_ON_A_STICK + currency: TOKEN + cost: 5000 + rarity: COMMON + item: "H4sIAAAAAAAA/+2ZUXIjIQxEz6DrcvqtxAN0S8JIgJ3aKvThjD3QryUQ4yQiN27cuHHjxo3/JYqKP0R/1cSA9R0LM8RnLYTEP+YgrvsJBznN0w7yekcdWC3Y7qOdf8yAEvp5Wzx+8UaexldQv1XaG7P3TxggjZ6otHxLe9NuHzRgkn8SHfDNxtszgFpVm1ntBTyV38GOxBa+5ypUa1gTwZrsG1AqfYMXn8/3tg0Y/JtmF7pVjhhQeM4ageoD2AZWaQn/UhRY2eJEHSjP4OJr5fE1HS9xa6Gnv1MBW/xa0jEdBsjmEsBU3FQzuh3pCObSR2oEr4cvFYDx0dp3A7gGKwZM+hJNvmcu6wVQrZdKXg/3VSf4Alc9o5yB5yeL5dJvCml8awOsQZDfJnSlPJ6npQpAw+vsFT6cBJkCIH+1+n0WPgpCfKy+gNCqATyIIwaIDy6qZuYYAI0ov/Qxz2QiCtuZF8AqRtN3H/ZwJIQMQBaxAji7f4ffXpP8BlO/bBm+9OGega4Q44PRengiyn6zwamDAgjMmBngs8rwoZtJSJ+YQvzEAvDZz6v/gLjyxO/9auZr/Rnfee6RMTIA179sNMlj43z20QtQrAHthfKf6fu3tX+1rrqouha2/rEFsHzmFRXSTKmSWYEs/3llmnkeQIvx1mCHWjjCt4e9y39yIz5ecv+n6h/jPxOYqfjp+kMVpvk3vyb5Ys/K9f3HFGWAid67XX74i8chvjISf+rq9hgIT/k6/yKxL+Je/gf6b52/1n9YhVch5+gBf6n+RixoQLz6l2U+N2DAg3M6x/nObVabOtDpT/VH91258u4Y8vnsI8z35apUFL/8/aslOjFAU4vzbAKhHP9pvgG/pcUfuOlj/8/4QmpORsoA841ZUIjheQFczWItDvH942D6VCiQ9gwI5TbolZpInF/ocnDuyesbF3eXHUTJ02WgAK1+Dj8UqBFMX/FLV1jAqy0S49MO/IO/P3kdsGKA1jDHhxV4Cazx9eFbYnz1DFhcAd5AifTRZ1NIG8Dz0ciGCyBYwRxePfcS6dPQJ5XRMfQme3v2hPGK31s4lbxQ9VN8W4CWViz5frGEV2d2E40Y4JGOYLIAWMv5GtjxK+lrA62XoSIDem9a2cGbJvz2/5+9JeC/qnmJ08A9vBRlgLafO5xHuUJbBqD6piXNvW28MdBOI/H59XNn4gkDtA36ZmxbDhf+DF7U1imW1QqOD4nR/DUDzsNwyFd7czN5R6OvtWD9pe+J4dQzBnDzc0sWb+SRsEIefzppy0BSLD/jpN5pek7zE/SqOxUODdpy8EZ9dv+YBUMZdcFHLZj4Anxk4ovoGzdu3Lhx48Zm/AOlFvCbAEAAAA==" + - id: "lantern" + name: "Lantern" + material: PLAYER_HEAD + texture: "70808284ba50ec088dcf6d9e5549e91f82585f1c28299c40593cc8aaf2db50" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aa27iMBQF4CUUm910BaNup/0R3dUPkNi+j2ODXxgJohGEkPo7vtcJtJrf357t6+vv769rhL7t43/8Zf73N123bdvez3d6W4o/NcJFupZd0OHAM/CA7Q9xJ0SarbsDOh7ZbqjJVF3y7niUAaYkcIh34UkFGJ7AaZ6c97t/fSYTYGwCxd/m62/w7dnHdswJkOGZPzOA0/yt68L3bCWwO8MsXviyACKAH8D7Ip86MSmA5fdKMz8G2Hd5AN8bwHvLZ/10MYwKAPhjoQWS0ou0GEcFgDybPvNFAdj5vidA8PmSesDnAXr8PK/82IChAY5B5S1Fg8bX0ZoD+DR9w2d8py+HUKrR09e+eHtMBzwiwPc+8NoujoYAoqR6+jlfNMD1+GqMKt+p7C0BYIMBl4T8+Q1+bvri6heAuupEveoD4PXNZ8vf9/wICFzt43I6oPEjvuRXBTDDN/qtBbDD56pt/QENABcwbD/wbQFcfQAwu6IPGqDq0ehLrsLXP1Tl2x81tzP92XTPrwqQLb9eftgn5VcX4HE//NZj74DodbXvBvhsmMd9w5n2Kx8uOD1Oe/lfwSe7/DN+dtlU+m6IX74DnO02zwcY9sGN9K391fV/T3/49T/QL93/Ov1zZr6lz5/MWbP97Oe/8Sv4Owuw3q+cfsUCfMCvLz/0TUHAPbFw2/S1vocL4GEftf9h/04D8v6Y8ms/Dtbu102fNUAPphZg9vdvxjf4sACtfgOvC+DU5ZZfESpx4/TPeriwFX12Qjo/vV/jmwJI3yFfnBD5pumDAqjx7foHfPv0CysAAaY+vdO3BcALIvfXlu7pwwBwhnb66OKs5s8+dQB1HE0Y/rnKN/q6AKYcklBg9/RTAXAAfXsrnNfo6w4U/WIx2vhyB3g0fXxE9UEAr8ywz08ayusloCG7O675JgBoQPLt9Ifweg2ae4Des/3q4+1t6K4/lhcByASwO/JTp5/PBQg7+sBwvhyAMnzvlQcTEG839jk/Si8FoKfwIkAgKfrs2CQ+JuABmG/40bpMkAKQ5N3Oz9BjAhGAAD9LDwkCJeoQV+ZMPUQ4uJgidn46vm8Obk/CUYbn0mG7/tdrojX2lb/4tDAAbbTeXxeAVvvbap+Of2sCXMu/cAXG9r+nT3H5LfPpZfwFAZK/pgC39i/1d3uRTx+f+08PsNzfXsHfbt9AF/X/XyjAout/tX8JsNInegH/+ArWMc6pefvZTqftdPHbh/hsp//n0UxhAEAAAA==" + - id: "year_of_the_rat" + name: "Year of the Rat" + material: PLAYER_HEAD + texture: "7311cc56f9e5b51e451555b9a6d88653514c90dacb3acee99f56e3817baba25" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "year_of_the_ox" + name: "Year of the Ox" + material: BEEF + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "lion_dancer" + name: "Lion Dancer" + material: SADDLE + currency: TOKEN + cost: 5000 + rarity: COMMON + item: "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" + - id: "year_of_the_tiger" + name: "Year of the Tiger" + material: ORANGE_DYE + currency: TOKEN + cost: 5000 + rarity: COMMON + item: "H4sIAAAAAAAA/+2XXXL0OghE16Dtsvpb9Y0F3YAs8E/ui1XJZEYjcRoEyBnjG9/4xjd6Q9z4H9F/KWLN/gsNJ5j3FRTsvyghMXx8jLPPK8iMyr8f+/uegsWJr/jLHXfw+GnBJ+JjArwhxFG++Tg8owCM/N4iRvRF+Qh9QADiRwQQf8objwnggx8hxsS3r10aPIP/WXbRdf3meCtLG106NRgL8NTj804S3tU01G3okfA88Z08KNQrAmyT8jXWZhc5wp0PZF8Q4JIcfrN2p3xUO2BhV4BreHKX3xSQZpzVv8mi/Of6d3nXEeCO0OeBY3MNrrK1IyDnQ76lMXDpaHtluPkiXjuOz4b4xgUh45cF2DorN9fgdB2FlxXYRwmGa3jwgVw+DB94+pYTQcbwku7wOeJD3ae8sEWxVCt8f9Z2BOibM8v+a9RDq9gLoBUzf8TwkOXOXR4gudUFMr6ZH/C6GdMUx+Aqfxot4/GpqcHn70Nqd/jibJQEiBYYrjaTDbx7SijxJ2/4oCmfPlYEgCu+PRf5waOegDHI5BkfYsbP0GavE39Ele4h72Hk68u7/OMlnLY13JYA/+EcLwL8BN+OgJhHpwLC6oQ/uiFAi+cVAH6Tw8jHG7csgD1aChDhVSMwBvX/ogJ0p8SfhMBnfKJvJaDl/4Cl3ATipVtSkDm1wVPxaV46oxJFLQUUbsGEj/1u0N0zpXlZT/H1mYf9dBdx8XHkCn8oGJ8yET9YzLmAxLky/8hdAPFjAC5dBmCDSudIv3v0GM52i7+ALfg/5zUTYxlsFdT5Qn/gK22+sQXq+7UEb3fN175Dh+35jFeyFWXgg90qn42y/+T98XOYgZ5xgc97MOJQAqBswsyoEyn+8yl/QN+XsIr5gJ/KvUJiTrsdfnADE84mcXv2T8JDfME2BPnpWuV7/Dy5NFP1jJIlNT75mgrI+PNl3gtBezn/kvoPpjD8tk2zcyR7L9V/zudb1xIeDuFm/Q+L5SICnm8HgAfht5j50/zDmQafQ5Tk/zmsLcDFf37CntjCP8CHTa/ywclB/k4zsf2w8T1/bloJGJR25na+0xK/yJ/lcqKAT9kqZ9Eg93yc3fN9m8ET2/FzfJMvrlHY8rAN1235fmVBgiUfRgHXNP7/FFtc4LPjCz4sPePHy6smIAaAtpFLcoIfyeIa3+FYeIj7ko/1XEzBNABUg/5IT/CAbvLdAwbO4HFU+W55SYDtmu3RxaTgv5UAd4tGCMa8l1xOqs0z/C1+cgZtvpYAFkpdgC1GvFhf2+Gtdgb07LIAsbtYW2it92ff2762gHk3B/4On/M7An78hZ0rfKn34Z8AMyPh7t3yMW5qsNGIUAY2hSrerREMQxMPmxv4Fb8nwG9u8HXVYehCGbB401PC0zXkDLbwsLnQ+aIAn7tFBWwpdNN7/K0Cb+kSn1p2qN0tHY+g2vhTAUobw/xYSgAmVEww2BRg1tSdRAPu8juu4DVskR8yAvbQgXMgmng7tzV/KvQF7/mX8NZ/XMAtpoaBmZCIWVk0FPAEziV8LpjcxmUB3npa9pJuuj7I3WBNj9mvF7/7voC0HUc+lt0DeMsfq3+Ktj8RTvv7eDOk1pMGpHJs3VN0JSED38UZ3vGcgiOqcy7w4d56lM4KdCby84XPKqDnG/iTLnlLQiScfPWSgsV4k77T8D57KeIP0d/4xje+8cj4D/jKaWcAQAAA" + - id: "year_of_the_rabbit" + name: "Year of the Rabbit" + material: RABBIT_HIDE + currency: TOKEN + cost: 5000 + rarity: COMMON + item: "H4sIAAAAAAAA/+2YW3LlIAxE18B2tfqpSgzq1gMQtjM/pia51zbotIQknGntG9/4xjdqQ8z4j+i/FJGz/0LDBPO+gg37L0oIDF+X/u7zCiKj8vNPP99TkOx4xk9X3MHjVcIn4mMCrCHEUb7ZODyjAIz8fkWMjF+Dj9AHBCC+eQDxu7z2mADe+OZiTHx9bNLgGfyvZRNd02+ur5LaqNKpwWiAux6bdxLwTtNwLEOPhO8T38iDQj0RoIsGf8Ra7SJHuPOB7AMBJsnhJ2p3g49qG0ysCjANT+7yiwLCjNP6V1mU/1z/Ju8qAswW2jwwbK7BLFsrAmI+5Fs2DIfa0T6ffaEGM6W7NBcbtBq+byGHYDWM0Obit40HH4KUWykQ7QiJ6Sp/E0/tUSaml3i1JwX6pSBqFWsBNKPnj1TxRnJBQMTHUFQEQBju8st4fGsq8Pl5NfEjASYHFgKumPVZsux4SwElfuc1G7RzAeCKbc+bfOdRMQKNTM74EDN+h+7mLqMHArbOIeuh4Tf35S3+9QvOv5+rOj/2Z44XAX5uZ1OEerI8h93smG8//UXGn1cA+D0WcxztMUgzcwHsUSpAhGdZVhTzEQtJswJFbvG7KYNLdlwXTHag4n+DqYkfXgCqDvngVMKnu5x8i0Ogjc4kYSKA6wFqzo+33QkY/GgjDvj9nWe3yIcAjfQ9fr+zx5cpX0Lntvjbhw31pGADFqjwHpos8YMN2IHF/D0FjT6P+QIfZGA7ABGf+tmcP05qY2OtoLnf+AzsHvHT/hsG4Jzv7LGEtYCET35M8+/SOTttYvzkKCS7d/iTYwhr8EV+pqClF0/zQwW24g/5Ex/mChZ8q+Wg/lYKZgKeqP8Fwtw65cPHih/MgDPDz1Tze+fPkj8TYLv3CvaUgPDJDv6IvyngPX4uwB3fJb5gLh0JMHztPTv8Xi4FAdy6qHzbFh/vVviZgJwf44/5wauX548nK76dWREw1jWDL/z9KTp5m69vv63RtbmY81ufgfOrAvz7F7kkE3wLJu/yIQesABf3lD+qnsVWBDT46Xjz/085HtB1vvrt+A2/7/DN9CIfXkWpotf+awlwt9gX0DrU4OmtMsXf45PfZ/xRAlgoBQEhXgOyxOu516Bn7wsIvd/p/dFzXXcLT/wVPuafCQjsnPCl0ocZL+7sXfJhhhqqNSLFm1aygzdzBMNQxMPiAj7j1wTYxQX+mHUZOigDFq96tvB0DBmDJTy+lFTwpg2LebJLhxDMXzsq/KUCa+mITy3b1e6Sjluw2/hDAYPWmvqRSgAmVIwzWBSg1oY7gQZcZVec4EfYPN9lBKyhDedAFPG6bzm/K7QFb/lHeO0/JuAaU8XAHZeIUVkUFPANvBfwuWBiG8cCrPWw7CVcdD7IXWdtbLOdL3b1fQFhO/Z8LLsH8Jo/Wv8UbbsjnPb38WpoWA8a0JCj856iDxIy8Ju/wyueU3BFtd9zfDi3HqWzgnHH8+OJzyqg9xv4CKe8JcETJo9eUpCMN+krDe+zUxF/iP7GN77xjUfGP36gDZUAQAAA" + - id: "year_of_the_dragon" + name: "Year of the Dragon" + material: ENDER_EYE + currency: TOKEN + cost: 5000 + rarity: COMMON + item: "H4sIAAAAAAAA/+2YUZbjOghE16Dtsvp3zsSCqgJk2XH6/dgz04kVxC0Q4PSM8V7v9V7vde0yuf5H9F+K6Nl/oWGB+b2CDf8/lFA4Pm7z6vMKKqf272+8/k5Bc+Idv93xDR7vGj4RHxOgjhBH9aZ5eEYBOPm8RYz5D+cj9AEBiB8ZQPwpbzwmgA9+pBwTPz6WMngG//Es2ZV5c7y11sdVOg2YSPDUo3VnBe9uGfo2jMh4nfgiDxr1joDY5HzPdfhFjvHkA9k3BEiRw79q3Dkf1Q4wvCpABp59y78ooKy46P/jNv7ALj6tOqJt/MBw8UBrAWLF7XBBQM2HeosjKQRQ5YScfT5XvnEieeqIACHwONwVwOPMNAUnAnQ8jpS/bTzEEOW4FGBcLja4CrcE9PyMxxJ0LVNsbtUdfnXWONv6+M2iRWv+hgDuWS/BDq9aDj0i+YKAio+p6PHR9OaKh+bgLr/KvK6GpXxrusDnz5vCrxVhovjp2Uynno8QZZXJELxB213iT97QpAWlhAt+FgYC9X6ff0YPY4fnX8HcasWHnKU5GlGloEXWGGGZ+SsBmCvTG8WnrVWabvKPH1RsZbOXCoYK0Js13gz4u3j9kMREREsByRpHKOM1u1lbxV93AMSdqJlg7SWaNKJWgBlbgZN60Dd46Rw6ix3+5J3gG/5IxxLBbPEHmFb8FV6dBx+Cavi8Eetgkf3sI/OxBAvURT5H1pwBOB23+AO9F/wiLxbWHMctvkPK9K/wgyrwuC2CO+fTwxz5C7yWoJGcBb/T1Iy+Dn/oYyebsWazUZHKReLrt+59vtHLZzURlvwyi+q3548BLw2/XM18mFTqd5s/ivRXiyU/ZsU+H9O8w4cR1yaAfSz5w3XOwVF97YIuoIeM8CGH6Pcqv+z/hK0EfMufwzsdr740AsjsHh+8Mt/8414AHfYWH0GhqODT75iDPlEBcVp0gDUf+kR9wvaoQEm1CJjVc6v/a/78OAlgvuTpSv/PF4MbFjAbQ3IvYolP7veePx3fIAY5GLFOddLDOgGf4WnJ6xi67O3Dlvx9qMdX/HnQQzBlYxwnjstf8kfUjWCquoQuRwHeBJf49imz+R+bZZgl33fHUR0Vq95XfG8XTDQ1XFGY6Graerec83HV+7TIdJhUk/H4DAog82t8wdcBrxwVFtro/AcMlFM+W1L8Bd8n7IQlPNZLP/2AH8b+84QPDXcsOV/6ccmfRU/uaNJsCEA7iw7G+Dt88MPY9bqeVQVYPO8ofo675ftIR7HsMO83vUgvn3uxPfNlU0r9MdFavvm3A69fOM8tvpjTmaZ5nunOx/8L2ok/WoCnBWUgPVFT+genn/kr/JJv2B+kQfhzhUfuFt8R2CgsoHqgRujwgsPzsDnFewdg28AJ+Gwpd6bm89CNAWcCdB8cbbyXfSPCFgvkn+Frvngm97KEs/cZPpzopFhzoZ5wdokPFuGJmBo1FJzKlFGygxebeApEcCIgxmFKhdTeFr7jBwJgy5O4yXerSL6Me3zX052POdvAx9wZ7n5h1uNh88bkKzwPDX5Af6UyVfphrtP0S/6weL7UvfAAn0Z27l2DPyxADP38L+LTFBgj4hAJwQemdutVPAU7vXk4SQJTdMcdfDRa4qeKgD0yrQYk4iI+zq3nT4Xa8Mq/hY/5I+M1choYWEmF2A+QLQW8QAMw87lhah+3Baj3su2t3HT/onCTNz9mtTfd/b2AahwWfGy7B/BRP9H/lG09ES777/HhyL1zP2C9g8LH6E5CBr7LK7zjOQVHVuda4vNXguforMBXMr82fFYBfb+Bl9LkVxKKX4D6j36koLl+ST/T8Ht2K+IP0e/1Xu/1Xo9c/wFdJbq9AEAAAA==" + - id: "year_of_the_snake" + name: "Year of the Snake" + material: GREEN_DYE + currency: TOKEN + cost: 5000 + rarity: COMMON + item: "H4sIAAAAAAAA/+2Xa5LjMAiEz6DrcvqtmokF3TR62Zn9Y9XuJJERX4MQSlp7xzve8Y69YTT+I/ovRdTsv9AwwHxfwYL/L0oQjj8f8+zzCpRT+/nnr99TUOx4xS9X3MHHTwUfiI8JYEcRB/XGeXhGQXDy+zZirP/p/Ah9QEDEtwwA/iWvPSYAN76lHAPfH1MZPIP/9UzZpX7zeWulj106NBhP8KWH684E77QM+7IYkeE88EleOKgnAnxR5/dcu9/IMex8QfaBACry8F+1u86Palsw3BVADc/u8jcFyIrz8++yoP7x/FPd7QigLeQ6IDaewapadwRofqg3iI0kYOW4nHU+xoKwRCcJOM1J28NfW4gpEJyUgzDVUv6W8SEGLjm5LBWCtcaS7vBH+CxAHNUVvt5rkykuBVStYi4ALK76sRU8C7AmanUqQPHJ93BxFBDScJe/hE9bQDEs8PG5KPzpcrakGpgH0ELTNOx4pC4Lsixgi3/xGidNVlIpKT4JoXB7XuTL1IudznwspTblh5zhd+hxomt+CKK7HAiIuTL5QXIaXhgP8D9/wv034edjWoZQ8w0qhLsumwK+5McWZICp+AbxZ75BVj74Nf74BIS40TfwuSO0Cd84olIA5N1NmU/4mH+Fh3CW+OYuMx45oVWW/BDMEr8F0xjn5SWWM6rT+BRUwYdZLj7VY7g2C/zqLTzmc4VhckbpP+Kn7zwiWuqMXK/3+OgMA79+hWV8IUEGt8OPLOs/q6Ig0+uiwjFfm6U4HB8LOn/NHfIL2ITfCB9a0iBze3wLL+zk57+4E8L9WwqIfof85j96d/DGSeDFwe8Rv7kfTmvHg4RDPhPpg8D7quJ7G/ka8ltzJ2o9tfyo5GOnfjEZ+N3nF3iD0b1Qp77P10pkozMt4Cl+rz+NRwEnfHb1uxjehQWlgMRnLTvnr79tTWhS/Bz/nfPfgtcZP9xJZ/zwEn1y0jW/W/D+LPdfmokxUfzqkuvKEn8KGwgo+GK9J5vSv4Bf4GP35fQSbjf8FT50gjGfJtD5nA/BCgHqcizx5oW/yL+Oywlf4Vf4cMyALyqg5md84mv8Er/3/4ov8NBQpny2RAB9987PNX7j96e5sbgC24VQCWiwRGRnzG+XRbQngvlaZhR0g5BsgG/CGLM46mnVhWgp7yW/n3oUK7KBF92Qz1s6wAe04uMFkDNR8vHWWOCTObv7NQypGAjorlfi9yOA3aL0eh3G0tTtel4H+GU+AEYCNvn9CMSDMhbgZ0+YxqD6ywDv914LPftYQA992vvVc183FaA3IPmZ4zV/QYAwFH5O+EadR/KF0O5six8sMLu78Tfo38t4srGYhh0+Lt7AV/yRAFjsM2f8buXJnxyDhEfxrmcJD9dQ2r4RnazDx4XOlwVw7UoF+SF6St30Hl93mIp+yoeWnc6uEgAf4/xq45cCuufWPA6WkLVchlQ6G/hg7956OEJDXMUrTvA9bZmfKiKsgQ3HRGzifd9q/qWQDzzzj/DefyjhnlPHhJlUiOpYbCjAiTgn+HhgtI9jAexdNgKTi84HhJu89W1me+PV9wXIdpz58dg9gPf68fMP2eYdwbK/j3dH3btoQF2O2z1F76TIiO/yDK54TsEnq9dc4od761E6Kugzma8Nn1UAl254kSbfkpAJg0dfUlCMb9JnGr7PLkX8Ifod73jHOx4Z/wAIEjwNAEAAAA==" + - id: "bed_shield" + name: "Bed Shield" + material: IRON_CHESTPLATE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/93ZuXIjLRAA4NibaFaRQ0wkF4GfYIoHck7A0+9wNzRHawakv362Vrau+bqhOST/YW9tH8f/r7c1G8L7eBtAvH1TAO/thf+Yr65d7fm35+OvjnZBP/HurOOVuhLAqXdX/HMRnHxv6e/7uQBUeO9lfz+RhlLxrdf9pyMI+i6v+zIFQLpYeKXRJb/uc5lHQGs2ec5n+Pz5CHaXPNdTfB0joMTgXmd1Pcnf9yOCvdI0apk+zz8ikCgCrGuHB13PGX+XlBkEUuNJn+mbCEgt9AWf7dc6PWPh0/7RyX453oWO+Ll+VxdCVHplot/UDS8F8NMT83w01Yrkj8KvPDHL7+ra6Me8rzwzye92/b4LszRJrM9af7pdfzSxB7/QuV7gB8MWnC0NaW9w8sfP6X7ChdsRTPGbW4mT19P9lLtd6v28kDYIrjE/4fwH/Uw/htwXphl6e9op9Rnnz2JDMbz0e3GY8dJQssZP7H8453wAyfenvVKf2P9ZbZuuTz539e9XnDQtJ/Y/L3jo27OZK4LjjgbJz/KR7qZ8XHJMHdo7KflwEpxy/i71XUffPu7qrxj5+X5MXkefex/UH9Rn+iB572s/5d3ZXNb4ab6GycclN0zHWAyFPmf+gykVd2K35ArXgh8mHTivkT6uDf1S97MtHvmdj5Kn+mrg513vlpzQ21GTFZ3qq5YPD6A6bUR2yhX5ygbPB42xkY+Sj1M+q3+sU3w29PPPNXHJsUceNzjS9z/ih779onPsl3pY8n1tFD549cBnJL9yANJuyc82wwo/8BnJ5xzp4cjhixD6WpN9RvU54v2Rw1cm8IG9D3xG8fEJxP0eyaz/YermHoln+TJQ83nJB1+Dw0jJ931W81XTz3Wu4ZKfHcYS3/VZ3VfIL7dgf8rIlhx3R+Z6b/PL/uCWHh34SS+WHP+1U8mTfPhY8PN/Ku6Bkc+n3A57J/K9vb+qOx//4QlMQR6Pl5mPRn6Q/ledr/c/mIKJb0x5sAN2P3pWde/f0AAwFU7hbr/X2ZJfw33vM1Lb4EQ4tBuO15eAKzW74oRzT0O3/N9Bu9u2ZX6l/kIH+Eo3N/brYPN7kx/7QS98drvVA/Bpx9kGK77QCXzSt6L/bzfM+wBs1aUvmut2OPbeh23bsG9rsRGAAiMv8dfxmf4Ej+qvXqbmombiSdHTyfy21X1WG/6wDiq79DpeAFSEH5rIb1vD/2Kt/H0XHICQItOtbB8qdH/9AR994fJv+26nNBGIaHr5+BQWP24hoKsH/7hC8BsDEDdqG4ER/T/hv/y2T5ZXL3n8fOCFn3+95PMIMp6C1/jN66Lb/yp07T1GoEVojdxHAx99MfKD7q5aRAB0FX4ZV31qMY2WH3PfIpFCKD7jdkZgxDf81PN31WuNy4cAhnrdB3pKowK2Y+jpGV/xsW47oX6tymv7PZ/r2C91ZzSuFQfoFP+LfZR7rmE8dM8J/Rf7ld5E1r28T8+94JFv9NEBjtJoetWfwTd8UHO/b/BhxauX+9mEe71f8C/2c/3z1X7Bv9gXJQ99ZfmVPtKh7/l1Pk7e+amxlX5R9p/YZwv9avJ5AGyh3+R9A0eOBf5joEN+gf94kJNf4D8eySfwTf/xRPtO7ZH8cd/nfnmViz4l+YU+kW/638RW96n6df+75tP5Jf4T/CqfqL/Kb/Iv8dv6S/wez35avisjUuv7Xb7pPyb5fX25P+IHPprFuPX8ob7WJ/ArfQq/zifp63wiv8qn8uznp+XT+IqvpvhEHvnqKb7pU/nPfAFST/LAzwIg85/ZHwqe1aN/4SpX9ORfuMxZ/Wb2/uizs/zZdjON3X7Gr1zqd/7+9v/23fi/0XdBfJhu+HlHswPw8Q9PhNTLAEAAAA==" + - id: "gg_wp" + name: "GG WP" + material: WRITTEN_BOOK + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "sorry" + name: "Sorry" + material: PLAYER_HEAD + texture: "f720df911c052377065408db78a25c678f791eb944c063935ae86dbe51c71b" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3ZQW7DIBAF0HW6QbnBJBfIDbyq2JerVGJRyc3VazBgMIONXXumVfhSq4bEfsNA7Ch9A9Zchp8bW2wJfLwtIPxmKoC3C82/sa8/Z5rf/OY3/8V9rfl8HXyGKuL+a01fAIBDtfOJS7C+J7UmXwPL22nzbEHnuyrGDvD59F1I/KgRdD6dReYrxeorVV/Agb5yIZ+/5dSU2TMkvopzq2/EQf1XWGoOPNO3BaxU4X30MnRuIp9BdwVMviRN4o/6nS7ybitI/Ps7WaQpIPGlNMOEsQ2Iffo0/+Y+/ze/+TK6MPvn0xG9NjAdG52l1l8+u64ZQH381rPiV3H4QEA9/4XEvfoMX8+mj/FjAbkfFiY5CTq74sBsI+D8UECVPy1h1QDyxB4/PedWX1e0/yxfBt+fpMKHrX5x/bf64P7zUu/n2z0eiIY2zP9IXyYPKnxhFmD+/ifzB1ssXX/LvsQG0r3g/U+bkQ1/o/svmx26/7IOpeIG30xfuP6jd7ND/O++77993/0D338h3PyzjVf0y4Vs9e37z8+fwbf7D2Crv3D9W/LtuqfzBxCwvf/7/HHjZf0nm//n9Zr5YPY/kX8dgvrT9S87u47PuMvv8P3XTe8/N3+dRBYGtvsd5ndd1v+T/KGA/vl89p2Le6CJfFMA4rvDk/030/KBXf5sGun58P1PleY3/6/4pN/9jXn/Uz7tt5/269bY13Rf/vroxKeuwJLex/8J+5vkFhII/uEVVPgj6/089iX+dTYfhaSH+P0c+yXjf/mlAhBfH+RDOFSpdd+/+kA/pOzjxx7t28zlkg8n+bA28ejg0/1xxKzLSgHomfb5kPDmV8GfFbDDB/ygaPLLaxAVUG7Akr8cteZDdB0uFrDfh1U/LeAEH5b5uIJSA37nryfcDJn8+MbO408lsPkLeXn/QekjnwJJfaQGcn9WAYMP7t3I5kd1AJOvwV2PuObvl+BV/dD/B5Pv0vzmM0WYez+fL0xAcPts9x9uf1x/5s9/IC6mDQ+O2AW4/ADgop9gAEAAAA==" + - id: "enderman" + name: "Enderman" + material: ENDERMAN_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "golem_riding" + name: "Golem Riding" + material: IRON_GOLEM_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "leaping_potion" + name: "Leaping Potion" + material: POTION + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/9XbOXLrOBAG4NhKdAVaqQJfwKWANQeYwk2sAEEXBV99gG7sxE5SHLef/Sy5rO9HA1xEyf9Op9aH/Pw8rTDCeTwGsF9PCnBuF/6yP8/7+IPzP88YYFuIDY3X/rYa9Gnks06xIcYW3+hmIkZijPd/Duut/qx5AD/ASI2Of7Y+YzPn7/bdsJks9FUAzvn7fMDuK1/+x5F+jw+uMAAnXtr0ebCPLACjwkng2lf1Jl/NeqJ6H6zfp8Yr6+FqOMGgH+BhBHZw/zO8DcC6Hq3X192X3Pe3o+n7N/jwf/Algp4XAG++yef8dvuObOzB7UYBehL0+4qX/ncQAW/fKMDR/u0mxHeqhOgP0L3+GX9J//V6Rbi8R/qvo/1P6b9uql5h6fve4stalltYy4L3Hzz/6mRD+6siXx0TT/WPPP6yP+BDzwPu7/MjfZx/XvAlf6SPZ32ZAIY/1gc68Vte61o48gf6QL4MsCy/cS3LAD/ms4zfzw/4UPI79SFfHYPP8W0ALkQcYBHieN+e/0o/aIG89RZ/phVAfljSV/vevtPPPp+edBf8rkPvkE8JzvRVgtN8+dSbzeX+92Xo9/GKxym+veTEMz4c2X/vWmPOZ50nn63+PHu8HKS3/kTgc3NFaHff8aCO/7n9D5grUvhre/mfbvjy6Sdkfa5WAO+6Jt3gu8vss2p90VfPfrquSUu/8oEPNNlrrXTpq+Bz7gWoPnp9/LaTM555IF/w5c9n24Nqb5v7j/seXPo1H2Z7WbRhBVzrEyA/zHFHX3gs+bgEjE+/WXzsa3383nGPswafq1WCV6frL1I1Dz/wRdK3AYDrZuHvlod/bQhAxx375EOkeAygE3gX6GuPff2nafzkc2BZ3U8ALgJug4XtcGqZALf80q2PJyHwaxPQ8CYFdc7RxOsAXv9pM8hXy/Tb8846bwNwWi3aL/S/Yfy0223jgw7IX8M9QWn8dZ9pv42PpgD3RWW/1n56nSnkIVGrAMy8SFXa/hrHzxxvhhWXC2E7YH60vf+M+KQN3r2UQeCTQdD3lAK0+Xq/Uxi3/yMAtwS2+szrfgr3fS+FH6A4AWXfEgXe9j9oA84A28UH6n6WD3LYG2EDtvql4aeLliDugTb6NPvPZxf/fGIDdvKF8nsCPJUveH0Btvig/fYAz5WfC1DZ/oLxy7o04tbH/IUALds/TT/5slpwCkCnwsUGNPki8KmKdNSAYT9u//Nyv+TrsbfPEr6srP94xP6m/rOEf1EduKsP/Q+/x7vujzDAHr46icj4/gd+oVeic37GqPu58WvZJjAvhaf9nNHQf4jm3/gX/6sdvwtg/bzQsP4AYLX90ahj3/RgPf4NPqT8cu3nT7QAz/OnyTzvSPp3XTmf7+DjFSd3/An94L/I95b/X/bDBdjR/6bpr5//2yeeqfV3Twz/4nhe0xt9KPtRC5wPUHnwxv67BjwS83+PeuCG3xCgafsjfx3gnviOzgLETj6Y8ScDZH3i2WbfPLXntAQogEtwd2Xwh+N3GL8ePPo2gEwQLgNL62OPdyGQ7+Sbq55mP7x691143Ke55/Xl3zj/6wDPn7giXvnTxGsNaPC5S2ADrHSbwDVf2vilWF9N+994CpI8BvD5Pfwp9DGAyPA/PyLgoaH/VV8VzaYXIJ1ARDxU9UZflQ2QSxDpatvf1ed2S/gVIspg7vi1NkB92+/yJzoOAMxcveFDrEvdbV8AacK7fJoCfPVZv+kksh3fsO5GfPfy9+rNP4bH+Wl/xD6/FoDmvUeX/teAr/7eIqF3DXyTT3/xEeIjepc/BwHsH52YJTdWXePXOeIatQf8OW7CCX4cYMKp6a+rOvZ3998PQN+O2MTLANf++Z90gkm3Y5vfs/9JxDjX31Q4/yf6FOJDteHrjMIJ+PgPtbeFlwBAAAA=" + - id: "sir_von_mewrtimer" + name: "Sir von Mewrtimer" + material: PLAYER_HEAD + texture: "d0dba942c06b77a2828e3f66a1faec5e8643e9ea61a81a4523279739ed82d" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/9XaWXLrIBAF0L2wJHbi0gdVXn1sDUB33x4AKanw8Z7tSH0ug5CcSkqPtXek/TH/nB/j/6dfyl/7foKnfS+AThbg9/Xc0uVs+gGW/zlR+KSc27fiBVj27QTFCVA8v/i+FaAUO8H+sekX4Ivylp+zftT5qcW3AHzYUmR6v74e4PzU5GuAbsiErwWgPj+qflzJneV+aX4ha76fXZzg8LUBaOdWsq25vjbvP/K19ZXVAORkNuNs7Nn89wVa9UG/hBr0++nPVoDLBwFivLj+UP/1ANWXR9zqawGEry7BGd/s31Xd9GOy7osAqm8tQSXGjC+vMMOv78//D/T6J+JLoB9V3+cv0r4ZnxuA7xcE0JYNH7b39dgT9Z0A+g5ws6/xxbwH/Ipv3QT7cqf/nvAtnTbm0XJd/3kz/ThPtmBZrC37gf4P6PzpjdUiM/Ab/rHv0CyD/mBTT+4Kf7WHfT3Y6fMAd/u1wvGu0E1YzsPd439VqGmETxPc5bOLDpRtfp8g7Lu5SImA37+P8O64SF/dlQ1frz3uqy3iE3HQV9RRXwkzGyAy/6xce90TswPA+o8aq1dfcuAhn1cE9Vmy6QARX1aXQzPlK83i23p4H++e8pU0jX8XJUAc0rc+mYf6x7a9OgCq38OJ70Cpe4571G/luH8keGgB9Dwf4+sH7/0Z9nFfdLIlk2Nzuw8muR6C/frTW3zQfxagvew/TsqtNzg+rRi4yHBRNAqa7iZAs6yfKnRcfWCJiFmmp0u++MUDh0i/e4TXzuV1ce3QQaRL5vmmri2RsA9+jB2tRXjdlz8f01d8eEAQVEvHQtLdwcKsEPLePbRIIt0NPR2N+6QH2hkuX16flsj2G+PN48+xCYzP63UGcHwDB2fttN3vnnf9eM/bCQO87dsDP361S97yVb0O/To/6buzYLSt5+d8fHzU37bG618envK3rQtQrO0n4o9H2LoAghkMMHMNdL5U2LERfzDAa7sCIGXGDwTYxV3/tvpuPQA+C/sf84V94w50j1++411X3XZ7gOJdCIdNAmjOTIBiLoTW5+3k0VErAVS/7nOX/+049hs0E6CL8YLt9EvAn1yEtn9OutV/dQCC+8A1DbpfbF/+yiAYgPowQDnYI4Tnj+5DzBcBjiIBfzZAPUc7/2rywlcgNVjQVwK4/tJVGPEdXg0AvCwD0DRTLT4AwuejsRRA8/c/M6gvH/C1L5e9n5tfQ7AhmveVLxfEP9DPvy1NoQFmHk6ZD3+XVf+SJ3dvsT8boHVnxBfzv3YNCL9wPz/qy1Uk/BYA+GnlCzIMIP0rAOKvMZz2xWUAfHsLGvCBJfaBQf/4chTzje2ef5iHBiDxNRzSb/NZAXxN4M8GfDsLKxzi8ZMM8rO4IPn4OxPg/drP8+F81HuSNQBJGZAlH+1Jmg/22HU/h/1i7Q/rvhIg6KPHoJif5T2BFiEBHvH5PYEWnvVT3L+OXPblJ76fb/HB1jHtGwvQ8tGAhHwyDY4ffkCI+3QYZi9AzA/4wQ0g+oSw4NNCLErITzO+t/zsOxDmh/wseeT7ARZ8UUlmcQOked/Q21jYAVKa9rP99BXqf7rPh89Cco4MfdFH/EDf7/XVqw+orf0AMrRb7wBAAAA=" + - id: "defenestration" + name: "Defenestration" + material: PINK_STAINED_GLASS + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3YS3LjIBQF0KkKb0Ip9zq8CE086fIe6AlVHoitN78HPHgg64OUpLiDdqy4fS4IZDnT1NPT09PT09PT09PT09PzffMV53yxksvgVmVGyEU1vo0f58QKpL+qy12loV8rc4f8cP/Pn7fN5y3uKEf5Kg9I2b9naeHbUBPT0n/Q/jvu8Tv9VE50+6ydXx83WpQn+O+T/YXTvuBv53+I/zjTp9wT/HTKqR1Z2H+/wTcisyn4xevPMb6W7UHX4UQfhg6HzZMA+2XZymcQ0M0/2VYsfP628tn5fqjhTsG7qS98Yjz4fi808QVOOgl5gUP8wUWQiekhLXCAPwxX+5zX/LiBehG+Hu73+bIvYn9AV6Ldtz9g1/hQwPvsIJ8rn1P+fIrPOSd1Mc+oggKF43GBff5gx35TSfnZdogCpwnmYrev34xTuuZnVyLjcYHNy9+wtxs5ej/+OTk8ohJ7/JsP4csw/3MbP4g3YvhSSAn+7Caf2V+5v3OYBo/H19dWX4jX6wUF0tmXugA6B+6kjyL5e8tWX75MjJ8NXuFSV1D0bFci+HoS8N98tvmy7EvwdQHYCQf7Enxd4Zbwzn+/oYCdf9fArEKXsi+WeG7HrgvQvv50k2YVCoEKsDFP7otKA33NVb7dfYkv4/Hr+GuA++ydqD8QUn6lATcTz3m67IF359/Gz4Aeu/3/y/5k7+S2+AlvDmzxTYPy/JvkBUTGe194PytAr/zqIpiKvj/1tgmPfTcHjLkBID8Vqj49dAFr3/BmowR/MN8DbHic8a7/pYglnayhCpjh80nzoYBe/+HjB53IdTzSiArh3PNtPrx1za+eClh6qR/dfZTePMxt7RXF6YgbCIE2SnzrU2qwREe+CM/iwHjtxosLYF5dGNVFhOIXdH9pEpSf7spV/kf6lKyPnCv5Sg2XZcL/lDcvJcYOWuGI480tScn/kCdGnpzs3Ofqs9/iEOWjFqt8dA7wVs5K2cfE13Ph/Fd4S2KSd/ui6EvkJwUQQPv+Gc3DAfvA7N1gxJvHyM/OaH389rHg4wORj7aA/emF3vYzHwrg13gfnRBunjM78L/J/YHMrkKoSr1B+vvcd6+MfBP4uT7C2m+XfFfC8+v9DckWYHQYvgvZNPRhBQZ/Aj9eXC38ZCOgwyzZXK19NfyrfHz2wWcs9w8vYCwR7T1/9F/is8x/Pg+qQG3cZAKIG7CnySE+eeVIfJo/pgJZoO4rd7yPhzUgEwpk0295X6BRBZgCavRP/T0w+G0qmAL52rOe+iqKHp/r7gc/bpCvPSGiYft5WHk/usuPGsA6yD5d28WtyjABo+FP88N9l5+FU/m4w1U8qnANP8U3wJfwU/rN5qoKV/I9PT3fMf8Boy77tQBAAAA=" + - id: "boo" + name: "Boo!" + material: PLAYER_HEAD + texture: "68d2183640218ab330ac56d2aab7e29a9790a545f691619e38578ea4a69ae0b6" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "perfect_sword_throw" + name: "Perfect Sword Throw" + material: IRON_SWORD + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3XPY/iMBAG4JIuNZSRUIRElDr0SNtESoO0fyPi/xdnOx/Ynhnb40wurJS5Y7kNwc/rsRO4n5+jjjrqqKOOOuqoo47ar55j7asLJuAM93RLUE8a7umXpE6N9zkO+JUBkPGQAZfj2OlrAqDjwQHx09b7qSOG/fwAO/vJI0b8SICq2tWvmgYPkD7i3/Z1MXlvyJgfyYB3QNgPpUADbOITOXSAyluITX1vEOU35lGljinif0rN3LQgeUhx3/CMdwj7ii9LVgDRqtTsyx0DaH/PAHrt9wxg2H2X4AiwXYDTafqbGuChqlUl5o+VcOoY4DGVUAKGrwMsvFQPbD+2Fo/qw0sFcP1wLx5u7eK/XjL+3Gie/1K1RFjpnxzfrqj/MhHW+0T9AV+m/6ee4y/bb+H5/sn8mf2+RwME/LXXv7vXv9jXP+cH7bMDMHyvGw+/2pwA2T7gmR3ox5rZPuT3zvHxjZjPCeD7sfJ8lOcswSa+1QBiGN93gH68Ae3mOwusn+cH5bcCvpoy4Tu/b+fjAPjdrZBP0F/n1/Wuft009Rf5fv0Hv77f6TO38e2q77dbIECwJPy+zw8g4+cHAH6b5ZsAta69/PtNXQfqSmAGkPJVgKbOaICYr+8CZXHl6fl+55e6CxRlUVzBC3hJ+3r6RakakBpgSiHn19erCcDxu07Q764FZwUsvxXw67rrTAN4AaR8U9MKcAJ8/Bb4Hdd3ArxVrfR1sfxlC2j8/ZsQIOoTGajxpgCzH02Q5CMZSH9cAa2biiXQXov78OQE3zSgHOdu5o8FsA5N/9Wz/Jbk7QykP6gAb9d3AyDHLhpd/BY2H0ag/aX1hjdPg2cD//LpQpw3CWh/GJa9N+pvdcS1/QAXXeeZPp/PYV0HCPnD7I8tmBLZpU8C/hTgkuLTNQzDDE6T9/nxDMQ/n+d/rPYH24L29r5hPX1wanN/8HgngfOeDf3Y0m/s+xsfbH3UX8F3QRy//JcA03OiRNyJE300B6NCn0UMPjdE5NOY6YMdwfTRRVgGF/YNF/k+5N0CJf2Ri3whs6cPdiPcoIhPdRb5LgjP86YP9qN/kwQ+PTPKd05DfWfCQT80dKqPSmQHYoL/cvgrOTV9Zw06wo/Orsf2P+17Hwl2gg7xU9qLn4b5y8hEAFhC/tvz8QTpfMJlgPqdczTeAQkfaT+VIJ33AmT5IEDwvsP0IQJvLO4mgC+H+NhtKMl3WgBfX+Gjk8Q+14ZAPhn/gyB8sD/5PipRRfYn27cPpycAh3N992iijxxO9/8B2OrzxwBAAAA=" + - id: "faboolous" + name: "FaBOOlous" + material: PLAYER_HEAD + texture: "68d2183640218ab330ac56d2aab7e29a9790a545f691619e38578ea4a69ae0b6" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "found_u" + name: "Found U" + material: PLAYER_HEAD + texture: "b18be27ffdfb918252bc5b62dfcb0baf146b656362048b73b8bcf4fb5aa47" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "snowball_fight" + name: "Snowball Fight" + material: SNOWBALL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "merry_base" + name: "Merry Base" + material: SNOW_BLOCK + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "surprise_snowball" + name: "Surprise Snowball" + material: PLAYER_HEAD + texture: "bc2b9b9ae622bd68adff7180f8206ec4494abbfa130e94a584ec692e8984ab2" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/83bTXKjPBAG4Kt4K1h7ASswqdyAlS/ghStFylUp4+/yn/7VkhohcAtPV00iMx4/r1oyxp7k9XqrqqpivGpelSymyxxhzB2xtyr+l+Ibr/f4lyacXwG/Lu+/nL/WAOhXlH5mA8CtMj7egITPCPx4BwYNOMBPNgD4dQl/bQckfIr1xxoAA3jtgH5N5ec2ADwdaf30OYChfkXsLzaAHeAvNwAWFyt/AxD7KwF8v9L+TFFv+FTzxwPUqvSw8v2azDcL4LZgjRRsjPFZAR+zbQYGGkDnewGS9Wm/DnyS/W+eAuu6jWBOVETzf/lb7jeuIAC5n8TDCDoAH1D1f17D/QSl/DT/+zvZANqn6v/rlaHDANTzn7N4HmByAWj9LN4FUPufzs/kbYAP+i4AnZ/NW5/0/JvPC38q60/Tmm8CUPnR40/LGQr7hn88Hgl/0gtAza/q5h66AbT+5Phk9wv52ZMv4gMd5ydQjweh3/KCenLjmfuoBlDxbQMeOtn9hy4yv1W+CCCuLBP+Axat3zSnaZ6ZCZAqcXf5hdifE768Dxzzf9DQ+fzBTspv7exaZzZNGxWdPzeGN34IIX5D6M9cP6nRgh8eEX/UZTCJ74q1EPNgd0N2pJAvJmslOHPQBskPRfyZ1Y1e8L5pGrf24XAo6/eqxKhRpjqgxoOoMj5/zD4sYXoHDvajOsbnRoge7bsEw/AZX5vDB/z+z6Jq0B6w/jP0/6D/11q/P8pvW+v/fcbHbzj/SVz1Rp9++rWnLN/44PnvmP637Um83Ngvp7aN/Lqc3yJ+G/nl+p/nl5v/gPgDjf8t6+vr6w2/vsjaz4sAKZ8jgQ9fDS+X4r6cpvW9q4GS/iV6pnsXAuropZh/8X20HE/tq1215l+O9ju/rN73b/jY84/pBx66VF1kC2SyPf5zcfWfTDc47XeuM7t5PIDdYQX97+/lBTjA/wZlE/zoyvS7/f63V0o90DfwEybg/l1Wtt/t9C1vx4J9Pm/K7wv7kH/e5fCG+au85//YyvTVjbsIcOfyjfuq8n3zevQTVI5vNr2w74Il9NMJ/CcdByXP/XGr3y36qQTGdwGMP4oEI42fiCBXP/TFcBSVv/3X/KUQxv8C/nOP32f4SALf9wr31SeOizzm35cS8JvqjIcHcK8+9oLDffqK6+u+imDHub5M4H/qjODav3t4yHvlXnOQxfHf+gZ808T4Vv/u6ibOuhv8RvoR30cdv0f+HSt+6kF8eJkf8jwAcmUaThrFnKlPuOJrvPzCHxDffBCOXRqnPKPe7OBmes+H/0Ul/WGRP512+OoUY77fbvYQNn0YIOKVHwbI80EAd87H/Nq+1wt18X9EW3y32LrON7TpsP0wQMjj/pDV9vM55fq+CeDjQvd9/bZ4ncdOdGjVIAD3m4g3/gDKbG6zu6O2Z/t1DQMMA85fPF345mllp+zzWa0H7bcBIl75A+ZDM9jqe3wRoOsCHeUH1NzlM/8Hf61/gn7ID4uuedLl+vpnmoHfQVzykU7pV5HfdU7nV9xoUfkM9U0COdzhn8/JM14wfflLDYEPyqHgwIo/jtva734Ee/UKOMM/5/uV9Rmpv7X9/4DPaPzzBp9Fv/aTE2Dd37L62/0u7Yt3dFt8Ruifb/INZaYf/MoNha/46/7pRz7ynhj1R1fXa1YAj7dn4RjD/HHJ3um7s3CmP44L+Dbfmz7qIwugfJ2AiK/Mi8Db/jXP9/YefBFaXwDuX3UAT93iI5tvk38Np2wDZPkVOv1MvxP+NbChn8eHm48tbQCkAVa8XoMA2dOPZ7/B/x9xeZxSAEAAAA==" + - id: "angry_turkey" + name: "Angry Turkey" + material: COOKED_CHICKEN + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3ZO3KrMBQG4D7LcEXICqIq2GMKZpKO0RY8Q5UUzvavhV7nJSEBJs09jW2O0fcjYYyTz09ew6OEzcc0TO/rK7HTAQ0T7dGTms9o8KZpiXs9pcGag+8d0yDnwTC3Rj03eUPv1xjHuTE3B9AxyYwvNvR+DeN/2dMA1dyKe6GG1isao9gYRxvgC3fNS+/zhmPqGqPYcL4r2DEtPxxuaK1XNLxDDRsAhPiKrTgcKK2hU9xABwoMG4A1R+/T4bROOAuNkQcYQ5F18B0+nkZV0whTzfUYg3ToeJpVeSNl5IoPu76KwP/+f7/WP8c63j/TOtRneibBE3yRTwXY30/wiQBP8jtaVX7f9xt8ZrsEZX4faqWf4LuuwO9JjeMPru3+x8eH7FPblCHv9zt4MBFkVykV/d/fXyDbVxafi/uSbvz7Pfr2ScJX3tdODAn888iDAFm+j2oMIPuRj/5vh54CvsZXNoBSOV8Rv+uUCr5Sdv2BfxF8M7598Pz14asSH/LBVx1+BnnBv0ffRbhenfsDHpd9egb6Zxm/R8dd7WPe++D0L/H7Xin/WOcrye9UrI74F9F/rDV6LPWV5Ctc631Wy75e8C+7+pwv8S8V/h1chUr97v094O/vXYnPyvn3Owqw4Ptv/3dYnC/x+xJf4O0dAOGP8d2tVgcTdPjjd8n493gRYr68/irjo/oo8OOlF/o/UC/zzxKM+Bo/8/lL8GdJNqUv2/zv72/rf5vazUcBgG8QaM81Ot1Uta8xL/g98VmNkc/6Ar/k08+f7HO+wp8TxBPI+dcK/zvpL04/uvVG/qM2+KXLn/KvoZ7rM14THqW4Lvmrlp/7jA91iJ/m8368+mzyM3zW1/v4OX7BVzv4Wb7U16v9PJ/zhenHAXbg9/OHQfKX+C0+4SV/kWf+KPIlvjD/yzz3x8gDfxjy/iD4lBIvBNwfA4/8gfrTxPmPNJ+4DAt+/PuX4GvgTzdX5v96N1JcL/EfbwJjRP8WBO9P2M/y5r2FPhok55+jL/A3orsESz4ZBPsD9s+Az/ohwLTgs0GKfbanDzBFny8L9oUxgB8CRP+cOXxLGdY+iPMCfWkE4Cvkvz3K+yn+UWHeJ7hV8hMDUN8HmKY5gOdTfojAZwb5yb0T/ts8aPTTfKqgn3kb9EGAt+l0Ok0beJAg+6aEfzb+fPgLs18QoNR3C2CxB3+6beN9gr38NlRdgky3bRVfgAH4kW9R1STI6C0JgHzIt6wqEmR00R+Yz/nNAVrBV8TP8RsDtKIfFuCkgC/zbds023nsh2ugMse/wJsAKxOAMYh/M0c9+/7Kl+aNvyoBGgQHsOMp72d5FuDlpd5vlBBg9nPnHvRDgJdCHw+haID5mjj7S7zzX0KtOPzmlQZwvJB1H5+MkPXz/Lr5J/yrEOBU48eRd/SluZL9ODC7Cyvjy/z5UDkfSOkusNDnAdj0N76QP5Eq4W/wYJI+ydqAyviFxx9HSvh0+htcSb7Mb5hPAyz4jefxwIV+s+gHfpJ5m6BwubN+6/zXWr9Zzd8g7yZgmkR/yvjr7z3w8Tev9swRD98FeJbfwFMX8PbO015S0v7OAQbCD7f463pfHwbwCYwI/KHEL/y2L5oCK/rVj7+5cgGK7zeyAQBvKvzsiO9NBJhqbnmSAdziI5H95g0JYJDHtqq7LinBBHhnwuc4QSiwp5+ElSmQTirtk9o0Cwlc+KMD+ZYjCXbGBV+qLQGyeKHvQ1T7nAKvKv3ib35RZ9tuwgdwz5KnmM/Fc/Xs9if7y7GeOf9iCSfDH/J/45MNf8kfPAFcO9RPfB6P9Iu2Hcgf65dvPa7+2t+v/gHYw+jsAEAAAA==" + - id: "santa_slips" + name: "Santa Slips" + material: PLAYER_HEAD + texture: "14e424b1676feec3a3f8ebade9e7d6a6f71f7756a869f36f7df0fc182d436e" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "easter_creeper" + name: "Easter Creeper" + material: CREEPER_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aW3KrMAwG4K2kPJHJHtiByQxLyUMeGJVs/WCMQbYl2eZizkyjh7a5fr9sQ4Cm77/1rW99S6pKrIv50xNE+a9f3n+bKut3ujBf1u+6JcDbCVDG77o1gJGv9KvS/mutdQkUnP/X0v/L48v4XYcnoFr1a8b/7/nB/Jf1ne3PrTJ+5fJk/86tg3JVboBK8J1bRw1MMNz8+I8Rl5vHzUyGP42PjdIV8tETXf+oAFyY4LHuUr9y/O5SvzrL7wW/K+H3aX53mt9f7XMBivlrgqt8MkBJn1qGgU/sok4JcZ1vXOxXjl+CN/5PUKV8hh+rpN8GpX5+SvCmQl8pdfs7fts+9Qmhhuc//gdfXerfbqpYAMO2gV8qwPU+ouf1r/nLfYBy/tNck8P+p6D/fE9XB+YAaqrPp4i/tK8vjzj+MJT0x5+zb3gYxoLz58DxUfsAxj87APHpO9Vkfw7z9Whm+Y/HmOAz1l51LfIpz7Bmv64H2OoPZNHPJQNovq637ANoWvDHuiunntavc7sHnwSAFP+Op37UrV9n4Q62RogHuNsAc4jHI98HYPyECbjjAIbP9MEWDYPsKxRA5fuAKqTRnczrW8JP5wFoH4I/WB8HyPQBWB9S11+LA/h+k8Xj8cf3jB+wfIBJtQHMzi+1f8nHJfmm7fscAPvTw+IABD5YL9NfZkAte98t08/5cwDBtwFCXxoA3icHQPLnAHn9cwuA8ckA645PBzAfAAf470Qf7/lpP2sCdvjTDNTad9vfsAAIf4j7OkC9Fgn6b5LozxXxxwCE32AtzQ8XYKKviPab5cf0/u4xGeNzFfFbxYy+GQPzaeo+EvGrquJ9i6Lf5ghs/O3Y8xQAcUoiDsDNfN2A8Vuvd7UEaJXrz6XfwT8klnz7ZZdkX60HofgCBEoQHJGL/kv/8z3mK+SjAKRPFO/rk2rN5/j2BAgH2HoMMrXvbocE33r8kmC/H+6G8AupEz+chboE1TRhmJw9gPNCIkDEbw71iQDYF0dd8KUA7JuEi4Fq9Tzf3w9rfmuALbw9DLUBmiY9QNIA/I7Fv0VD17b+IZRNnaKzAX7DytCTccJ3zOgM7NWxH3QsrgBm3DP1OUBPDjnyIS1AitcR99FTHtsEsn3zXTJSj/UPSZtgjCb9YFPjfCGAVJ1XpE74w37fp0PfE47zSdr3MeD7Lp/j87TnO4AfgPDjASK067s6t+vL8F8pvPUHnweJT/NfKQk4/hA/IYCrrzz0DL8uzgQ/noBuXvAhz48FoJufzk3Z9u3cJPmRBDzfs3ymLybgeRuAbT/dFwJQuj01Jvh0/+VWxKf4nuE3+VyCUEcXBuT25QCBTweQ+DGA1H6uTyYQef+fkLDTJxJ4undV5nA/SLCH3+R7CTL4o3wnwR5eDCD5KAGrM/xB/pIgmc/0Y7xNsIvf508J/gF+Neo8AEAAAA==" + - id: "the_great_egg_hunt" + name: "The Great Egg Hunt" + material: PLAYER_HEAD + texture: "83c25a7a188196b18717264ffe837ca348cf719e827179edc4b78cbcb8c7dd8" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aXbKjKhAH8LXEh5SplFtwBaKlb9lG3saKZusXAfnqBho0yb115z8zNafmEH4NIiSeWRad9YtZHirLT/zl/+0vqP/JAhY/v/QvPD/0uV5V1Vd9a+CXRfCVKmH5SgFSFqlMHtUp/qyCfW8TVyibXFNpVE/vd9CXPaH+Pn43SdTojeu/V1hGnk+3Jd+AWzffj9iPWJozfXyE3/KjTp7vFxDz31n+ukJ/n6iIH77/5KJdKP48Px6vl++bhbhtIZnbhD1nIVYvhLa98vGHbwO5d+YUsOT421dWNVK1roO4xHsNH/DRQRvfbJh6EpJVkPxwjI9u3FXKd/hLlIr58JzQfV7Ivj7u83z0lHpI+yKPc5R+274++fJ9fMNUnVpZnUKsUS/ueW/F32oQH9ettwyRiceXjCphmsxWE17/IT7lL0jcXp7P6zW01aT5fN/vZpr8rSZDt9+ykXykI6TTnOiNmOBTB5XpX4J+ll7m600487qf5/MKwA4M+JKuyb46i14yX/Xts/By1M+/LGBPkz68/OW+OfmTuHUen+U3DepHaDkJPDZfcOSLNLa/HRWWDN6hNS8nln45z7cCJgr1xYf8I74m+FERiqjT8yWsElU6Fcx3boOoDsf/3pK8hzSP+cERI7znvy3+Kj/TxPmOgoV113f0LfOMv7475lt88/ZjtQtdPItH5j+Vpon5hPK7z/mU2es+6BNe3v3U7/x82X/cvPz1z/DBZQ3mEz5dD/qs0O/y9IDP2GMo9fN44DOZoczPxIP+MNQJlekCD/GoPwzDrWbxDIhfwCP+pt8S/mBNEK4z/qvIFzr3o68a6trz/RZewdOUmE8zMllG7RfmpHb8gcBTC3Bvg1A8P6Ez9uThf83zfI7vzv/gBbZXftu2ND+Ob6vP9u9O4GBut26aOsEnC0jpCg/7Vtt6fxTB5EUh+nFc6SEf5VU60vWP6rUJ5tvNAc8YujZDsV8IcNxP8FlZXy/zUoA7PmPn82z7AKVxqFs+u4sCnJk9zFt+Mry+zbejnzuQDgFs6+rWlbpWpO9s0PLx07qs0W0cifGpS1VcHuDvKfbpY98WB/TFw9AD48/Rob+sR+c/R0f8PZ/zndvy6763KXzZB1tSiW8/LtX/SNok4IZY4LvPa/N8sBmf5pMCD4Mi/343f/4Lvn5D5+F8Qd4Z0Tdr2J1/yqrfDgTEZ6nPaoHk8tuRhI2/TJcF5DTvcL+YT/vW98V9V9fA/6DOPy/tLZQO/HKdVKHyte75RZ1Oe5Itu67ydMc/QNMq4H7y42JWxjGvAHnHn+nnV3C2/8sCxtGu4PlUTwW+56+qgqfJXz+Z0xbJOJb4561SLq+eH3+BeFpSeJV68dv3/fFHu5BPiwrH37OeB/WJ0y/+E22h36Mp8p2nAqcUYPmghd2HnP8CHsd5pqfrwxZWL13ZyMN6L3bd3edv2ceUH1Vy9d5s+/J5WWL8OuhTLLRlBFc+H/0o7eT8a95+ErjjPVJAXFc89/Xlj8//HvgkLgH9u31r+dN88CSwjNeXP9t374NCXfhjiR+d+6qCXQT5477fvPJ99kkf6vyE8CpgAX9Sl99e/pk+aFxV/IhArgB1+Fk+2iuf/46iz/NRH++X89xPz0A7IT7WMEvf2vddzz8nU/15LvGBKVPtFRDG3yM+VgCFV/8ghk3cj9r5vvn97o90HzbZv6AtvX5bfftP6Pj9munDBkTU5I/jtzl+toX6PLIErrc5/im88GUN4ifQ8tYn+Ofoxv/Tpv1/AKyhvoUAQAAA" + - id: "easter_basket" + name: "Easter Basket" + material: PLAYER_HEAD + texture: "83c25a7a188196b18717264ffe837ca348cf719e827179edc4b78cbcb8c7dd8" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/8XbTXbrLAwG4JnPscdJOvcML8cL8CI89OpvDMYgkIREwFfn3K910+R5ET9J069/f2i9WhZOcNWU1ydozSsj9ODlAfro4gSlB3mT1SRAHS3O8AMv0AUZKnkxXgxRwatxNoGWr9OZBCq+XmcyiPlfdSqBjG+hiwP00okIj/JYhId5pAfP8myAJ3hmCp7h6Q48xFMBntKRAA/zeYLU782nAaDfX08DwOFL7v7BqzKAkidwZYZan9cVIXC/AS5N8EKqkS5LoON1uiiDxlfbh6v9kPvN+CPUvu8HFaETf4rQpxJ04pMAhyxAOx0E2LkAvXjoiwKo+HmeV1fw647D/UIAJe99kMB7cYCdD1DBrzPhH5gvbIBi9Ot68/YTwHM+E0DF33U1AvgH49MzIOfn3F9jvrMfz3xYCBHPLUAygIZPGuA+xGd+RQPUfhrjkw6Y8LEAitUXBpzMQwefW/tzOg/ZhFM+EkAxfMpfYwNbgHqfG356Aq17yWcnoMJPGqHw99/8pO/Ox8AffZpPD4D/6q+h/VJfFADjEz8EQSe8vZ8tfP/pngT43aeGn6/8bx0F/+jtpzuu4AsCeHI4a9vcBVx4a+B7+putYfgkT/2hOvie3zbPfwOkOy/wvfyAn20YvA9zIGLJXxaZP4SySW4+DlDhH0shQcZfyyDz5xkTC/vf+kQEd0NYfBHuA4AjEBWFfp7Af32xs28n/YwQLUM4/7W+KflnAkde/0CA6AigiIJvUH+Ja8MqCyD1D4F/wcZW4g94AHKI9OtP5xvKN75A47dwEF4B3CKo9N9oA1Le+UMawO6C63WP3rcX77fEH6AfXfJ+6fg535Bj/c8n9gd4Cqt9bDFi/hL7TtzAB3AQutd91f6b9z8Bg350Dq69/Hfsg49hQzie8Y+WPv5E0Ni/19/5/If68XGg89Orkj8gBY/hbZ4p8hd/If2EF/t5mu9//VlP+WG/5brfEfmsCvy95NsAn3jHQzyshE7+cjZgo+sOxPoH4+8/+FE/2Bkv+BP2/H8HoP14OqqXf7U/ELzex9ofTcBE4mExCn38MCz5E0qDvVC1/P13sv7y9bEDEO5EpT+Bwv2oAUV+0Cz/KavYfyENKOjfKWFFcJXrlz9p/HRFiNqP0YwffgJJ1h2yFSQ+yUM/bwDx40+8HfgXuCz+k+8bUtj9rO79yfHYBCyb/T6S35j2F/Vr+SP+dPvXd1o0ubddDvjwD3y7gRrH6Rac/6J9omi/NPQvP44Cfyw9jmq9A/3yrfCGv369j8ZlLAZwIWTrDeGdkPz+N/hmlCVQlePNxVsg8cfbN2PzBBcf/C8AfwE/+ea4nwTVEUZfRf588rHXsT8F378VII4wZoXenLz3cvsvN/z7rYnwVkT8WNTYEvm+Y3abuXzz9odv7I+RHyUw+djiGAhN3NN4HvHPAOP5JZP7RAKaRTNcl7GP/Q9AWAOyAJyHRgifE/wdwKANMPU4LGr4pQaYFjjr5w2AERrgnjcYj/pJE5rwC85TARpGWLjh035NAux+S+znfIsA2R2X7EZy+JEvCZBTVGHDx/8uiPbzcWjKgFOF5K8AXCP1dvYwDM/5Swu9MHw+QItyPsn39kvD7x2gNPwrQJulhvKm9DeiHX0j8TsGEPE2QKPNnvNG8FfCL+83DmAfUsCHAA/w/wCNGU5NAEAAAA==" + - id: "egg_hunt" + name: "Egg Hunt" + material: WHEAT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+XZvZKbMBAH8NpX2m/hkpLi2swwMLyCY1fmCcwM5Nmjb62kXUmAgGRui0tsn/n9WQkJkj9//tu6sTqZPzPBzdTJ/DkRbrdzE/j+0QlC/9AACP/T/SP5s6ffDz/90D+WP3v1O5n/1/wfxv9be//x/A7+zOoUfsYrmqvk2RM+Vb6/lV/qi/L4JUNXwgenj3XnQB/7FB64qG+8KI/WPn7+VyMZlvC3DTyVI9st5XsZcnjtg3c28TBHrn/z/BJ8ToX+fCQ/B+0/uE72Dx3rpH98GCgWuPBXBdjo13VdxI9ve1F/SwCYZDf/N1br/NEUSLBEf4a1wB/9KuHLBDl8o+psv3H9Opoi089Yf5p9/WQ1jOL653Om/2HVAH8+0P/1i/tgABwfz1DaDyaAqd19fAIe7fNZAH2difhWSb9WZf0GVprf18cC7OE3lC8T3HUV9nUAuAH4ftMMwwADZPALfG/6g9dOgqraxZ8d3k8DBqGqrtdCflVVRBP8pcAmmOer8edN/vc3PxXwhj/i7u1IaV/yIEAw48wyBBPMXXfFL4Cl/jhCH5nxdhEGbWB+l+3TzRfHFP4IAGT4YTzx+q38ideLF50g4Y8j42F9SF9/YZ7f77fxX7YeYcV05H53/Hyi/jDwn5W+/g2vT3ahP/ObnY+jEwHU3juIAAt8VrxJUV9H0C8i/v3OA8iLT/i69QkfFuY7FfHF3nOlfSyB7ztZQn32l0DHt5uf8O3cW+fz8nXCNzdfGmdzAfHDACk/HJe4L6ehKMxfH8DmiEwA8ecgr4MZXPsFGjDpy3BC/Vr5oBGoHwRYyntrsFqBrF+j/vYAKb+O+5tHgPB5AP6xDZDyYw1gW+d6338Aei0O0IlK+cEATDqA/E3Xf6Aj4GyIkCEDUD4SgGdoW+2jARzfnQEmgBdEbYKkLwLoBG3bToq3PhYALNduB4KxsJtw4weYQIBa88bHAkzys7u7YZgEqgtIAO7rN3zfJBA85oNJyF/pnUI/NYEOILPA3gaQvowwCX6yY4wGYKXwx0M/tblDsDgAO++W+a3vkwGeQucz0OnAYt92gNuSt77qNhpALQZTJwOY7ssp6PwIZwBchEedsW2tz46s7rrxlcguRp0K0NHFjks0wH0Qg7656afWQut3Ub8VZRogX7bOKqD/pvhJP3c8owFe1o8FUKDuQOCDJLj/jPtIA9pQDwoLoD/zH7oI3wZw/ba0j18EX6JkgDsMAHjaxwKQPkjg+7KUD+UEjyVQ73fYU2/oX0ypAE7jod+H5UcAsTrU10uh479l6Qb4fEvyeJrAdwM8HP8NygwA1vo07yToaP8BfTHu4ty/vi6Xrb5N4Pi/XZ/P9WFQ7TeTj08B2X+0Mv0+01fb/nC5WP0yHOi7AYQ+lPM7ylcBWnPrI648oG/07emL9ecV9W0CwBN+XgLLC9/801vg6wB36cN/N6f8ZAL7i9LnF3rSlwGy+FgI+Bvqyn1FfDcAPPukn6wO+sEEwP17Ob+L+ypA39/xAseptvBJnwhgD1St8OHKvdGvqu56XYvzjQP4T8xHA0C+6xb5/q69ymcXkjxrdgj+3x8rZO1zYp3PP2R6lo/IwO971FeLBsL3Pf8vj77nOh8Ab2mJnLDLd3ah8nywaEV9MQDB2pbSvf6bCnE0gPF7xbM/YIQsWvKZO6Zji5Ljzweg6uXB4K5OtHu1TxYbgV75KgDu7OWL0nxP9Z7m1/lqnGEA/X4SdflNvncAt/vJaeh/fR1vjuFPPoo3O/9aP3OhI8cc4Gv8KJ++9NFvlbETCXK+TOZZ8GXqyRyvv0W5Dd8AQAAA" + - id: "rabbit_costume" + name: "Rabbit Costume" + material: RABBIT_FOOT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aS3KjMBAG4CNwBeka2id7Z2FW2bm4hXP2AQmB1OqnhJ2ZqunFTCpY/f0tME7sfH7+r3+gQqqBpd3r6w7GFqGpMd3WoNUvGEBs4PdC9QsGCCELnsQp25aAaeGxDF4a3RaA79EkUOtKX+zi0ZJ1ZQC5SzevCaBq06lf5odOXhFA2adPlwOo+3TyY/68Fghg5KkAH6lE/Uxwjf9Rl8Tf7+cO9PGBonX8HWxAcbA4N4oAiG70Q83HY1of1QX/Hgsbcz6zKQPY+ZCHR/0jm8Ynhr/OF67LUb89BI4JzwyzH9vNR+l8OoDV91a/MwDHF377iBlmE+6NJv9oRfvt3lznn52Ye1x7btgABr/cyQL4ygUDvMaH3/36IgKAhe/ziZXX+M133+YTTX7bv91uEV//J30mwBX+TeJf6Yc3+WSL3/bD7jP8/rL5yz66etCP340+/3POsM/w2ede5l/j+6be6rc8HeEF/iE+n08xAxVN6TP8cy8+gs2X40O9DVCvuNb3CC9EGPLbViiPRmA3ALGXtbjxWZ2+EBT+kovZfi/yMITGX+pith/Rf9aiU6B7WPJLW8z2o3oqPEKHz4wfSJ2IgA4x5pM6lgDvUvCyXy0seyN8EwE/ixf4BA5SkH30fr1My+8hWH/R+B7xdfhWzCRho0Qf8MGkyz5a3KYN8OAKJPkFrih9i477XuIXuKC8Znjvu6yGT/1if0Zv/bLDTy0w/HqY8MWixw/hmwkA/IaPLRV+SrAsCD/qC1tfF/aSMeob+AXhZf/4amD7Bf8Y1fLkS76FXxDecAcYHh/5QXDUt/Eanzwyuv2PtaT955INbP8j19W+Xqb9gBrbU2V0/Acs5wTfVzXkN3jyhRNQ3SHFq4/wMTrqm98GIJm+q5/QI4/6+AWgGT/2NUwv+4dUX/u473Jv2Xe5pBOAFz6+c4XwSh/nV99VCOk7V/pNgB4/8SDAo8+XAtDjQ39LwPJdG8DwbQB+/OTDAPzvINz4igDOyT75Wxj8nbflpQAO833r029/oHzh8wE0fvUuBPmGB8WzASBvDICd+wB5JgCAQyB8IgHFa304d16OvgxUIdDDFE8GgNt+duj586pzcXtWVePX7zj388gVgAZgrrrOAHsX1SXQTF+JXVuQF2Enweh3bMHZwyMBFPxQgLKDVwTA+NZXJ6gaeDkAOj7+kZeZPz81oAOgPPWJn5EvPjW5xld82Fw9qFhI+Pj2c5+4Sjj6eR0ZwO5jEaijou+6/PIh5IFX+0SR67Ar0Cn96hhb7hrfQ1+XYH2YxXcWX4yQHqPzXZdPZziPG3zAM36oH5f+0K9tCnmbP+n8GRbtE1u0+5BX+Y0OAtD+xPuTyo/eNMV/UtUB6O33EwjQ8Ao/6VNKsa87vhT9KkDlp1FUfp75HLoMwPtlAJsfMhWbzDDA0VnwiwA9/pQmhdfd6Qe9X5XO3zbeVU+B86S8y5/PZ8AeYX6jPxV+mWHUd1p/PwnHHSDzE8Zf7bt8w9nmzXegI9hr/VD4rvSnoq/oU7zSj3X427+V36wZ8Ikb0Ok752A/lv/r/D/sgXUBAEAAAA==" + - id: "dragon" + name: "Dragon" + material: DRAGON_EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3bS5KkIBAG4HXdyeAGQERtvIbhktMPbzIhU0HRrsXQE11Vavv9PESsiDEGlN3+e7h4hCkv8EcBXuH5AC/xbID9Jd4G+O//lJ83v+bH1zzwUY7nfQS/dt21Mfa/5EOAP+RjCwwdb4sQYmKAodpP9wevOc5/6+I58ue2y0/65r9POmyud3zzE/7jvOHq+Y4PeASZV3wDecHseIsX7fZnfZrH+HM+zZhf4x/3EfJW7SufSfWar2Kpav8Yfuo/rff49nM5fHqcHl9rPctvFpIdvi7+/e5AAQTylaJ8ref6IIA7l2KKiL5Ovpen+yzva55063t5xuUAAtiT8bqzc/W1yOWuv0NfsLrQKcSjPpFAwPKoHwIIns/drwUuU/xyOtKXUrP+jQB5/C3LAiwprW1/xw2r28Lz1wOU4W/9ZV3X7IficVee8U3wl8Xzi5dqf7UHravy8z7HX/QjH3BbpLdAAPvW68gn+EsBjIGd74qykOVUCpAa3/OK1E1JMJjCwLk3+kpFiyqED5Zko42A+OIflNj8BpWrXYD5Ab9C5/B7B68SDzshDpwhm/N7eO15MAgu+/jzOQ+rjwah84cvv+YrxKHq358A268wu/im+a8GaPw+vvKXG34V4AovwC3zXgd01l7ji8+PvUt61QDFOeMrPwz+fn0rP9ZP73eKj2uQY94HgGc9/oEfTA6QbraOQHzeCnnn4wzdPKp/CQAkxfr+ZhNrH9sg9/2l+m8mBQBUjQc/3urizFO6IAbor/+Gij+pfZV0sa79nW+0GhQ0/LfrJSRgeLcUIuzq7iNv8CmBB1hfN0VMDBAirGsTQPs1N7oAWl64leLdABsdoL0AIQ8eVm77bpjZAIf+WvvLxAZg5OKv64r5MvOLz/0AJ/za8mnmt/wEnw0QH34yX838/hgXQE/yAwbukdEnR37x9akf5lV+vwkPY8H/urJ/vyYFqGa9/EbmAD16h79n3pXkN5MeuPhjBxwOAXXR/0IfT/sL8H2Ag3OrXt/U/nclh34J0OOrHn+jfTj/oTk3fjMTrlAXgD256vM3z4chDfWcQFS+T3Dup8XEqW9LuqKpGRCP/BQg7HU9wJxdRTr8vu7XIx/uDEOAPntaw4ZmOOXpAPWCK/u+Y+SBj9bT6thfOF+ACw8PAXDLpANUDxIXfYDi5i++In014MdvMvK5BVGafik+FaDm+/yDgl3/Ejv3ZV/nFOXkNsDTfhr2YeTLE7/hz8bfVvmfpLY+6Hg2wKjvMzhlqf08HOthh3wb4Jg/922xykb4IUNT/aoB7vhb8beQ4JMCoPWhZn0UAN14BvwtPlF6PwZBC9T6OYHz4Y1nxC85wulCg6DqK/iIzjRAmRrKUUP+tsHqwDknnbnhgZ93yBj3pr/FVRA2K17J/CeyOsS/3PG5Mcf47a4rPh2A52XuAWLf+HNadUEf+amT9/g35BE3fXLIgeq5Hbw/3v6Vv6U2pusft4cA9FE3fVwpRJQPwVdkM0306wsvv9t9ALqhptafa4vk1xGf8PNMiLb6pxGqAWb76RaDIZn8x+sP7y1wawjwmF9uLY0Qd/sAT7W/hLeUBpfpYYA44K6/xbO6E3OVD9vpAOaunyY2/i4UN5NDMHzdf8+n1canhqD/DzAP+5L3jVGjAQZ8iV5SAOA7frQFRvyyyis++Bx48P/P+vzuANRa2H9OXnqTvtud2wDU5RCGgMkNAMt0n9iWfEOUKT6/Dg/bfIAn/bLIb3G/Fv7M9yU2mNrL3AOc33kB8H64CTAL4jwNG9rvDEC1/9Hdr+4Plu8MQPb/2VMQyMbzfQGu3IBAtpr/BxGdhasAQAAA" + - id: "pig_peace" + name: "Pig Peace" + material: CARROT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+2YTXLDIAyFz9IcyRvdg2UXOXsTzI8EkpEMrjITM502MdL7HsIFY4Cl7fd3rZ6Z74u/+V/OdzfgzXc34L0CuRfgAwx4O/DmvyrgbeHX30L08Akm/C18vQN3A/4O/A2YMzbc5hOtBjamTeXYDHBSxxZGGWv4kgNFvMWALLcrHnxdUoBDQWP7FL7FgDN/Jf7MBNz8K/h6Azefa2EEEgIW8UPIWiwgR6zgcwbCWx12vVY//k4hMt7wFCTgs2IDYIMY/sQEBCJN9z8paiG/EZb4rAGsqzXA4NX81gARPmWAUxVaH0p1z/ANeCa4EbYbqIp9ZSiFM9AJKw1QPlES6LlrwNeuAiJeWP94A5yy7q0A4iehn9T69a/2AEqR+JDejgxcEDyCvDANH/UASTKd21gDgPGP2Dh+7qkGYBq/tzKQxIgYyv9BXaVsC9Cx5TEWxAPgQfnvK7X3eOLn+egiQl3NRwOsjOoNFeBiPvB8+D8+cPW/ir91/Ee+Wvrf9I6/yACqMRl/6ku/oI4f/olfKVfyyU1W+aQDML/vWMyP0//62dfl/ZkcmOGv5iO5OOuID7ivHkJW4sOGG6KUQ8lWvpfYdfxAH6qE80cMGe/9Cioz/hDQ8a5srsRNCun4RicoldYVFaDq1tNgDMET1eup+Rv6mArAn65pkWhMJ2fgHz9rjy50ElpwmzGQPXTajmZkg45lwG8HNuSPy5DTBsNiVcQwKnrI53Z1pQE5aOicUQk4njVAVmMxoHwO6KKGHzgRY5P0dAUIKOEkvSxLhg2hGMb8EwYOxDQGako4ZSAmFQnTWTBtdSHn0okx4KFq7II6fDG9/2F2Ih0d8l1v246rTMi5fZeCDjk79F1KPn3ro3RAQkdvgkZ8Jk/DRnEj/rO0Rp9YFz2K2hqZiEdGSCp93DM3XMWgE6leYPQKUY/PJdAkVQOj6pr4egHZwCxfmSYamOSr87z5koE5viGRnwErfiK7/hPCBP588rM3cAZ/Pvk5Drm0Pd0NePPdDTjz3Q34z4C3gXsK0AOhowNvC9A8nfvZcDbwAbeDfxFuA97828DX3wLufHcDN//mO+Ld+QsN/AFd4vHlAEAAAA==" + - id: "angry_cow" + name: "Angry Cow" + material: LEATHER + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/73bW5KqOhQG4CEwHRkCA/AhjCJIlWUx+kOSdc9KCK1n56VbxXx/roB2fz7tsvysdJB/wf8lwC/1+wl+rd9MgG95POZmdYcuvwwAx4fH6TsBjnb5RQA6vPg6QMceyXCLB58TDOBXEcZ56w/jnQjz4zHMC3++rbsJzooe/QDq8OxDgLr2lynXCebid8Zgafo6gbXbMVy/FWCxvgoAETq2m0HxyQ+tAHa4wBcB5nlAryIIHn0vQDVdAndAPIuqP8Z9b+L5JRNgZt8PUPHQARHLsL/veHDEBDPz4FcBfJ90y7UD7OxDAB6+tu/wRxTFYs5TovmRj4pxVn4Af7ngjy7f7IBd8hCAU3DzdYBL3qO8Dii8mCtRJngof+nxURW3q82UdFp/lq0EyuVh/KXpG7411LVfLRQVIGp+GeYH/QpP/qYSKH8Z42/49XPGj8pfXP7PvltsgMUE+J/5K/+a/97vBKj9iv+1Hy15wX/plwCDvs9v3/tjATz+J/5YB3j6yf/EHwjg8qn5/8T39eJ/FWCrB6C6N2jhyve217/5cVgvPPp/SrA5A3AM6qe/fet7EyAO88X/vgOMf4z5yJcl+EM/DvrR+Hf34hQY/EYHjDSfA/zZbw7AEL8VN45fCiIv/LsBBM8B7nVAni8XfiuA4lt+f0Ke84f8TgA3gubPt0N/6gA8II3bgbYvN8F0myhfYvb5fPY6gP16YPBOdLsMQLfqmy3v9xMTuB0g/Kr9eCMsxjD6AVw/v/HNAdwl0PGh+bv0GwHc5qPPAZwO6Pox+2oSuwH87i8d94YEqgN21481H2XzmyNw6ZcAvs+/xYpPP9Qk9k8D/uyDqcMBdhHg/NUuuPIYYuyi95/PJwfYtkGfpq7TAbG+0dfdgB9DpOYX/r25AdrNp6XrdUCMDT53A38KwvxbVX4M+AnbZADsgNeFD2Ocu0HwL7ET0H7Xa/8u258bMHLykb0DfHm39emz0cbeV/z3W/mjAfJv+y54XFA3/N3wz+fQ2Zf5TfK3/RRA6YM+lL00/y18OrFJv3XuycuM3l168p6/KT5NADqxigCtk1+EAKy/txv3onnnE9132y8BNuTPSvKnecP+tpnp8/IHoOuXNyQ+Vzrup8HXAV53fdooN7wBHtsBoPmw6Ut/v+dzgIKnMuinpUOnney/ylnhlr+xT0+lq9r9ciNKH1qISxfie74XoCqwv10kgM8MxNUjnJSwmm/9nODSf23lvJV37j1e+SMJXkMB6FODLZO75f/sM9ELwJ8a6KsdrqfhH1v+nmYd8OW1p5BF83PxePF1rvXL91Tr2krQ86GX87g7AYSeBPbFl8sz+X6ANKVhMb/sLR+OcdR+TiAekYB+fnjTf9c+31tYXxcEgvSD7X7fP2uGM6Hjy0vCNh9CyNWHAHz+nhl9fPW+r69Iu37IvPIn9kNJF3w+vRLQ15NRdkbfD9Rk8CfpQ3H0c2TySw5PfVEmR9ufKn+aiBd+tRUlfg5Nn/VBf0JfbwCcTr9vJj28On6eHl0fy0G+CsCvahv7PkwtW/rtAA6/8MrDAGUvVjryU+/bgNOf566/TWK8yTd/5HKwTy+sxF/5qbR9PveQP6tiTwZQRvjkT/iGa/7weApgnh3h0/wPFMBNcFT8ysbKAeip1fBX/jnAIYjcTd3zi7YeqK6r8q/4XHKAIDO4OPriwBU4/DnjuWBo7pGPe8wqWjZLPdeLzWd/Vb6Qb/GvvMYCnklE5/K8yjU3/NXquF9uQ70vA1CDqHqYWOUF4EMLV/44bzpg1c2TlvCv+MG5VwUIpntn60+9AIIfHHz0MYBYCdwX1g+X/vXKrzuAA3CFeqbhBJBHZNX6Nb9zuQ7g+gH+FGiyx9DSJf+sSt3476ZcjUDLD+XyRx/E29FMJ51J3vBa3YuQP+imANaHC9AwweWXPEzxuO3DDbcudB/uJdi1T2MecpXQs+iLqSr59DbkbQBxV+clKIecNa+lXdjpiiq+CaD80k+x8uVDJwG9cPq0/eBQsjWxT8/O1l/VH4FSy+EXlJwZEbNvptLK1AQ8BiglHacX6Rr7xfaBGiHLr9Ia9K8CpG/pqwkCr2g+rDLAsjg+XrzI7ejS9wYo9b5dyGWFKf3D1z+OD5NiPIAqDb90Lv4V7qL6u8yOmXeoez5UD7ydfPJ6YIXF9wnqBPmdj0TlSx592H0a/ix9528SW77IC0PJy33YT0/Js1+6ahvxcWnjI7nZld6QfgrwwdM/zDizGd/2SxGPaK+Z9Jou/kf4OP+qAHC3OO6XB3gnTRsLNJtX1vSp/DDpBPJmdTQB8aHi87Cnk0Jw/Jn9EgF/lfeD15sh8AeYuQa67sy1UtuSrzsgyMyaxyrG9EONePm9XA5bX11+OD7wfBEzxB8T3oKEfNbjyw4UJ/JlgioADj4nvJoI5Xgzi0r9NKVy+Tj+2uGhdOci3WMKX83ooHgMMLm+uGUVVXRWg34DvGVSvtbJz0cgT2fmpeNXGczNve5HwefTzsf3J+MvTm3HYKE3iEtsqFv+64v0p8rHBKN8Xun4IJPmAsfyn6kq9C8KefmaBBeNLtOIHlYXWBVfJ+D/kMD84/99OKkpwp0oeKtXCchfyR9OAANpdPIbvEpg31QthcsA/Ml2XRq8LA3/zjA08Lv/AWxWwmCEJn77H6Ab5U92g/8PRkWNxQBAAAA=" + - id: "egg_gunner" + name: "Egg Gunner" + material: FIREWORK_STAR + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "egg_hit" + name: "Egg Hit" + material: EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "rabbits_in_a_basket" + name: "Rabbits in a Basket" + material: RABBIT_HIDE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "pumpkinz" + name: "Pumpkinz" + material: PUMPKIN_PIE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+2aWXarMAyGn80y8sYeJFaTQ/e/gxvbsjWaEEpKe26UhxozfL8kj9Cvr//dbgfP/YDdDgs4Sfh5/v/ZSJ4m4Lc/8GNfn6h+7GPfsL/UfS6fEC4X8HvsvVqu9vTqRN+uFnD6jVdn9Dy7X2x/xv95fmMUdvHfImB/pOb50vj/ggS868m3a/mP8VlJEXKWbIjlT+Yv3U4VIA8mDWcF80xlsjMVBLYowwd+LnBZ+1P0LOCB1/CTFKzBz8G7OQFLdP8Lv6DKsykFi0vAtwWs26EXOFzQ1Z2QhNWYpotyi4A9UUJwmoWu9+Cb4zMEjGKvAegqTQgGzboU9sX/pr2P8LoWAE5Owcg59KUHPKUkJQg/bofivwY8d0jlDK/mBaxTyJG/uP3vwNMB40MBx2wPvh5K/GkCBryAr/FnCdA4AGpbbrhFi0/pDL5yFyrjocBPOFv8HQLCxqndB9G6wfFd+F8ScAs6pxh5DF4ld4x/KQCvuB8J2OYfFBAkfySAzk70K4Yn8i3eCND4hxn/Dwnw7iv3wPErulrmixniJH57+GQEgMVnAYtLQNTOn/FpbAeBJwGGr/HTlKu7/xQA18/neZf7ha+8UwIiPPPzGnGUAMsXEbJ8/fQsQPIjfBaA9TdsAF5AFH7PzwIEP8Yv0PC7+Tb+I77zP+STABQCFmFbfBX+LOAl/9vN0PBo6LRxWsv+9an7RYBRsOV/uxmh4VE51ZaSiLR/fs4vk/8+/3voiv/MN3DJ9woc3yqQA2yEL7kHZL57YhbCaiK+XWgIAXp87wLkxUsTMM8PvtivdnqNEkYCQn5e6PRFmDd1eSrozgezWZO7l0jAiB+Tm7iQn/GlEO1ZpKwjfImU/BTwQVM3BRzjc6OQfCoA9zv3RDoz5IO6mnseyGYY8LHx+WUNqjSZbezIfcVnDCTDb4ep8kvt3PsYSQj5WsB+vhCg+MBQ2c0t3gogvuktnYjKaUgDfkKZa/WwmP8YOuq+JvSfiZv8fiheUHH/7gICfhm7QARA+89hVnxIIV+9HxPP6XNp/VNcVnwRAPVqS7hp+GU9rPnJ4d2bmhbxKiDkY8+b9rPy2/KmLscZX44cnnYQYuMqkPoAVQPU/NQf1XwGNelQNDy+vB7IU5YKiOLn6StVvkiA4adEj2o+98mwH2S8jXYuEl4KSIpP6zmdAOZP+ieIxlLg/oCfqsvEp/V8TwDyxFw83mnO/TJXZ35S1aiQdbxcFF/7v5+v3YcSqk2+nY3Y/95go0gL4wus+zA1flL1FHSQVZZf5mt+TAGVadRSlyEfJse3Y8KSF288Iio+tv1LA9EyolEXW0qo5+nAf8+fFB/7AFAXDUUA8zkATO1XJLR8ztwWX2xmoe+U2uqlCkgUXcHvWLqiDL2v8+vZJsDzWwTSlFoVNK9LiVL0Kh8lf6K3esh8FlCbwmPpnwS/zvBQ3jOV83XmAT3XZn5ZsDNfL/iWSfLz/WvMLxI4AGWgrViUpYC/6PZnEpDhsFQ+Or4R0PmUjFJUhRE/aT5KPiyVj5rvA8AqoGP7Fc/5PAIir1E0H9SLilgAGL/VMY0YcmtMfLWEq1vzZ/x1HABxQh3WEYN3GjXwig/Vf6hLw8zHPBtUvsLf7xsBiCvriAF9ryf45H29ol2Z+5LoZJp+f0EAyD9ts1ndRrExqrFxN5DJT0/0KeownwfFnmvK+5Avv331b2H7BMRPrQt3nkco71apxJMA8TFul4C4NfKo1ARs8OXXP/U1dtwHnvP91Yof4e/+HwCeCgBTGvOVUK43n5/tB2knoPSMCHDfyYeaWAsKE0DNQOFVDcj6QIANj3XY4SMBkYmH6spn/Gf4vQKGqtzEKWu3brYD0EEJlr/3RjcC/6it1i6F/6SEAfxHNGyz3ypiJ/odIl5Gn6Tje9xjWs5nfuxjH/vYW+wfDUFmZwBAAAA=" + - id: "sweets" + name: "Sweets" + material: GOLDEN_APPLE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/8WbS3LjNhCG1541inthJfsIUwFT1s7aUSegudMNIp4+6CcaD4KUPKl0MjYlk/z+bjTe5DTdbt7fwIb/w6ab2nMXjuP4MtTQJvD/Rf44hHFcX6Irb7phBKZop2je2L6AMK7r03G4ZQ5PqQBcYTvwiEf6kwISHgWw/3v4N2vMD0x/rgyQlQKQ/O85/PYrGQhwLuKFD1F4Di82Gf+78SYsGB65KMCFf4LQLb8qkC+wbT4KmKZ+cUcouk7/vzkQEPmQ/kUGSJHoF+7Lb/PdMJH18QPi3369vdFPONu5yA/MD0LEIyvAgffX6w7f4CkhfJ6A5DaUgfIhAoFiADoIGQ9CxnfAv34lPgqYFD/kyT5pOsb6bxQQ/836jykA/JDwQ8AmAWxkvEN8zp9uBT9zXS0q6PE5B4WP54XweBB/Te5n+Cgg4fNCz+lUCmX8LR+1Ez5wuCNeBJjw+4x/mrjF3cF7I+CXlH3Gl8JTAQ7xj9p/I+AUL6CU2/HeGwFc834VfFEAMRgKAcZ/K8BvNLB18K0ApWv9t4YS+AgFeK98FXBVPF+xg5dOAgWU7V/RWth4PGInetLekwsgCvDX63pdHxsNTcN95Tvk2/a/01o5dyIBGhoRgHgom6fwJOAtt05jiXwQoJ9FwFdHwB5/OIpXAeZzFABdwPVxxdx8+FrALv/owCS2Q/GE6L8VhBFgAY9WBHr4SsDl0sOPrkpuJwoQj+3T83y1y2Xp4Ufsm4vvVfuGgKf4yyZ/ZP6mkYK6APr8bGgU8S0B47iM1A32BxLYQq5lAI7yI2VeyGrHl6ggDUS2+T4rgPEw/xJtaQpYeMhBAkJLgPv8bPt/iE94xLIAm+LoOvNRQKjwn2CId0UCUrxIgPdtvGMI8+clr2EB0TAIXGg0In88nZzi/SXx19Vb/pj4TQFwuwu4SAJmA9fB5wK/whIc0BXvSQA4f/m8SPgz/6m8uACSADsUg/ux78zP8JT3C9xotu3jA3pC7Gw/PeAT36Y/Dx0A500JZNPCwfDnkJU88aPN+M/8DUDov3Ofisf0z+o/FJckgIn+VMzLKOvDPM/BlDyMOxI+zDYrqKGB1pDwzHdF8yPhKquA8h04HQ19j7+z9g2z3Qm/xjNf8SQA8I6HbGnwXfIn8X5hBTV+QO9bHaMMA5P/6jD9DDpmFKsEZIVP/LLzZa8rfJwH0CgUvib/817T4aQh+6oQgAGgeyJ/o+9vDgdwTrAK34H/vsUfTUSGcv4TP6V7xxavxmxa0Hkg8U0CJv5IAYAkSSFQCbge9CIfa8Vo+SRAPLP+Yzl5c3OekA/YfBr+E+4bAZQcLIAbOcor9l/ytHGXkxXwnDlYoCH3qQFCAbZ0ddLWFfAqP4246Bj7v88p+q7rPVr+2lDUfO9fFjCY6iICED6JBBkpQIu8tgV436xeL2mJ7qvdJo8CqP5Rj9Tm/yAApQDHcD/RmtdNWqDUVDYE/JkAFBMYEiANEI9I/rMAlE09RsIn/4dt/4c/wM9XaEgBtnPaAD82E/APBEDwtreJEQD398v/DwSA8aUAs2q2nf/DzwNg8HZRlseh4n8n/N77H/IVr3xnpwHr13pdr1TPilSVnZAfCLB4nRs6WSdTPLrveDFTFKStGIefVD4d2o2a5jF8ggXRx5jzs2lwA8+BsntBbmAZ8Z6O7mwxG8fxEye3nZrneFybuyKfckIEEDea4dNx+uIAn5dDW3jh+yv1k7I6MSrfbfL5pwmOHFsBsBrI6+GjLlpb/MDuD8pfRQAB4Qr8bfgmCtzL2mOVDIZLcTISFefXhB/8l+Dt4q3l83pSh29ixefL54G2FGkcPMhgw66Qf11zvpRWlv1uOMo3NQc/8GKsKCvXx6n8pVrk/psC9lt8LvHBnFfwM/w9mbR3KfyDS+JGruZGwCa/rP4Z3zEev31Pdr/zl9b/mKu2aHIBr/HN0QBUNhJA/nvDP/nfdnHIaf3ztuYV8TdVThKgzb+z6/Ff4mf+Y2kpXvJrm9/M/y4fyHfLT7tjjvff0y3g2Ppv7Vj+l3xgZ/57EOCM/+YOXBWbfGe+sHX1Wf4XLM6L/wl/Mvyx5HltEAVqj3f494qvm8MubRtws0X833Bbm/ve5Xy3yafGu+O/svUH80+JP2Ijw/2AY7wJiLPHQ041WSH895oP81OrZsA9lMTXW5k7pulEPrsoqKlR5Nx/b/F9IQD40hWacQv/0t850NYAsZST5P97m/8pC6RCAj4IwOHb8LpZfqv9MwLsMFMGyI9iQX3voZzKXBq9uqL9z84D/10toBwQPz0XsEVi+7/yRtH/jE8Cfoy3e7N1mlo++p8LoMX8n+ErNRt48t/V527jO/uAuX18fOydAvhLqSrXU+LdclDA+fzxsSMBsr90v7Aq+G45JiCW4RkldPCTCX97ttfCH+LzDsW5E4KIvyW87hoN8rRQCw/8eV72tvv0eahw3lQwTZ/T5XbR/lL5uljZwjvYiMNtx+7SLO9PQQw20gDWxBS/rl5XPe1qacUH5wl/6SlQ/GYIYEHulvDr48H8tB80VQJgQ4B35C49Abo/JyGoFdBaIN0f8FEA8z0rgL/nDwvRfghvCF7q/eA2PhXCNh78J74uldPTSmUzOs8hzLIXvMEfG1aGYEp43DFR/28p+JX/yhcFzWrQwlchgNKnsdI4jqX/N/OoXNE0434jC4Db1gFo4zEERgD7r+c/hF/sRjX4M9lGJdzE5wKm22T5af+65Od3h86R+YHy8Dg+KwJciSfnRtzD1n3MqeV+2kcVfvyN+3NP4FlA8l8E8Gauk9CU+Is+/REzJgie+Nn+Wg/fETDkI47iQUV+AkIF5PzYEKiEPj4XwLshOki0iWYfjlU6CaA2gLIQeyKTAwfwowkARmBomg6WLN0KSJXQpOAeX/BSBWi7sWOXy/eytAS4xD9a+BV+16LvJT4JoDDYkch+6ON/x/nR9+/vtgBVYPnbaF1etqW/Y95/t/FZgzPPyg8ddBJwEP9+P0cB/ogAxYcOWgQc4+M81W9F4Dtr8uaEDx00CziCl4ky8lv+zw0+Z9c2mvzf58tEfVMA1Lr6stAns+3i399LfiGAup4G/5Cdu3hdouDff1cC5i38MX7ffVmi0aWSO/FVANPnakj+BL+8DPO14NNCFXxMAr6/E701TXsRb7YHnUsB4CMJQMQbenOW+BIf8bIbi/y7oacU3KXLDl6X3nY/6DsszskSVUoB5O/SZcWkB29NxJkv+47uXqVgbAQtfRPf5Z95HSLhuciFzwJcS8DptEdPb4N04Xr9qDmnfHmLw+V1AHIB+T26DEf24HwD7Z/kUSwTAFsCUgkjv0s3L4I0i1zggjevSeH7Kxl/yAKA2Xhqrprt8Uu2XJ+/JpUCoPy8EcDNMniiy/BSi2Hw7ghcn4nA+ebA1Ybf4uLFTieLxIker1egPHA9LvqaFz1qtw23oQskQHf6WAAEQKcBdqVWrhePR8MnxXCsfC1y14ILP2SvKbHsdGZNl1cLw5jxQYDg3blKt81eyr6mpGu95uSKLgL+Snh+7npU/sfHRpE3+GYT3kx0kjUc4DrS4rvK2mxxlnYXzDMl9QWN21BHVfA5dIfYfF/im/2+9on1Vy3+X0zvQksByM/e0zl0ZSx+KwDeOAB+OOB2LsAB/tT3vzJMv8BPewc5SPznBAD/Gf/pkVYrQPGaAc8IwBe1/gVXJ/NbAEAAAA==" + - id: "snow_angel" + name: "Snow Angel" + material: SNOWBALL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "good_fortune" + name: "Good Fortune" + material: GOLD_INGOT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "bunny_parkour" + name: "Bunny Parkour" + material: BRICKS + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aS3LiMBAG4DU5gDfZeQPFGahechKKM6h0+vFDWK1+6I3NzNCpygTH9ve7JT9g8ni8ry7Xy+WNu//6ibp+rD/9YodkurLPyGA/zLKTfz3WD7IE/v4zMxT39y9f/78e/8+a/0ffmY72P/fO+Bf6cKBvp0r7dvp6g2+XApteZypjevtF/OSjAC2+xQUQ7b8NfB+g3respgRqC3r7QOHtnzK/rgACf2o+bIuy/KYACBNK3sZY0+v4YW9/HDkv+etieRa0jP+IA0CeTwM4ev5S/Kdakz++fgbi8yivl+E+TFg6pvivAEACKP68UPbXDgiK3PthqscSIGy/PAF/f1cf5u9kALCfP/YDCbDpCZ9PAdT9fN4FGLcA/PBnk/riFKysMADvv+6XBVCnHwrA55/z10W39dvmF81yvXAA2YfArwuQNwTi/AdSt74zAAcAIQDl+/uPoAHz6Z3nd21A1L+V+/aBHoaNMv9HWsIAAA3gfWWu2aC0WwKzYz7cfG03J8W3VgiQpZ+lM0AZ/uUancOvAdI49ZUAN3xqFvnuPqvh6gDYGy5I++hpDPnuEhfnRT+oNn9I8EkfMny5/1n8Wb4Ee7zGnxMsfpKfAigNkBaDxEfmXwbPBsC/Op1OaPF89hX6qanHA3jZ1Tb+61W6vz+vRgb+hAvdGmTeth4/2/p0+vEVjEjm4Zf4fOOfoLAv8mL/baYvZCf+j/cVXmlAhi/piq/ZxDcl/Zd57sfswDdF/rKmcM3r5+u22wq97fKXuXofD7/ReWEjfJl1rr8CVfq6zTYKrvOOD/fYw1e3Ae6fiB8LIPsqzbYB7lO9LIAJ/ZxNUADp6IsCmM3Pjxz4kh4PIFRMxz764Mf9KB59eYBosX3TByDxiewNPv7gS3gPmuFH+6wVu+6GnvDsxwNM72EXPz7Sik8DBBx+FvNrsPd/a4D4RFd9pSi/RZL9Ifw4s91XIokTYOjXgFgifQZ6vzFAvCOJBtT5sTxkFub4zQFq/UHx78XFPe6HWyz+cF/8ci/bhxy/Q4B7qe8CfKTfMAe3yba+HNFbhXkt8lj38ttPwSfhny9+CyA+08rPWZW9R/66fHR+lG6fAcLlzvvTGOf4QYC6oQ/770Z7yPochw9BHU/8ZwGP/bb2AzrVMu0zHYFqHw73wZb7I/UNZ+ydXsEEH8ilrsT3Abb/IBYqNv/4OgX62c/ACC8EYP6zwj9zX+bZfcQPAPt9wdk3T0HSf/7ZvOLfFb7Ix/Nv/cOAfF8qdHctw5Gf2X/Vrzt63/96vxAnCRJ+OkENjxLE/TQf6210g7zjL/TT6/uN+vjsgAqr3W+rr//1v/7H+OQ2/G/4Wnfn/e/Qf3HP7kB38OU9Oz/6+NvJlx/t1hTuD2OP8l9/mvtWP1LmYH+X8U/zWoAefNbxywG68Injn9dg78Bznrsr/eBkmF70c8p9447/vWWidbT/B3JKCxwAQAAA" + - id: "lucky_rabbit" + name: "Lucky Rabbit" + material: RABBIT_FOOT + currency: TOKEN + cost: 10000 + rarity: RARE + item: "H4sIAAAAAAAA/+3afZqjIAwG8DN4g4Zb7NXm9FMrIkgS8gXOPLP85ey2/b0EQaXdtofb19nww7A2lB7zcxmww8AqD6T//p/18XN1hs/Oiof85gXNn9E+Lj3t0+vVsAGA3KcUuw8gD8D5+QXaooPGb6KETHp41ofWTykt9aH209EW+lD7yenrF72aP2wApd/PP7kPlZ959fhjs1zvv0rndb72f3heM/qdol10vfwdNCz6CO/x5W9t/IZX+E0UtR/Jmy86Qbze/9fyy32CX+UT1bfyZj+o+9aLbhRvvOgW3nn2Gf3M56uOh9f5Pa9eegP8FxQf8hCs9QN5g3/yu58HYJH/qf2r6n4O4OBV/qvms+8sv87f+Uf9cP7X+an1vbzGR7rv5rV+230/7/GdK4/WT6ni3dd9td/Ra32cXzb+FL/GJ/U184/jF/gsP3/9G/Cz/RE/+foz5qf6An6mT4FxAVif7u8Snyl3WAEYnxvtBb6cD3/+gmtXWVD9eH+PgPP9yecMQNafCsCUJcaHXH1VgED/yKDqvSMAPf6itXeO/7m5PvytPGmxJTF8Ccf42/Ft2m2l5wJA9P7nUVNp9cEcgPSvE2BQ+rwPZgxAn3+wQdlg5CJcr4r09wlw9AtKJwe8KQDtv1ehY3tJsRYE+tvHPwLIEwT6OYS886YAAfffP8rXBgi4/3cFCLj/n+gbeGUAw/1/aIAZviaA/vkjNoD6+eNX+LqfQmief+rGrc1/wOcvTV7f1/0F/ujK/LQvC2D2xzcmU33JfVGc32mi27Iw38aLAkh8Kz/Lj7wdF/g3TnVLbvevAI2nfCAon8P72O/ven+0CYG0+vU1Kvn93/0z1HtCZAD693+1X558HTwe4DbghP/ZBCgfYeTb91E+9VNIOB/v9RtyaADspOP84wkcHN1v3wmEX/1r54PlvCcCND5z2Pj1DovJv95u8318Oj9gL+Qzfj6Lweqjwy/OdI4g0D7eWF9eklxBWlngvxujdFU5/9zi+LeP1b9qGl9xQtY+JeGjQvua+VD78vE/A6K+ajpWPivhUxHzVasxXP5g0uOHGD/8Ogbhrf52p6BqqVygeV2LMj50jYwANW/22z3wni8RyJTdpKPWX/wwrA2lh/yH2zfTfSyyAEAAAA==" + - id: "spooky_game_over" + name: "Spooky Game Over" + material: GOLDEN_PICKAXE + currency: TOKEN + cost: 0 + rarity: RARE + item: "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" + - id: "season_s_greetings" + name: "Season's Greetings" + material: SPRUCE_SAPLING + currency: TOKEN + cost: 0 + rarity: RARE + item: "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" + - id: "silent_night" + name: "Silent Night" + material: ZOMBIE_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: RARE + item: "H4sIAAAAAAAA/+2XS7KqMBRF+7QJA6DFZySM4LbsaeWVZTkCB//yz8lJCAFjYqmb4pZKirXPL3Ap/Xr1tQ18uL4mvzsDFcsvlc/6wo76wG8lM1C2XT1Hfd/Xi76nPVcwB6/KC3LE8V9Vf3z0gd+eOPr49drxv9/8l1XWWh84auuVvf3x8e88QjtLbWkXJfPgxF9yqwmc1eO3m6BskMIZOBB/hqlH9aclI37j+uc6d/TRBeBLR67qf6mCV8cbxE+rGFDEX/y0igFNJPSVBiJbteIRa4AQUiF+ohwQrbIGSEh8KszZg8/5Tqm2DfJfnYW23eTzJOSP+nJphWgCf0c7Jv7L3hrZkYvyeRm26pgaeQtl8PH4t3OQuGe0SDv4aBrQKV4htmtOw/St+m/nQO+akTwIooNGXpIchEVl/DJSqd5doSh24JAI3v725SAe/0rMiC+UYGJlF1vtAxvzOt6t/8ZI7oi/dWJO5UMXQSOh+utEOL95Db+D7xlZzQEF8cOhwjrI9xISF2x4jH+Kj4uA4qe2D8KMzHyCSk3t03ydv3bRvXEiX+cAaQUxQGXgy4a04Uf4A9Y8R/lJBvREeHwaAQs2V4RP9/H9uUDg6xWxt/kpBsAqjA+FDdjZ+cCBuNscV6AHET6RD5bFug3GvjIET/OBhVV+ZAYwf9tAaNl60w8zYqMewPc9xucO/FabXX6wB3PxCfGDFV/nsC2Pbxo5je8vW+OHZ2A4yl9bZlHN0DSw9gBuNiRTAw+/ZcBb1UA++9s0c8NOGy6O3OmBw3y9jLEMP9z9TuS4B3183ABe1TTCAEh3w/PfONOnjF1hHxyM31sm44eR8fzrdKsKYPj87+j+57k8NSfNl0HicecfXTjcAbZ4KxbsN8kPDFhkBue5YzrKd3Ticg1Epcx0UoX5ti6dNpADLwxIByNTlI74XQ7+Ivis0pw/jUaArbqSz2VOvgp/WQx/mqZRH9aBhMt9ITt/kQYEX+V4UmKTZ3blxvDltQx8Hb7oABM/54LpQ3zlTOcgA56L3Unyb0w8wTp+hz9ZeA6+dcAyAPhXptnnO/As/JOtv4p/vt3uN5F4DrJ8zM7LX7gBw7+zQvMv7Cmk+WIoXfrT/K47QS2C/3jcH+y8s/ghfxyHAW1M7MJhvhwdB6/q/xCyfPUIHrkDdzdQCTjIxgYWEz8TqL/PB4/DvfwOCcCZEH+A/S/yP+t0OA2QYAJzXfyiJOfv/DifxdvOZPafwDsJ4jvawoayz/Hy7uez4A9m/q/imcjbb8TvIRuAZPwJvO5wvmhuweeBz7L4Ix6AJ/ndiR8uXPL/dJ7lc0B0nzzywa3MM499HrrhjwlVOxR/Ljrn25lmJpgN+PIp+KOA29eBfHDLh3tL58bvuskKDxjAys7zRCI2Xk/v8EZRlu5aKQ2UVGI+lDUgcRZaBf/FqpQAja2M/yaVnuwo/vVeom9/BVJROd2e3s3PR6v+rP2K/dNPRXT5D08/3aAAQAAA" + - id: "ugly_bed_wars_sweater" + name: "Ugly Bed Wars Sweater" + material: RED_BED + currency: TOKEN + cost: 0 + rarity: RARE + item: "H4sIAAAAAAAA/+2aa46kMAyEz5Ar5D65/3VmNR1ov6psAyPtD5B2RSeur+wEQtOTMf6fY855M+IeYU6uz/rvEuZk/bz3KmEFAfNzfjbaLqH+d0QWZcIyhDNIxP1+QloL6BBWRNhRMnAGE7fMYTNICRawpH6I4F0M1foaOCEGnIRjuM7hHLnW1EAIDLBO/TF/ZiipWGcQEjL9RugrbUJx3IYIsRmrQhw46qp+lfpKFv1+myOJuFpf3ZzEFbUwhcQ8WVYSd7ImVvTHolhOwZnTZbloXkUA82f0GSITP6DHiFFTBw/njjlIoWqOUmjJA0ZXfVeOGA31XblntNV35Qrx93JyT1XNGvK1bBzOwGuXk7cAv+4acX45rFoH+VcAADHO//F0rUMZJVABYIRRe4RYRsMEUgBFRGpBMOt4kEACSBBIvfXuKeYSSAAZYhwvZ1YN/NduFP4UkCH2d5hgyQTitW8eVT8GZIjxraHov0vX/mTJ54j9ttb1X+cKkgCI/wfxCe35ryUWMA5IEeKHgqK/WUA5IEWAX2X2fbXC28f5Y0AJIUdS5W7zt4oSoIMg6sSbANoIp64JIQAjoqdV3T+otOUfD1bxAHPd1M+LiEN2Ty6fG221fv+9Jt9Prw5Djpte/TrmU+uqcylTH8GHotw8r9UgZK+nouSjsTYKsVuUEZNPd9vAjkLpsp0NggsJus2UFkrPcrNqUqEH+MrJGJNBSErPBoGQ4xTQd0msJINQKD3Qq1RZ6VELBTRv8CkzB7G42QLCWJTCVAxQKMCGAHrRAjaPYNekATCTtJezUY4U7y/Q5vSOY+1i13XdHJVQKapHgOYoWaTM23NGJwUcVq6hYA4Iptf7Z9dzw9wTfM8Yxx81zxudTkNMt6c4yGE/FX//sdjwaXB0dIZHeE+dyhSdRkBAHX812dJxiO+x5Vqy8ZdNbh4DpW7SSDgDcf+Ex+7+fu2c8mwEKQT6r405xbrTZQ+1zES47kmpscKD9O8KRZ1m5kQ3veageRBrkt4n+oHz/TBMYK3mWgri2sZPr+GjM3Py19yh3Y82uxtB+59R5PEg7TUhTsC2Sq0ERPcws1+OECaQaTGA2bvfxAChpIWAYvaQEMiB9hkAuxxz8QN6iohi7+nf/S+FiKv11c1JXFELU0jMzQIRRDN3t7709OEK3TIPVti2eRUBzJ/RZ4hM/IAeI0ZNbdbarjlIoWqOUmjJA0ZXfVeOGA31XblntNV35Qrx93JyT1XNGvJ3/8u7/+Xd//Luf3n3vxzT1vRfSyxgHPDuf3n3v7z7X979L8B8futoq/X77zX5u//FJpO+ngYLfm0UYrcoIzpw6A1v8vsJlF4cBJA5HMVW6VENkoEzDxp8BQAfJ6ASJKWDwa3uf6E5fF5lFNJkTqb3CDY55aVH8foMu5sMplJ5QD8J1TOTU6NvW2sIa/PXf65/8mhManz8AJhLq7wAQAAA" + - id: "golem_picnic" + name: "Golem Picnic" + material: POPPY + currency: TOKEN + cost: 0 + rarity: RARE + item: "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" + - id: "cooler_climates" + name: "Cooler Climates" + material: PRISMARINE_SHARD + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/8Xa226jSBAG4Gv7KdZcdfMEWSm2Rha2QNwEX3sNEW8RWX727arqQ/WJQ0I0ldXEYzDfX03TkOxcrzXV9Rerbuu2UYUQfYe/Vqpgm6oWqi6wfgE3ARqLU5Kqom1tq0chl6CJai3v/Ia6xwxVa7bX2QSxbT8+r8PYUofuc41N0DQtdW/5KEAeXxDAHBPOruABGhOATjzjdYJJHXEcyAVjYGaXYJ93AdrJABndHoaaW8SHvg6Q4jFA7gS4U6cDtLkA9mgZvw7/7gW4JgNw3favAEvSsQKezr8/Adw3/sIFuKYCcJ3131KA2vDewVqa/yLhJwI0bgSiWVineBMAz6H5NE+gLz/BAtj+owBmafKvw4bGtAnLnd9Gr2Bsg3nl+hdmDWATOOGb4xZzK0GNKwkubXoFY0PT8DhqK/o6QOX2Eu5lGKAowiGI9EbrNfXfeAEae6OBEixA5fYSwp+MbmmeCYA7tlrHl3VwcdgjuQTGdwMQ+vkAfgK2hGg/mP18LGwCfRvw/eQANNznAfSFHvJR/97Fara0JoDnF0ViAJpBHW9IlrejaTrqv0mNhg7g+yrAqP4yBp8aBu2fY5vxDe/fC+D5dpgSfl2M45gIkOn/7HZzdzI6UDYAy9nGfj1i5QbA1BidBe6vCMB9GLeiZr6bAeR/5ieBm4aC/GY+AEwBr//W9q8TmJMc9e/xA5sCenlJBHBXrR0qtRhW9i3tmwDDQr/BAQh9uuk2Xgh397Ih2trzeQA8rPPNhEsPP18xhA6Aa4MXoO/jAHoBSvkD9/mp//TxYMEAXZbswcedgl4V3HztaLUmQKUvGxeAjv4Z9J+aes6HAb4qXcqytLx+out10fDoj8EJwABpfzADkKDHuH3rl5IGoL4a3ui9FOz2R1t8f+T+YP2zNfPtk3+1vuavjO+l1L550oQ3nY8BmK8XgjFd+hAN86/Mv9YpHwO0NDGs35tlq6X2B8/P8sEyR5NOQpUCfXB6xoMPAXqamS4Z823/aszPuMKfscYzqz+qGj0AUQDVvyhN+1xXfsl8FYD7sqjdLUBf78w/Bz7dpjIDMOWrAL0OYLcqXwr1fOEtADM+8c0Q8FcAZNovmd8zv6H+McDo9X/O+n+awDePx+YKnPT7yMf+U36CPzve+vbpDOefLKvE8Jc4OSX4fe376u1Vvr30PwetuwDljN9P+CP3h2m/psXJ6CZA3heu/d6ffjXzh6X9G38ovADoQ4A24PXyKyd8u7oY/5z3a3tzKIoHC6D9HgYg8IPxtxtqNf6C+7b/dM35NMqhX2Z9vP6k738u8THloPiH9Ss6yXCWI7/kfs94mH9yXf+GD/qvKuJliPi+tyX06f4zzvrD8Hy+VD3V1wtfFfC7VJhjUgfI+v2Ev6R/bP9pZfgG38Fnq0xq/KP3v+sP5GPjJoT1Rezw6Rf4/Td8tdPz9cz5cf/lln4NzyWxX0z0P+H3kT/O+hDyH6iC1U3x9JSzpv8+9uf7R7/rutuHqttNf1N87xaAH/rZAPj8MQ5dp/0b+erPrutz/Qvz9Jfz5eGg6POi/pXfUSm0uGEV6B8OxAtx8AvvPrDpkCjnLxv/P39I/+huXqm3Drr/wDfDL8Nc3/NH7P+D/I+CRqJAX+hK+0L+a2rK/5zrH3ZSvFIPauKoFx/q+80cK9u/2Kh/8J8P7Fp9/AP6P6gJ8DLHyvQf58r744z/hBX/8eCn/2X8fP/L/bn+tf94wPpnvh9y83+2f3VxrPefSV/IeAJO94+XJvPn1l/tqyHn/g0nA/Ay4+f6R97v/zzv4zm/P+AedH/cH7gKqmMl+7e8fvt49HwJAd5Wjb8QtPLe4SGAeFVvlhdvrErL09tHVeoPs5n6X+lLEmVZPp/3u74E3izv+UIKc16s/360AeL+xwU+9a98qBvdhd6ELe47XmDboU8/G43048+y+ac+cmM+JpC7nfN3rBwvlLrfG39PRf3LleOPASxfwkWU8x0P/m531AGMb/tfcPtnvpCOVyU9f88Ksgnr6+J+2P/0zz9ZHw+V9sWkjydg3f1HB5AL/C9dvn/0+heBP3f/GRAXwkUAPvK/4kr6EGAcg5//p30pzJpOVe5j/5TwvzL9C9f/uMiXZVeqxd+Of8qfDhD3v/j8j9B6B58EQ3VfgsivP+SnA3jTc938H8wTpQRCilLA6XcX4G7KDwLojxj/c+H59y4+geO/MwF24J9OcwG4v9utuv4CX59/t+btjT8VwPm7tZX2vTrNBqD9Vttb+F+b+TLjn06zAaLIy2uNzwKc7NdW/t6+yPthYYBN/a5b42/Uf4ddL+j/mIrwfnz/qd9pv0vO//2UD/xP+qdfATC/S+w01f7xZ/3Tbz86m6S7pffL+T/ktX9zrwL/NOP/cPjn/dPJ8MwvOP+7/Sdnf2ESvCv+L/h2AN6hNvDVnYBe4ePnvM/5H/j4nAFPPzt4RQ9CeM9f43+fX+BPLj68/aL4lg+sQH+nfxQJfPwxE/i8j7+2jj42UbC7SxCVt697yszwQKua65//ih13NzX5KXWnx94nfK1nj2RMDfs1k4F4SpBtXx+7YD1NVqSHI2Hf+HJYIgD5+L/MtL9jR1+WZDLgF9eOYTme/Fd0nJerJWnC+vLbTQdgWF5/+W9+i/cTmPFnh/XbfUV8cizY3rN8YgIGTU2Nd2JTPusiXvn0ryUSDH/HsyL9FX9Y1RL+pHETwRw+ON0oRKHiIePv+Hzqucf6QNO3hEDTAsbAbXtlbJYi4LW/S/uKvmICr0WH+JnioY4rzcMzxy7p00m4eKeevZ7sdQHP/CLjX5nvDcNKGvmsX/g896++/5OK+Nz0+x0/5v+mf53yL5ft/bDBKf/hBfg9PxfgF/zo/Ob94/Hx+Iv+8dd9XFcyj554YRQPzv+KnwtA/OZ+dXJ3uwv3j5EOvPUvit/IP5oEOLnhfwk/oic/wz84v7F/cX4iQ4G8mn/6S1W1uX9xfhGUfpvz2/d/uTxmivOb9F8ZH/nLf1AZGzZdTCl+7X0+7VcKv6j/Cufr4q4pzm/TvxoB6r0oAj9VANNXUW3l0wExQZGF7/SF+0LBP9rbwGcBMMT9XtynqtKF/2bwfwa2yjoAQAAA" + - id: "comfy_web" + name: "Comfy Web" + material: STRING + currency: TOKEN + cost: 0 + rarity: RARE + item: "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" + - id: "casual_christmas" + name: "Casual Christmas" + material: ENDER_PEARL + currency: TOKEN + cost: 0 + rarity: RARE + item: "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" + - id: "family_photo_christmas_edition" + name: "Family Photo (Christmas Edition)" + material: ZOMBIE_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: RARE + item: "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" + - id: "flowers_for_you" + name: "Flowers For You" + material: DANDELION + currency: TOKEN + cost: 10000 + rarity: RARE + item: "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" + - id: "lazy_spring" + name: "Lazy Spring" + material: SPRUCE_SAPLING + currency: TOKEN + cost: 10000 + rarity: RARE + item: "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" + - id: "sand_castle" + name: "Sand Castle" + material: SAND + currency: TOKEN + cost: 10000 + rarity: RARE + item: "H4sIAAAAAAAA/+3YTXajMAwA4LXUTa6QnAMzq+ZYc/bB/5Isg8F2Mn2N8toECnySDIb0+/sTvzmeb/55f/zuDjzf/Hp3fOp/c/0zLql1bd52eEXrc+NXc2L8x1a/2dZv3X50/cb7/leMvfrHNt8Xb2QCa3WPobwxJrMmxH4PxlZf1J3TMNPrJ6CWwOz6n6ser66/5v+n9T/drxE/x/Ur+729/lHVH9ev7jeu/u+r4z8qjutXorPm+53U/+cPdePS1Po3P9e/78+o/3a7vaf+29PaWyj1h+m/rf6rF9ztFv207vD8r124lxoQ/VyZ5+4uqL/sj//Fn+Qvy+LXBf9hg/hLSGBk9T6MTWBJtXnuUfg2ge3ViSm8C+mvgt/8xaYwy9+O3OAvE31R/8r5mb5vrfT549/r6xcxzX8KX0/ATOPDAJC5ZanHBN414M4mt9fyxE+Q0WNKAhiCZFDhd25//bxLYDH7fFcCuM/7BI78jgSEjwiFvwBi8PM8FK7OXn8DxCKA9GHzcRFT3zrRRxZL8MvZp993wIEf6lemvzE+tNVf8dce3x0fgK0Ax7kP8b3qr+HV5SP3MbPxE1Z893LvPTxtQO46QE7AnQWV+n0iXT5e9fM/xLp40oAd38gJgD4M9fnY4q/F///IYh/f5JtVPP7RzyrwtxL+a8SD+lCsU/rve56CtqJG7QTSgGId98XIy+V+H8p1JCRfrOnkD33e7xk+7PmcU1pymgd2eCA+KFG0v9tHenJ7RK6V/TeUFwmc5pVKi65UBgBK/5Rtr/OyepeAllbcNHUfipTO2e6DNsrW19b7FMKXkHR/xjQRndDzZ42v4T48Rk6RM/ojVV5mEM9/oO3HYsEmsLjq4aQf5AcJkoB38slHeL4A1kcUI7BTsX+XdAp7oLM+FH7R14Q/fOGqHW52gNHfrokGH5mP9tFTBVLTq3i42Z6rP2Ub1mzXntHKl6w9SPrAb/aQzjokJqoL6Uyk92W9toRENusph8IinWWK3Ez4UGB0TVosLuh0LNCY6iiwzTYfpE9GuEhL+nDRD+Hrrw0B7PJd9Uc9jr9yeD7Yyja9/hp9RKV2qucsVB/P+H4f+wo+KqWx7hedGOvrvd8bk3h2Fn5jsCeQqnIYFZ8VKyqf4YN2cFAW2CZw7FcfZio+QEGSBb6d3U3xWRdzA3U6/d2dTfFCrPiQTjtAzZdj1BqQEzj0kWTK/Ks4ivrJaLCqIPxRq7/Dzk446sGmpH4bI/2mJopNf7pfvSbinw92GFK/LIo+kckZckb/Cz9+lO/jfb3/Lf6Q/vPhbfP5Ll2+vMXJ8S/eEUEkDR2+rL5pDpWTFPxkP87pCKD4Xy4UP+zhd5vlR1pk8Crfsl9fZQuG+nSB+xv6lUP4bL855x/jD/yL/H79O76YAK7y/Ju2OGzV949A+kH6+GZfDMAAH2T72+sf4p+tf8gAXK6fJ9DtQ+BP+DSBXj/xZ3zysN73tUd5+mnyUwqdX7soT1Oo+FB8pe2YAEQ6Maean57GBoGaHx0tig0n+cM2nOR/4hOfaIt/RSPePwBAAAA=" + - id: "haunted_house" + name: "Haunted House" + material: STRING + currency: TOKEN + cost: 0 + rarity: RARE + item: "H4sIAAAAAAAA/72Zu47cOgxAm50irgfY3v8xfxHgNhp4iwHYXCDA9MH+emxLpCiJoijLXia78fihc0g97HFer1NjPnB65zU/HRPFSQ125DsVcbyteInxohKOCtBPTQRG6Ft08Qucha/RV/7QUBD5yU6dvvFPG4xSZCSZf51AQSrwcKGAkClCWfh9l+MzKsbXZQJCqSW8WaBzpQjMCZuvZV8XwHkERj6A/2H8tdNb+CjQyLyd/wrP8JMBbxEAXWBOzuN4ve/zQaik1lGGbrxR4DC/iScBpUno4G+NAXTgTQIbeTYJ7POuC48CYwUI43Dqzt4m0JgFMf2+vk8ExMT5Rpt/EC8KROQcCtDF78J7gcB64ZwHmnmcrw2Fw/j9WJY8sKmfLQJwOj4TwHSBDX1Ijqh8Az5MFL9RCLByA3IzEYW/NSZEg58LUNcD/0cbhjtcItv4mUA6+WgNqD8TTGWY6+83WWOMz8ccGdr4PPk+Pi36UYBjMzmFv/1af3r4vOApv8DzSXMOP5nzjIKr0cwNk17o4hOUbWZ8PuMhHfni/aCbn6tMhCvqDgleXoUu4NMHgGTki8uAMOnq47/KT9qmtHO8dAeIacP0C/YH8IN8uu/iDSCmn9nEmBP+dAKfoSBZhHn2/JVDwdeIAv+V8nHkY/qxC1j2Gr83Yg+nUz8b/t4FAn6u8C2R3ZoKPhAM2JwAlKrkb02XwLgR2ktWIEwWMrpU/9chevyQ5Q+x42kUsDIJcZCOO/L6Y+rRQoMzw256auA5sy8/hO4/DS7TyYAvNxDRRK+8+Bynx4OhPRRJ8FfS2QnxeUvmp/voysZTZ5MeT2IrT+U8KlKIJt9ET06sF5bXwcY309nJFb48Bip8uSdsBowvjTkTX2pb4W4NhQ0o5h7V/CU8/+y08LQVfjE+/9Tk4x2vzD58oF3s2Kl8/+ST8ZM6xFvgAP9rf10l8lMBoeKJzXw+X1vUytE4wv/z5/8tcn5jVT2Jv8Yxft/8a+R/u93qfN7l9dvQAP9D5SvD7gT+Gh8fty3Sws71Jx5Zwc6P4T9/f/9d4/svOfD85WQBigXQxBePb+QPz/e7JH723JM8ks0Z3yn54zexL5b/zgf6TylD/i/1/tPL3+vfy88XxIL/fj/WOMRfloS/NEvgCr7zeBTozH9ZDaDJjyWQ+dOKn4jvFL7PFvnLHvsxvxkMBA/wdOcc73YX+NMDvxKtu6p8wK86jI+VW2JsfLkSbo8v51DBsfo7Hp4X/qGg73oh3EJdt2RRsGfiZ7Hnv4aFf2P8/WCVLzrU+GX+LiBSgy3/W+Q7xhcFvMKi8+3h6++ezyftEvkuNTiN/9/v3+vfdSMTAEgFXK6w2PjPxnF2ZnZqUYCETyMBGEqA+V33LdoGqkDODwZQu5zt+ryfIiCORZCbSsLK5wJPm8Bi4H+a+UzAb7UNoC3QwY8CT8lga+VavjCKooBv5mK+MIx/ki8KOD/7ZX5ToI9fEVgVfohfE/hBfqUCXfxPFgpfQtUE7quBu6czEWoCSC0j55cwpQKeHyuR8PlVdX4iUOMrN06VT9cZ+U6+cakCfCRU6+/MfCkaAilfmQEjfEXg7rCdBt/1Tz+LwH3/cyUfBVoPcJfxg4CJrwoM8ZsKTT7Nw14+CugnXcg3CVzJ3+6ELQFoCYzw3dO1SnAtn43CUf4xPFUgc6Dtq/mO8ZkErUzQEiC+/auoys9MGvwn8VsT+YDAFm3+nvzKP4rXBTr4J1XAvx/BDWgNgMB3I/wogG+WHo+wpfKfO3+7U9+d8V1IGC6ywDviH8krVjV/1zH3Nvz+wC4JvDW+5UUEtqXytwJ8Csotvl3gGN+dya8paHzX4JNAa6BdxUeBgaVmjA/IP2zQ5r81/nAFBvPvmYUH+Xr+owbD+Q8qnJD/MYX4dd3z/YsTgW/Jv98hrPv4soZkDuffqRHqToEqQv7vXn5T5FnysSuk/N9H+TWDLv7DKwST9z9ADS3BAEAAAA==" + - id: "bed_breaker" + name: "Bed Breaker" + material: RED_BED + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "i_love_you" + name: "I Love You" + material: POPPY + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aW5KcIBQA0O/Jj2X1BtQN9G5kKW4/8hDuE0HoJqkaumZqgsC5INqI+bMMTT/nzzosuRDG8S6A+HtQAGNH4ddfW8//69XqN+E+jfDnqIP0RX9dn7uiv98lyX8It/snPdhvmnk9/MaLr81fXyGGbr7xaYvJ/W1/hSO0Nh3/OSRaTssn/nGXBF9QqKTl9/Vnku7yO/uUuSAtv4ufpj9nPKTli36a6EjV5r8LIOPParbip0CwLxXBvuhoPgygjy8zeqrxjcn5ue738O1dZ5zv73qj/HDTHeRfusnOv0/5Sc/P/w/5QB/oh0k4yI+XwBAfXIDDrv+h11+6BIb4xlT4lQGAijfX36//f/hVAcB6/75fcv+vCgA9Md35Zd8/Z3oV8xX+/foz+YUjsJb7Jetf4BeNAH1i1/2y9Tf0CwJgOwaaX7r+R/7tKYiPS/GP1ucPGIFtMz/2ed8/47krHvsuS3kAJL4ewFro2wi4rz6AlvrrOvPCpX7mAZgm+anTHXnum0Z/5b4vyX2jnH9T49MQWKmX5J+I3/HasH+YsBfGN8BUHwSwKr5L0D/uU7l/RRCymC+c/87+Gide3o+fAh+UVj7zfP7gvHlmpazv/vpk/zMpbpxK11/xBrDmF/Hen5b7Ia378MHmH++7v6eCcLunlzj/PvcR3lNd3Z++EkAa9Zh83jR9jY8BwNO/fOcEwBDC6Qg505f/wwNJXzz918feIZc5/GtA/08f9H/0+A84AfAD+w9v9MttNjjCu8XqaI089/EXU2//iLlGrLqz9FWf87jZdv8KwEi+xOfPWVdf5mHDj3z3onlzi2231vN5/nW0yzcGt2XCEd6yCe+u7dErI7zIDhmCv6Rl/w58kAt546O0aYsh8JauSjQj718B4Gch6G8HSlsPnw+A1n24PeJTmCe9fB+A1n3S+RBBu08HQOu+xIdz0Ms//Ds4sfsy71+Ut/lkAHj3lwzvAujm2wDqug8GIOObrI8HoLL7aQBU386oQv8MgI9am+83UrI+GgDW/SXP2wB0/9rOL/WF7t/5RvfT64S8v3AB1Mn6bpdK8c1jH9XJ+GGXrNnHAZAqlF8WWC4W7eWzKsS3WVDnvqn34cVKa+yMPwMwRvNTRr0v1iA7o6Rp4sOMGn8h73+FoSnwrwybs1f6QpOiHxYjgp8ySKH890+Vb3QfZKBCx833X4Uf2y73wQXZ6oO2YVnhco+F4KRp9MMRt+LaUslDut0EH0/aJj8ewT5oHTSw0eV6pY8rnPd/GJp/MZH0+P2Ly6AFc5XPKuChQUMPyu7CoQe+UEH2aeO7qlf4YoVdCAC0TX2mk+beqq9UEAZAaHtX9UJfrcAGAJVEvqiX+XqF7NwCyyRN7+Dvin6ADQh9mYZbe+CnAHT+oz65PMRy6jp17+Avwv4Dn6Yl/ENfaF3YAi3gn/qsdWETmD8q7rzU+/3MR80L7QoRiKUUHyexcVBMO04akgrI/vfSrz+Mnux3/zh/smmZRvvD3r+N9v35H/7+8ccOw3tEcifg5y+T1tpxAEAAAA==" + - id: "bye_bye" + name: "Bye Bye" + material: PLAYER_HEAD + texture: "f888b25e129df7bfdf9453dfbc78b33758c01992198cffdd15288dc56432a" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "tnt_drop" + name: "TNT Drop" + material: TNT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "candy_king" + name: "Candy King" + material: GOLD_INGOT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "groovy_the_ghost" + name: "Groovy the Ghost" + material: NOTE_BLOCK + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aW3LiMBCF4b3owQtiM65yFXsPEAy69FV9ZPGgfhkyIfp+Gxubyez7mjVr1qz5vbkxM1e/pkDSLwhQeLXgGM3LBUfMZwVbwHHEfGl51T8ODK/Vcc+B8+kzTQD588FDby9WTuVYAhCHPq2fBcN9Vq8DyBXi557AlwF4X+VfBUN9jU/Cj0fP/nOjJF4IOAD+bvLpQxDgO/myAOTLfO1nAeE3/9dizCuefXG7SQEBfy+g6oBjfezt0Ik0/n6hn3up/BbhWwPuwvfOddrtzc73Pv9+f/9h9EsO4b9G3H6Kb/1z7zj95gHrE5vb+O4D0OCTm8/50jvAFF/mHX6JsX4dMMiv33+KIsfZ//XZAGn3tyekcAlu7If5Of19fvsGXH4YMPJv9d7tPx81RdJdWLdP7usadgX4/WxT988OoXxTROXzT/z65drllbBjL3xU9fJD+rviG48Ddbp9VEDLGH1gQJ+PC+DWlflhftIOfnSALo0t6PcxBREf0RD1oxkgvz8CGdCTgPX9CXDfmSCt87xFGB2g8MMDNL4zwFyg8oMDCLLiL9sBuVh82LpoB9y4+Ul/+3XfFpAMAaQ6yd/qBzE/5T4XkC/6drchPhNQ+ueAfD2gXBXKNz4VUK1r9E1867cB6oYGeMKvCxSH2RGb3W8DPBcf8rV4/FXId1z8qdPBzr//uUVVLAH5mPl4QJD/vgy4ADcfuwsH+NCADj74MWS2n6I8MmCKn6J+/INo0IcF9PqogHn+f0G3zwfoN1tZwAjfE9DvswHP3WoOCPhcwOYJiPiIgJDPBGyOgJhPB/yGbysI+mSAw4/y0YC4TwV8L6+zfaUAwKsBQgOEpwJsPogXA9hnIH8v2y5P3N2M09kA+mlgmg4I3VpAAq7l+V9Oz/Ev56uCGT75P7KmBMzi/xNm6mvWrFkDmT+8vbZJAEAAAA==" + - id: "starry_veggie" + name: "Starry Veggie" + material: CARVED_PUMPKIN + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "witch_bouillon" + name: "Witch Bouillon" + material: MUSHROOM_STEW + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "fake_vampire" + name: "Fake Vampire" + material: PLAYER_HEAD + texture: "8d44756e0b4ece8d746296a3d5e297e1415f4ba17647ffe228385383d161a9" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3azZKjIBAH8GsS3yn33Ky5ePQZlCoPqan46ss3NHRDoyTZrdo+7CYz6u8PImIy09RQc1PZfVqAbjYSpNXrQh+LALY/wR1LMAynmw4b05TgEl5uheL7UYiaPd9uV/f6JuuQTYRgBJC886+3Gwhw4BwgIcoBFK/969XypnjQ67XveyVEsQvmG1V1WtduqpAg7xEOXw7w8rWHKsZt5gsBXi/U9zkWrg+9q65agBcsxF8wHwswI7wOYF/UdcxXvLx4hIDXb7X3r9eLLMlefdH+tlH+YpovxKxjwAAgxQzPgPSH4aLdi0lS8sn2L8uueQF3zAPME+VfbEFfH9E2XLXH+1IEzd8R3o2A9Dyk/R/zspIAYtZ0fAJQX6C+ChBNS+ofMNztSVfuIHsC88UrdEDo/yjA4nyEj7rBVnLBeX8YbAC4p/W3dPwtIYB+STQ/93V/IxcB4c/KDzTWAc6n+SjApdWfRXb9ww5YWnxFoP5A+tH8AweADcDyZ5Yfjb/ocLi/A7/Gu/si6fvh7yYA4UeUm3nABOA7YOH5s7knX/Lzb6dKN/+ECUjYCEY2RfsV3vpweg7ldTD/mQRVf105/kStc29++lMdA/eq+Iv1692vffkfWOq6Gci1XZ2XdD8VwGz98wNvQNZfV+XXeOeny58w+eO8mYC0jvnLvp7yAY/7ZgKKWh/5q6mlwZ9zfjBX5Q3nyQWQ56Vf5YM/Q99MPdbHdwX2sriZLzS/zZ9Jn9rX2epqWGyNqo75M/QveubD156+FG1GGojgArT5M/TN+Ks8/YjVV0jghyDLj96lw7/SellrXCCBygC3xZ5lp+QzhhCAWHaX/BX6stCZteTbCDy8zUf3R/ymivVxzPzqCDz76Rbg3TTQEKBr86E/jowA/fxxtPeeJMD3fE6Abqc/H3pHfX2lUNcLxWM+ZwAAv3axtvqMS8D79BTF8kXuO77oF6bGs/7S4jfCuZ+O/dB8xl34aJV8Xvv7+XSAD/hi/++TAd7vi72Pf/T67+Q3zwN9/faJyPn7d33x+7urz5o68G0B3uEfCFD0W/mmAP380l2YjsTwmSvM0jKA6RO8ecSZpuKjTrIOMZs697Qfvs5n8XZT3xOFIVHzp7R4rZ/854K9fU6COfCKtjy6e+SXur8tgNHS8YgfQK89lf+04rhEaz+MB/v7n2XDPxuO+CGU/9TlzHEci80Hu6P+lPvkMaT/BP7oH3xoPgRA/S19jweYUL929mEApk8EmJT/JP0Cn/1JSKJtWRGHWddtU/q2Nfrpn0Mc9qWN+xU+GdS5CHQqgDv/R/ypwaeKHn913qjf9u3hyz59+lc1AtUYPOPXy2/N9Vn8AR9EMPf/58/PUZ8dItnQvLTrX33609tv5/bbCPAn/vnzfr8zfdh/Tb7dNebddx1tfhSh1YfNd9+0aD8JkDQUAc/6gTeroNy3CjTBu3P+utIBIuUMwueTAO9B/yY/q5E4AZ/iRzMJjp/wJ9q3AU7NdbgZF+Lf7xFfmIGPoyXe+fXVfxIFfwgrrDkIP3sAZPjIQxhjL6bfcg9uLQ7/df+NAVj8+3xe898XgMl/3X9XgIwnv3/7EP9l/0F///gBXzweD9J/R4Cc/6IvhFx8F/z+AZLmS16UOqB7gISv+j0CxCuDnC+PwDMBkCUR0vyaL5ejfWyCr1wCOgB3aVWgM77Bz1bkrTCiKz741QDnnglWpFzzjX//tO+bT/jph5KdfWF9+UvjpwHUbp30PIBstOTv5nfWv6PN7WBnGXSX5/497vheKF6471v7dn9TYJwmivONejy+Z/+vf7P+AFnvTvMAQAAA" + - id: "scared" + name: "Scared" + material: PLAYER_HEAD + texture: "1f1b875de49c587e3b4023ce24d472ff27583a1f054f37e73a1154b5b5498" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3XzY6jOBAH8Fcg4oqUFyFBNK8SqS8j9aEPkfz0a+OvqnK5XAZ6e7UaayYhkPD7l20M/Xr9bX/bf6aZXw9gDkW4LLcx/QkOZhYCdJ3wSOSmrz9ld96LA/yc3zqpOTJalwb4CT770lVljD5maJ+2dQa4jv/MTePLV5U5w3d1gsLv5nUBhLPreGh99geQzq+oHWGU141AdQ6oa6+2Lp8yHj6hq32fgO6KR47zXRFoIOmojj4T4DKeCXBuHe/DuQCi31po+vkiQsPXdc+JAKJw4DbLa1W/ecPr9TubSPzAc0YP0fOc8Qv+JdHkO/5Luj4u9Ct33MYPL+APP81eNjOw3/P3zyU86YDWWdPXkM8s61IjCzAM0Cgrfyt/r7qy83Z5A6AB+EefvGWqfCsAfwMCj7XcZISDY9IfCYacUvYb3zK0gYlokIo7q3Lja+h6v9hP+XZTBRSgMzxrX+GfoCuzhApff074Mq7zv/7UE5yyVf7rmK/CWR8EWGz7Cr7d1POyaWT/Bfk9wJffKgKoZFPsUPjuxYKzb4vfTAlelbseX62hn1u+bzv58AEe4X1JbsEL3Y1A/KnuO/7hXPh/Xky6OWnoKBr+g+hb8fl4PJ+Ppw+yh1kWbdXYN2AbHRT42dqLixDmgNtAvgZPAUzcxMeE3ne88azreLvxRL6W58pW+/YycO92Y/fnpVNGKY76z/hu/YP27qcAOUndf/6+b+HFsW4AXPe78e9GmU2j9Bd3/Tl+b4vzTxQNdmn8ea9+hxf3fznm+wDp8iO87Nvu9ve9JV6IR4bfxOvfv5m2P45jDJDvhY/Z+lVk+wCND5AbOIZhv28cY4A5BnBDMFdn37Yhnvo0ATxC6MQPw34D2u+57p9f/f3x222kfMMHa3Dh028G3gVYwk0vbPjyR+vfiN72y5W/0hLvE8RHkDnzJIDS17UR8oN1bosPYV8GwLO+e903T/LID83ywxAOu895BkT//U6v11QP+ZvfE4/DDrjaH+p+Psz458df4G/7gXTcvmP/4yo/6SMu3x3Kh8H1D8t/v986/54a9cFAU5/lgf9+f3/7ACq58OPcDv6g4qH/bVvdpzLrh7mWMM7Hp237PFz4Y+5zPBMcD+YmKQuM/xuN/71FM/6N80OPh10Mzlx+bVjw6YWIB5z6TlxTkG1W09gHPFt+jfelr7aFT+d9Wj4dcmbo19g+OgNA30/3Yh1U8B+ARwG2ze5U+WnNLbtf0Jnyoe++YAdG48cAn4VP5XTmsnwSYOvx9wThQqv6qDKG9/4H/M4qBig7Fi51dum5Dezv0GUP/M198gESf8BPS9+N97eKH8UV8g0f74Dl+wuyVT0qP5t5U7wAaKPlsx0glR+GXFW97Md7cKMDaPl+zp+oPvuj3AGlH3tmPcbfCV/1YQDIl/4BPj1jxjtCh58WprP8cB+lDuAGYNvAIZGfBD1O/nuuv3EFwPLzMYnnfMrfQVf0+XeRn1yr8gPi6z4zANsGD1b4aQI+CMJWL/BMB2yKhWaC/lT4g7r8sv4WP8HG+4AHO+p8fuTdFzy9nz+nw/CWHwOV5UcEL//+CThBpUvLn8hE2EGoV7p/gy08a/i3XD4+7cQ3PBFQgD1ctXzc8gAwfoWmHYEDpH0qH4TYFB6TCY/VkPdNYUbAIWX5GKCt8p1C5wq4OOKn+J1DfmtQCh73FFil1lXyKwHAyQV/ogHyYXAS+Iiz5c26D8+dhXItiP3Dl4D88hmzGiCSmS76WWZ5v3zc4/07csGuJlZLQPiJmYGk1PzrfJp2pbUj9hXomQ9LISxanE4CreigoAMed4D8axHWBfAN86u7C3XLsg8GUub9gBzl2YfR8tr5GZ4pnc3R5NdDPPOsIPt+8zKevV7QjnwEdtBVvOjnj2WfXMRnixtlJiIJcJbPbNXn+fg3xklemdBPBJLlguqPhUntX+dJCDsE/av9hRF+x/5ftX8AD1oEjABAAAA=" + - id: "garlic" + name: "Garlic" + material: PLAYER_HEAD + texture: "8d44756e0b4ece8d746296a3d5e297e1415f4ba17647ffe228385383d161a9" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aS3LjOAwA0C0pb5RRdR8gK7u88CUUX0EXMNX3v8EQAD8A/1Kc6k2jalKTxPEDQYqE5P7z51/8i3rcIP4yf72+huOd+Ovl+AP+m9IA9kX+9Yz/jTxe3r2/rj5O+4fyCK+mYd/v7/O7SYgXurK/269lkb3EzXoswDt9mQX70e80gv9+PmRRxV38rN/Cf7n4cb6p2/i7+g/7Xf2IP2N8xDjh/8piGE7woQR6+Ihf1Y/5RbzvN/SBBHp4L4GAL8vyfJ70W3jbj7jVKQ77Hb3l5/pRv4s3fF75v+CXBp/6Pf4bvuefafAr4Rlfv21v9UulD75LAb77Gb86eF6C54/5HZ5H5E/7two/oP+gP8SvK/NLCQz5SQLIDw1+Df72Pn949CuEU7/jX28ZPzj44G9bngB+O8JfeQFG+XVl/lbwt0H/KvxBfl2jvwWeJ7Cd8sf4dRU+D86P+HQDJPxD/OMhf5cuh7Z+97dgB3iG2+9S32fha9HS8R4cg/lHeeGz73q+vweHeA3zUm/5z6YfnvzABLDFP8x7T5ZffL/WfPi5f/Jzd0+Choaf6MC1/LXg+6EyPjx/6/hx8K8KLxPIfbY7HfeDboyJWKMAeDgVaMZ7/9r3Az8zPykB/YD/watg8+Hf2QPA5sUfdODrPkvA+QXcBu0698yvJuD5bYv+ExpB5lMywi/2RD6BO/eNae/98G7LnPn/yeEP+68XbHvhCRi8addf0N+qvihG17/SM9C79BsJLAVfhEjmGZqDSlDltb4P+ov3N7MN+OuYrzSWIPqtBGbyt4ovYtifbjdjRvwn+PMx31RwY9zGo9TkE5i7CdhfmiP+VvZR8zsQJjDoPzNfnkdDPhXb+ONX2RmYON8ugDHRX0XkvC1/5hvDfdh/lK2AVmrIfzLfvv/n5+eDIsug6BsW5N/Q15OdBK31QALoE/B4BB7iU2Tg/K2iYwI4fLwG9GQnQYUEBnzgE//zkyWQ+SYL3P+veA1Y3dZAqbl/5+19MoUP0yD9cP3nujFw5XsfZkBHv5OAG37uhwRW4Zd0Y+DCx8+gLpSA1kP+E/0HjxlOnkfNL+vmppX/FI6WYBx/O4HMxz9xxeA+3oNUdFt+5fz73RbAZuDeiPxmAviV8XAy+Qsx8Vu8cjvA7YIJDPtPtv+CTyejS0CWv+4TTw3oBRJgfP7QsxexANIfGr5dgTbmWfrHEpDR9WG1heHb4/9yMfOhBKrnTvxtvfyw2YXhy/Zn1P+qHTzN4U+wycC1pvDiy9tP4bcS+MKoHH8VH4et3Vfl7vxbfiOBrywBloX3izyO3v6vwcNv8t3fOb+Ug4/EpxPO10BRB2Z3ff/7uZBAYwJ4BsUUsFGOKdC44xQ4X00tv38NfsmQPlsBcMQHHjd7718zHnazUb+URcX3c49ZkA9Hz2HfffLSTsL/MM6+5G05fP9d9OsLIH7206pF0Q8rEL84X8FaSPyl6vMPvzqTIvzIu3VoC0/tP+1GShf9NAH54d8BX6uUV3dq/ydqflVsP+sTkH76e8znkw++DTiHJ2x+ef9b8/OPn4d9pcLw6SpUF3v42K2PWq9JNOCVBZDz/RTC/qMYD6O/uJMXZ8P93CewxAL0/Y+42Fu+UQ/BRz+MHv5LJ6DPYwbVHNgBYJsjQpB3vlKTKwCukIafs/BKlkExidSnuJDv7v+xAC6Bk/5Hae9LfFyFXr/YXiTee0EB+B1IXIDN6vMEZAohTJYA6bAhkk/r36+LOVmAzcmfZQKlDEwtbNnt9b8r5e5+tY48m4C+L/9ZzKCPy5DWn0tAnfAHMijzuBlS56/c8wdx/5X5Fb6YgEhCllzDsxa7zhUef3TngUvS/uZxyq8l4FPgOtQccpji8H0Ck5pFJBdgnW9lADlIXiOPh42iDyDw1otNfNFv8j6Bcgas9m7zo8tNhX/7uqc3f4d9n0Apg5TX/qzdr5TDbiPV0wOo59PLiym4yw2vbs9jJ7Dfh/0e/0FH9VzKwV9vGuedDlnM4watl92ASvw5n6cQcvDbLjT/1P64E/AGWw/yRX+OfpeXOcipCNu+0r77wn0eig+z0Cj/MV+kgH+f+IoWgRu+83Wj/CW/cpXlScj6G8drdwnCKUiHr10VzelfEr7ruxRyn2oAGxD1X+7BJ2zIGOXhp/4AL8L5u+PdzQY0AXT4qzA1ujj8hb/Z2PALPqwye77QAlB++NdYFH738U5/Djz4friw4+KHr35KWOub8N/w8c0CD8Hav8u+uw8flL8lEX6F7/j5Uhb+zvR9d88f3J3PlPc+b/L3nSfg9X23e/DtQgng/pxcgSf4NIUPWH97JTQ8AYVH/3b6Q+vjds+l4i8VtB5Vfp+cDxuz95fET/nD/lznsQeh7kve+JeHP58Yvv2TavWpBZLNl9j4CvxBf677+ARu9+2n5EvVdz8+zJd96kLynrMz+Yd496ZFXWMjnrXcsvr56I/4c9XXvgdTJb4294eGz962WHxshWTT75qW2r5zkl+W0tLz/CXhlyY/6Cc1zX3leeZLPn+/YT6d0ZLvmlEV7noWGWV+xM/0km8zoE7A+z19kM9Wc9WHXqTCl95yhC/jNb/y2qLe5eckZDnbfF9v8imdLaWSX3l1Q0/5nK3gNv4HQTiZcgBAAAA=" + - id: "witch_please" + name: "Witch Please" + material: PLAYER_HEAD + texture: "2e139130d7efd41fbad53735f64f8aff265bd7c54977189c02babbec4b0d07b" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "mob_party" + name: "Mob Party" + material: WITHER_SKELETON_SKULL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "festive_harbinger" + name: "Festive Harbinger" + material: IRON_HOE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/93aObKjOhQG4C24egVXymARDomgqyD0EggJHHj1T2g+g4QEsq/7naDbvmX0/WgCD8PwxSV9CVWf939UeV58PsOPKSFCgE/3go/wywnErydwEfSE+JUEMqpfCfDTdin8VVUZAE2Dvu/PwraKj/kBCcwgKL5fT8K1fjwGvvq+K/YtuJz2fRfEAdZifzL8azntc10Az/9PVMSf9gTjMl7wdYDHzyNMARn8P7iIP01Xxt8EeKgAjwfdDImOE0xsgFp/0OdPArA6TDBNXIJqf9A8DJDU4wDTxCWo94fHAwXI8WyA6ZI/KDoKkNejAF3HBDjja9YEkKDSAfRS7ZgEZ/k9AOaTGdz5kwTjeN5XARiejaAPc10QJRjP+H7kkz4TwO2WsA+UXz8CfvIn+SjBDS+COMGo/dpJsB++BxhyvktA/JBA4eq/+nWgrvkqwL7rZX2zLm9MAJdAV9VWtOxl/Ef4QyjgC+PfqB8ngLuxzKYIUMfyIILZmrwPAtiZuD8MsPpHvqRMBwjIPM8p3ydI+/YF5onlX3LfDNR/Y3IkFuKzfCoA5m0C44/GldIuCCYB5HUA/eT5jG3zzPEqAOiAeH4M8fnbFG49/mW2Jd38tm3Bt+AT8E/bBW6T5CdAKHw/YnMkT18lmCP/yfuLOO+P7K4cIS4Ae/pPFzME4Hw/ApyeOX3d+6YLNm703dPNB6g6f6OPkry/RJNv20MsmTrnj8X+duz7AKW+sdW+BFeI8c2Yz5ubfxv1tRZ4l6DQHz3f4TWqag5lR38zItTdH6r9MeK5l82o97UfgeahRP527Ov7sFhn+SX0thuFzW600fsA02nVPtB5fokCLDYA8aX3N97Hkwr4ad1OfhzA+/ZyI3k/rD9mWns/o9PLHPQl8Tfo2wDMrFbV7b7XuVeQlaZ4Mx7x6Uuu+1WAW7gA8L4rcmUc7CN31aP+Enc/798i3wYQnC/58t0Pp1/aXyBvfBBAMD4/7nD2bRE/Lz4A7P4F+TfoC71cUPt5fUDzb3a+DQBOH/POdwHMOj3ycr7bhEOXBH9ZsH+Dvrjqh4uAkxZS3Onr8vtUrd9R3gZgEsT8th/t+OE031Hd+WBhEB+3dEbXK4TyIQHsghx/rvp9gVIdBNhciDfw2u84PwwCHPWG+oE/L6jewBu/NICpVvrO5zsgkaCprwMMyQBshJa8DjDkAjBBmvrmW6aCALbUamzL22+5KgK08NcV8uUBmvjrXtAvTdDCX23h7xg/7a/4O85P+8w3fO/xe1A5/ygB56+g9RJ+SPMHCY59EqAn/A6n+f19UZqn/rpmA3B9n5JDgEQG9vRxgEO+zOcypPxkAH7mFfswA3//sWYC8PyRn7jzyvH8FEjwB37qrjvrswHi70O6tdAntxxlPrC6z/trI5/ecpXxjXzmlq+13zcuxh++wx++0kdL5XLV+o1513Sp357/X/kvUA19bp4kXVro5f4nD77haj80cWSTBPsng1d9GRqp9KU88IcC330SXex3zIEX/PiT8bLzRx+ho4a57j8a/7f73AIMf7jk44b/Pf9a/+N2/xkfL8DL8+/r/IH34QDI7/T3X3rEj59JX17yQzNCCI9BMPzxA/5x4V9ltvOLAoiET7a1Sp/rADwOp/3kBiRBAIYnAdr6oC3B8Qe+ENd80BjrowDw7AXyu6b+/rYX+wk+O/2xD1pI++Z994EPnp/xoyZqfXHK73ATvhk01fYBIPMPHwt8edoX3P7DrX82eJWPRzATgBY5SqYCvMcXuKp9dECgT/kSV60fXXhK/SgH4RM+9zskx0eNF/lxT1BfVvqg9fthgbgcL1l+KOITfviNi/LB6zlfVvl3LsAtXXg8Kn0y+ncUIENz/OueClDmy3tdAMLfmQBV/Y8CHJz/jfDUr+h/M9wVPAxgJ8uZ/retoQDHfJwgnqwp/z88XPiJAEAAAA==" + - id: "sleep_well" + name: "Sleep Well" + material: RED_BED + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "snowball_spammer" + name: "Snowball Spammer" + material: SNOWBALL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "puppy_surprise" + name: "Puppy Surprise" + material: BONE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "sniper_snowball" + name: "Sniper Snowball" + material: SNOWBALL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "wrong_eggs" + name: "Wrong Eggs" + material: EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3abXKkIBAG4KsE7jHeQW8y/vAHZc3ZV767m24FwUltVbo2m+iYPC+IDJoY81d/9Vd/9b/Xx9Y3uQJnE6y+xvPQ+nykAGuqB/wP2rjwhwZA2KfKV7ZG+5/SxwG8rY9SJIA+vtbf8LUvhQNo7T+G+fu++8/4yORr6h91uwNQazNb+Ifh/G0jAY4t9+95P/HQT30ywjfQx92PfJ38fEqG+uXpZ3wF9EH+7oYfw5tD3rSGoFJo66aPLwBzjP3d76PHuaYbM02ZZC/HPj/vKvwwxLMP9Y4JMfA72VMcF3jYfgXqtr8X/k62fcuP/6cJTcEDcNHf92in2cVOQd5XJEEPH5sLx7ubg/2Xyjc3DnX/9kd7oM93gx75cBNcZ6HndXEGOn1z4guX/FjfYB5UwJL3kC8VxrH/er3Wx/w4AdArLfIHPtmrcZokX99fk8A3YsP7k6vgC3ybj+a80oc/FwVgeX+GWvkcAPn+w9dxzrEvt75tVOA5sJgRAv6aVuRP/L2AVs0LEjLnc7wJTcYdIPitg49vMePbc37h31qOtvh5i29+z6VXEyBuRK/wn+HN6aAT/fe4e1bvl2D8HAY9HPvrav33mAi8Httr3ytogPXt64EnF+DNGWySQ97ZbwqwSMUFANuKBGj2RZjNUbaYzLvvd1q4Xfi18LLMtsSfA320cFyleaENDnXemMijNUvhNzZ5pv7VRCP7HXD25XkvrBhE3z1LugnLvkqA8h8Fj/xQrTDwUQC/VM2GYprP+TlFpQx8nVrrpwL8KIj6xx18iFr669qko/GHnsSAhgY/PrjwDxDSfWSTX74KRznj2wix/SFA8NN00OQXr4NONryvGT+ejUZ/sQmk9ueTzQZIvtZNPtzhBic+gvE1vFPXxS1rq+8viCUmEPofD3aV7hZ13qHzSi0+s6rxfQBpYpD8oqjvItacf+ev0rzU6ruVm44dU3MBuknp2N3vh7sFsLPGjwF8Ardn29p9F8EugeCjhCrfXfbrnF/bthygrf12AeaGf5uPa9tAANb/ufBd++3RFz7o58LfKvwf6scJIa4Oz33Yzy2+Ca5B/WB73c89eYHABeD7ucGPg8AQX+fHhk/6Jq278Gj07tTqlwFOfflqSNf/Mf+kA77o2wDrgb/gzesdf673aQfYn/8KGSR/rfPnKt9VmHLz+23ug1v+fDL/8f7q7/oAEjrgng+qxjfxYQ12vuuvVDNXvjgBtvr2WZE/35S/egO4rjoePrBC/ukFOMZPOjIN+LrKF0ZDBf8iPKpaf7vp+99QiHytv3X4tsSnPnW+yFeN/8MXX6v13Ss3/bNifCaA5e3q97f8eXNr/wfaXz8AMO8WMdbvjdBwARDdB+jtg0ofVV5K95+Fej+LugjQkaDWByLjj+wCquI+x/6QAEb0S1IJfufvNWbOBwj6K6Mn/HkufKik+yfR7wqQfggMABngogBqqB8SlDxBwe7BPjgPGgdgwtg+Ge/HBLIP/xQkf8sQ3z1jcryq8kHiTh/+8sH5/CNTqfVDfZuAXGeqxDE/1j+KPjRSjAwH7GjfJUDNnrlK01afz/8iTGgxoz/j5wjg+khDBOr9vhTgpMb6NwIsY/x4Inv8vubHU3k3QI+O3/0bI4zgsd+WwH/DWL8hQjy426cBajLAox7wz0PQ1x/yr2r55QDLkABD/I4A9L3sFt/r3wmwDA3QnmCw35qAXpQDArQkKFZtI/yGDOWycZBflYAuyEZ2wHWEeNRz/kkIcAD2/wEcK+C8AEAAAA==" + - id: "egg_surprise" + name: "Egg Surprise" + material: PLAYER_HEAD + texture: "1ccd53b8d9e8f463bc1f06fc1a367b624c21ef93695a4071f269d8bc779d" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aS46kOBQF0BGxkNwBw9qAZ0iW59Q6Qo7NV4Ad9rN9rz98olulelJ3kU7gXH4Gk/z+/a/+1YFaRf2H9JdjMPoLIdr0bSFG6MtDHMOvSXDCviDEFXorgVJ36/UEytWtei2BCnUjXomgZN2pkwRKZQnu02EAldetfhmh8O9PsDb8ryaA/hcDYP/+AGvdV48vJSD6u8hSpqwzCQhOAszzDPxahCkUDkD1MsAcKqFDaw2nGSieB5i7qqpPy1LxH6AGdZmh1De/SFDBH4/PdSj3cqP86YD0nc8TUHvTXUdQHumq7YrzaQKGP0JPlJ7oHTRLsKAAdfxd+HrrKsovU9VX1/BpgoSPV2IVP8uLABkfAtTwMV7XEiyFP+U+6ImHNlXXApS8D0Dt4Z2vNU5ANt8HwDLjo1Bo2hUMgPk9wAgv1l9qOm+KU4zfAhzjSy20iFlggMO+LjcfBGoFyPpE6mO+9EGLaCoC5H0y8wmvS4w3JQeM+BPmH4TXpVW2WWvLI2YwD/1H5P2qbM3fW6UOA2C+9Pf+KOhuVdY+tzWtq0Z6qCn6NvpLCAD4qaAFH/3n86m3R5G2b60IoGUAyE+FHf3Pit7/ffz1s84V8dOkn9bKBM73AaCP7v9Sd/X21f4s9rF6fBv85QL/6R5GP34MECa3MyzzrdwBiF+6eOGv3sT+e7Z0QdvYAcwveX8Agh8PxWey4k8T9hfiK7T53F8jn/vWnRjYXwrf9b2q4q8fc4289MEOmHyAhh/7fuarA771/lT62wlL7j/w8McdkPur8MsdQPxl3M92QDLXQncAuvAO+W5ArHUuZLNmbTW+23ddNIflvHlbhR/w2/bIDljG/D6c+CDAcpcP+yDOd/rdvIWXAOeJf3jz31TTT4Yjf58PAlD9+/5y0n+9cvH1km2Op37OQz/t55LVvV4pV7TA42+ZvhTP/+5WzPzXKw+Qt+x+zlNfPv/Lx5B06bBGB0kub8Gbb9nW4+ffmu//Fb78Bdl8DXXuZw+gwi9WbdPfMJ/ofb4d8OHu34ZgCO/3e3sAvPm5L/oD5uMDUCm3BN78fQiKdOirYgDU5xs2p/CLO3Equ4LjvzbPfO3eQdTH37KCH1KE1f6Q8q9JyOZrOvzlvgn71AWo6T8/pu3jAJ2+m2j5JuH9wvqwL1+C7FMtPvFN9CvvPyj/Xjp5BxR9YySc+PKs9T+GzccBKr4pfPtrK2O2/0d/a6n65ozvzwM34XgXwGcxv6RvEt6/gLnOt94SvEn4GMD/KPheP/9jnpWr9pNNP/wc/bnD33pB8id2uStM5ME8qR+mZhQA9P81P0xS36S8qG6fB4hFeerP/X5PALKR/DeX+4PJLvZr0Qjf758McMpXt/gz8VH/c4M/D/oXB5iZj8af9IuKs/yQf2GAmfl4/F35puSUnvl0/F/9quWEPu6fTzATPwyGGv65APOMfTEUbPknEuS699NxcNs/mKDUdz9/CdDjjwdA+MaXLyG6/LEEGH8XegnS6XdHoDj2Qf/vbsAHItRo6Pv7r1fTB4BaDbLEZ/f/x2NglUNV6uzv37fw8Csc7N8RAH8CgvxbAhg8/mP+xQEM4bl/bYAeP3YB45dWB9///kcduLab+iH/kgDmhH8+gqny5PszdVEAuZrD/uEI6TrO+EcimB6+3x+JgBYe82vf/g7TF/swR2tmwlP/9Jfn/y+f8dMfwe5p9gBAAAA=" + - id: "golden_egg" + name: "Golden Egg" + material: PLAYER_HEAD + texture: "17daff4239e560f7f53b1ccbcebc614f0ddf3581a6fad5bd81567291ecf4571" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3ZwW6jMBAG4CvZy16MuHPNExQpHPMslfYeifDyiwHjGdszHhsDu21HqjZLmvl+25hC++tXkWqTDjNvlA1AMW1xP0yVZ9ICfCc/hJ27KH7jk+fEay2dklK+0/xk3gvgz8fBJ2TEP3474AAt894ZASKrcYzfgtf4nTN8GADPxUnXQsI/iwcBUJITfxIYDAYpwdd0ub72WsPm84zIZVhkEONQlwpgK4VWZPtWf00lCJDNK8y/bIEca0knIJt/4fLmw8ux11fQf/lFrMuWYz+vOJ4KYCPAnZccQEE/yNMBnAg557+S+EwAPsPtFkS3w0oh34Lzp4UBbrqYCKHCvHL45ZNd14kCmJ7cWrhBMK9CvPa7fT4U8THMYx/wogAEP4RnfonA+FAHAWK+N/iBCECNHw2/69wAkQVYpxYF6HN8NPsBv9kK+tvKogmgA8T95/OJArg6SGAW1frvdQKYGbjdgv7HOvi23QIAv2ncAPoL8GuA9xKgZwOQ/mQ+Z/8Z8xt9pEY7beGXAD0bgPK1+VyK8G0QfRBvdOPHA+T68EyYedh0dmd/WP1Hkv/6WBbd8uj886qZ7gAIPxaA8G0Awf7XPPZb6w9iX0H/o0PF+m3bIP+N/CVAmu8GYK+/y20g7fezTwRQ4QXQAUyE6QXnr3ehjK8DPIgAlL8EWEvAE/579qcAlO+egIEA25GQv92C247DEPAlC4D9NcFLxtP+OLIT4Prk7WfIBw8g2AcXgHEJIPYT7n/hc9jWsNdbTp8CyNcBhD4RIDD7sKzfD23YDwZwNwARIKLzvg7wICYg5EefP2P+2/iD8afRtwk+8fwNyn0GR/5g/XHzU8Y/1e+5BCP3/PFS/6H9Afl9YT/0exjkj3k+CpA//n7yh/kCRH+X0N/+593v0/5j8kfqu7xHYcq/z+XydADkkyn9CQj7d1MuH/X1a8b3AhT2Vaof3gCkH+mr9vlbgLDPtK1Nrwi/w+e6zn1Nh3K+wLV9VWE/vuaorxL5Hk/4gSd8vlQ533/Al/N7fe/hXhjA38LpftA+yyfxE3zOPtiP0TIfnULi009kC3x0Bivur1SbX+kq4iu32KtfBWu/7+GxEyDLF8ICvyriMzgfoMryo+BX9iUTLg6Q6svWW+xXaX6W3pbyM8deaPzrJ+45POG7OuMb/V7Q93nKt3oe70YIyIxfAz7T33qRMukbPXvgMpnwd+nSUZN+nc2DJmLc9fN1lWM7/g599VNx6Ne7eJWFW9/qTZPl5+mrD/ULfKSf7jt6np/LV7XHX+ODfXiBj64DZ/KV+el4pV9d6i//XuWbutqvfvx/xc8I8AX8XQtwsV+C/1b+51ahAGX9T7bK+rxV1k+38v0ylsw/zvqpn7q4/rh1QMukKtvt/6u/inN8MQBAAAA=" + - id: "dogs_of_wisdom" + name: "Dogs of Wisdom" + material: BONE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3bTXbjIAwA4KvAOjfogqWvMPfw0qcf/2AQQgYEEs57LYuOxyZ8AgRxE3fbsrKWTq3CJbe+0I/VpPlGX42nxhqfO2sNQ24v/t+Kj/FVoOennsoP/op9gYF3jqIpPzszBt/688WGyR/mS1fLs6/OT/DLl4v+uN7tS9DNfrK9gzyc5K9r7PUGzgutvrLvf4ReJ1Mi4NcCSPY3lIESPG//0fBL229x/xfifQh0exO67yNYyRYL3de42Sn6+IS4TwSA/Cwc6QAqPtwPVXzcKjn+GnLd11M1fGu7eNLvMK3tCICwOD40LT+AM7GpkDi+hceMAJ4mmcujUsby0h7wk2+qAbBwVvZ53hR9Xs+5429MGsR9KeMbG+X5u26OCM4faQA24Rub7PBtHIbUPw/ZWTaY/+l67PNbq1r7+Xj0E46m+ceIf35u/+eDR+A65PuN9Y6M+8D+4wCuQ/Y20173yTcG+HcECj6Zf/uwmPQqd/23VQMLHvkxurOK4H6fBkDy6QI4gpF9y4nFz/pzAOdorPQHmjI8yvpr8tH80wGMh+BBnHu4gloAhL/zy5L5mgEY8LZz8Qu8DNJBPgCUc5e+LGDyDVwN8gsBJ95y+TZeMwbfDSkkoc/5xfN7p9d7UmA60kGMBrCXHd3cAngbb0YeX6TjGwP90osEByD4xoCbseOKe/yYSXICjNmbccYkb0h7w+4uz7isD9fD0fTtp5jwCjjWwOmj7SAEQG08wr41+c3AdgVQ0YX8ZCOCA1DlB/29gXwbBgOg658NBDhuxHP8LeHf9Q3wj5yPCVhZA0J86LVLFr3LtwApPpl857cfB8rWsvwG+aTTgb83HkV+87wBY27hQLdsfd08IMCgWyxqbb2JgaacUQR0FMIEnbyP5vO9+sNHeVxfmL8ieK/7VwATfAbx53+v38v/+SKl8vSDtl97+kI7gJf9EX7cLz344QnFAOjfxxEg7ru0VLpfWZ3afvXj90G+3nqlBjcAjt725VOfX232brqxGrf3kn5zBEye8d1nvOEt3PkxddZ3r/Xfe1Ym7gNorluMgIN2F0eH0N9g16t5+1uN74heiu9/yExEH/CHy+zM/Q4/cNNX7iUF7x0/grN9zL3nU8/7TvUxP9cnH/eex5N/2Tbdh2cn6Gn2hzlYw18+zPHv/8An9CaOfxxvlAwT/BAElYHz6Jd8xP02P+Ne9amA9vJPC84ef8DDr9b/u+3y7Gv6GCe7r+A/d1bp2cAH/h2/ONdf6P8HlupVmwBAAAA=" + - id: "peaceful" + name: "Peaceful" + material: DANDELION + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "H4sIAAAAAAAA/+3aW47jKhAA0C2EDXkVSPnsLZTwhyWkzt36BQw2FA8DLnCPlEqPkinGnCpDnEcP59/4xoMhXXB0PyejbrYO+2h2xtbiHs3PmFrC+7mZR7o+M4+s+pmZsMdLGWGCebczgJMEeFOmIZbMg+DHmeoONYGAEqTvmB8WB3WUt1TdvOR2MpGAWJxlrxe87L+n8k0/atoXwwXo0lTej2AFTBXd4U2yn+pQ0rbWGC6LBX53AcEkeYihZcH99xaAJslAFf3T+Df67yogmqS/fxK/vX+g8Y9ZGvsHqv6hq3/InP9PITLn3139Gvo3Zy21/0t84Pv7X8+WhiAq6wXH9ZfM36+/EF5/9zZBX+/98J5+ietfkU8W4L38svDy+3J94rJsCfZdEu/17Zt7fqx+6oUWbYHzya/aZupo1sJj305wAdmh4I856wzUrclHBbgJMkRS9/Zc5F/yGZ8XqagUt+ewf83nfB5MnmG9NbHHq8Pb2scFnBN4W0AEmyxVzXE4h0Ye++cEWSer4+jwg8hAP1L6SfyMb+NLBWDn5/DDGOeH0eZX8h3+svjZZUkf/VsbWR87P25ALG5IPYDM/rvvC/Ad4Q8AW0yoFyR0xSX0mZocdoeB36b62/6jCxnpO8L8/Cn/TI9c/6DRpM/FSF/wrM/3Emb4Anjoixq/uoBK33/+cevrl0M+ztdTC+vzv+Vz5/ORPnc+T/r8yn9f0O8Kn1/5udDzm0jK51BpjrTPzbukCt8xuIYge+1bEI9U+GcBb2wfmSo/OVKOu9vvCprmd8bX//pnvBOPxvq4gPSl6JeXPsL1hf20Vnf+1/KHyF5diLXJJ6tA9Po0BYjB/nZxu+GLy8m3hvY7/IozUN9+te8XcH0C6vn6aFmBcpR8823DhS8u5t+q28/4ySL8HUDVfsn/ZPmKE1Dr7wVIKa35G3zrk+MpfPe1mf3iJul/pEzp93zHywr/o4cincLP9B+fAB0jfJHx94h9OdUPC/DXa5Dv3P9QAbP6j3xbwej1X/K+qSD2JaW/FPrXEe9/sxHu+f58xf5T/v3+w63c7N9ff/Qbi+m+KPiogL/hRwV8fQJfPuPDwctOH+7wG5wF9Plw1/f/72KLL0l8VAD21UedjG8XDAh8iHxpfoMWvOM2GdS/PvYmjwpo8Hedxj9KqPYBiPijABNVvn/AaH9P5/37fLIA58OFT8EHBTzib50+kZ7wZY1Pxqf9k0/660rnb82+fm4Q+tsa+WvJX8l9VMB+8cn56wA/KGAN+NB3V0TC/Wd853mCX8C6+94QNY8DQj8aGupDGKkxQh83CImIhij9nvhXfHdNkRu6n5NRN1uHfTQ7Y2txj+ZnTC3h/dzMI12fmUdW/cxM2OOlzPaNbzwY/wMcdQRZAEAAAA==" + - id: "smug_pig" + name: "Smug Pig" + material: PLAYER_HEAD + texture: "e239dc5e1bacd518f8b2a2fef515c6a4badeb2c64539313b5fe26f0b899906a" + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "H4sIAAAAAAAA/+3ZS66rMAwG4K1UdITYQ0aILXQLZVrpMsjqL4+EvJzERnY4UmupOlVV8v0x4XW6LL/y659wGeH8k/jC06thP/+L/CtfEPXBQ4LVDwBhrFo//7v9b6+7+//zf36u1Fm3+Cos+Ev6qAY+GEG7auDrqKJPRP3YBvwrCVA+ZIM+PQHCz+lbgPQjbr+ggz4xwF/39bCW4A6onP/W8YYhiTDYAnwaX/Ett74AHmwAo+/OboMeVMAfoXR6CBJ5pL9Dx2qMd0cYgMoXfZ0o0OHgfUbWsb4CMCAArx/wyr5S/0xwgS/4GvYzAa7epGB98H3YAkHfXYkKJ2ReP+6vrl4Oj+2mScD3+pDlteEF/XIZ/k5/utefppHNpwcwPoln9kdGnxpg2/VkntvfGkBaAsjrb71G448jaSfw+aObPqED6Pufuj96PI9PCGBaf2zG1H9CgGjObD4ywdFz7vs/dADDMz9/owNMpw8FyHyM9ysJJo8HJFXuCvL/bxX75FOMx198Quuu2092AJ9qPL65tpvqthoBHAhQXpYE36tndxSg+9z+Vn2YfDffp/XXBMCqsJvYZ8bSkwnFH53/LPk2wPnQyuO7y5vnd+BxsW+xzfwDrchL/nJe3cdx9R975fyNPFr/+fD5k+Odnw2g7d5n8l0A59caUNv7VP/c/Z6fD7Dw+ovnPx7oAOUxZf3KyY/oL4CfBjgfkc0KYPRzAWLff0qvjMjid6GvGvj5AKFfG5H4+5+54FUagJ79JV/vfmkJ4nmqv91yaR01IBsAMSDZPwrXADkf1QDMgNTfn/+QXwuAGu+qHzUACiDuVxqA9V+U0n6AcgNI49IDVBvQ1k8CyPD5HRAHaOGXGiDulxsgxEd+EqClX2yAvK8U1IBOlncB1P1+PoAcX/bNEhTkAz9ZgaYBDXxlfSCAJO/87f0N/stOf397R4CXnT7YgIe87ye5pQFeALgB7QKg/H6rGwM09pMAkj6iAX1rPwog69cb0N4PAvQN/FIAab/SAHEe9F2Ag58F/VIDzOwb+ivmAvTN/KfjTYLeq1nU9xrQgzU38J85f56leRcAxhv5mam38F+BPs8hLsKH57TMtAUnH5xWm+ueGPJt9Kjhif7eS3TZFXTDv9+Ycf4DqutIuQBAAAA=" + - id: "earth_pig" + name: "Earth Pig" + material: PLAYER_HEAD + texture: "b1dd4fe4a429abd665dfdb3e21321d6efa6a6b5e7b956db9c5d59c9efab25" + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "H4sIAAAAAAAA/+2bvZLjIAyA38J1irxEGk8KDxXjIuMHSOc+TWby9AeYHwkECOzEW5xuZzfJOXwfQsiO9+75RLF2x/Og6Dc4RmEH/3yBQxT+Cxwn8DmBf3oG6CHbUnF6Bn7UCMoHf1+Af6we9qXiYeJAPvvg1yvwaw7lkUItNtkC+qsi0MTnCij8wuQXh/x8vEDjeln+Yvj9JRDPnytw07Hx9VqoJ30CKZ8ncFtu6uuxZUGlQNvoN6tcpNngTSmTgRt5rAYvj8DftoGhU6vRJMA59AHC7IWb3Yjb19cFHo/QAUAnWLO1yBPgd4Fo+nv7ULcAuw8yDVpcXSP2S1Hm8wZuEnDpdwpVgfrgLXw9Z/PddGQuv+LC53v8wz1rF0hRHXz4tPlShRKAT+8uKL75njdsMFjRmyg+YcAIrsCKBGg+KTCj6HQg+RvvXhKYiXhers0GaNKBfy9ngKLr2PiXy6VBwK0D5jseyc/hzTJcLtfrBR7NqYSU74EJXwzSoKSOROBylVezDpewGg389ZkYYP4wiEluMalIBZSYSoAOUA08AbAUmoszYPFCiAkExZ+vKqJVaE0ADFACGq8E5lmhzaOJrAKpBdBu6ElAzL8PKhR0UARhg07AZoB24wH8QQT+4ARwCYZnMuLXBDAfVbzHC2Wg+ar2REiA9BtBl6Q3uF4X2AdYCXAPcMl7vGdui+8emzp0GyIsSGMFpHxnYNdeCKAAZAzMasCCaKyAPP/paq/GF7Y4ggHmlz6rBf76xAa+9Em+5fm/hXzZWoDg4R2FTj4tMJi6k4PbEpA/d/LBWSDUXn7+uu4Y/IoAOiISyBaf2Yxm4d2WHGA/mHr5eAkylWfrz3Vi+xw0JNnP1895/NTHCchd/HVFxdfAn9z1wTQMe/hr4LuwnT+cfzIZsO2wlZ8c0sl33RDzywKZIxB+sK1G7ffigrhmLBoSkD2C4MMTcDkGsJHKAnX+IMDW5lYk7KJ1fnzE5/MJ/BlFB78okPA/JkY/0jwXBIYhd4Zq4z8hfhzVF4vvu36qAPGlCoiL1PBHFn+AJ51YAF1JMPj2kA1e4hOzpwoD8/MCaJ/qyW/zX/xA0ZW2zPEjAZD8ogDqVJ6/BD6+1AeXoDy+M2Dx7eQ/kC8mdGpt55cFMF/DTUC+P7VKhI+XJuKrQfASMPhmBWK+EOCjL3oZ8aMNYMeBY9f579Hx32gwf24D7PguQFT/dpxqCeLpj/T8kyDuQETnZruS9U0YJcAbuCD5KT3ij7aUxrG2Aoi/jKEE3c89/BFXQF0gLMLWBTMGBB6X5vtN8kkDMH3zx3QA14HpVUjvf0RbY3kvhq/HqxqkGVDLhoaLJaboDkxE1/Pf9lIyNGlAHpUk3QhYDSQwRXhfuyM5MKHA4vvBzXd4OyyHz/OTHKRHbC0vY2E5mB7t3BKe0Qu23BYEdCZAYcSNY2znIwXLL2XAi3i67x7l2bNuC8zVDODE6x+jcBdQZTzn5jCfH0WZzOWvK3liOQbP+1VRVwJY+AP5aJ9KWUfz+bQAbgv+2szej00AR/Ole2mziM5D5DDd/BVMzvGdk9wqk4GnFJj8NQwtEX+WM8EvjdTHBwY4Ae4FLj4S4PPXmO+hkU4Fv0Yf9poFQvnj/cDGL8nH3RYDgBOEAHeoLr4KkeeryLxpyRo084NBiqePp/6BkX+hgw8UGFPf1/iYDuUjewTIFesNWmB/CvYa/FCANDmD/xcM1tMFus/DXxM43CH/69ZbTuBZf6+NI9rD6TuSI3BoHywZxP8i+0fxB9fgbP5PBSj++SfG3xl8m1/bvxn+zzKQ5f9IIM//jUGJ/wuDMp9SKMhVT5sd/C+nZxf/AIW9/L0Gf5jP/g+T587/fP4egUP4OwSO4fcL/APoXxHuAEAAAA==" + - id: "rat_costume" + name: "Rat Costume" + material: PLAYER_HEAD + texture: "c1c94fe00f3befa501d5a9a01a5a01f5fc896fc0d2a5fd64794047c87e4ab47e" + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "H4sIAAAAAAAA/+3ZTZLiOBAF4CMoTJ9DF2DWFGuzIfokXH9sS7Ly56WUsl010R2Tm6JcoO8pJRtD/fpl1lQq0Jp4hUaxJ9pOS++M3NLPJVDjx7XEwD1edmtQn4iciw3c5w8GIPwuv3Lt/XDxhwJo/lVrLj5phiMAO+TRCf+iNb8KH9+p+gH0sT4/Ff7Fa57n5L9r+RrhSuDgN//Nq6fRPRwbAXp88d+yJMgPR1FWgEn6ks++wO/3+xvpJQEdiSRo8FNj+jPglwD1hJCtWQeaySBWgMk3fdtPw6q1WQea2TAwwNT3Nb/Kyc8BouKXvyyvEiPpAJP2+9NP9Ma/Tf79nq0ABm/4Gz/r1tc+A399AvBfvAGT25ft5z7iUwDVTOpPB/034Ts+bEAc8Wd48tdSPNmcsAFLYX7U3wcEU08dwg3IvuKhP1s+eQ7wUyH/lX3NI7/w0hdjNnzUANsP3J93P7R4GeDd9wGvfcKHJi/W4IQfqj9TngYAPA4QUIDNR3y5ZWL4zsdxP5g+5nMAYlednOaQf82mPw/6Aeo1gNevQ0nf4vd7VqSXAAY/qwBkKl5f3zSLe7gBn/XS608tfHvv8vq8lSRB25/aejk9AD9Dnu4mD48+fxY8/fD4fA3p+fTq8ftdMHhjN33+JqU2EUnQnX7xi1gbb86fn6y4dr3LLwESbQ2F9TZPetrTcQfr/APUO3508os93fAQZf1rALqvZhLQtDv8OvMJ8XlbRerPojaJ7v995zj5DV/4m7bldKRdul/EEkKexH2d+/psygNhHjXNx+/6wt/I682FFHy+POEQHn5/mHw5cdnI+HhQPfU94vNmG6nReVYr35x4wrci+hYgXbNwAr+PhgA4qT0AXrV01MfjV2sSBrAjsBVu6vLs22bf8x+kPWTNqe8IsOnAJy1/Pp/dAPUSwPxegHTpgz7lXQFi+UaI8PQcN/Se/8z+V65mBNIDopj8VHjlb+1fucQ/v2S1tyL1e2tgLH9ink8rAOxEqAHoRA/7z5a/RZB7owQAjbZ50H7BWwH05oQBzvh5C9o88sMVfhncbEBtDdkGoAGtBWgs/z45w5drk3ZhQAGO+utZaPlwb+w+m7TtG+2PZT6PssuVjzfn7t+mC/zaV6P7sjeR+p53v5bfLLw5693YrXfduch/YP/2A77enJH7jgDG9u/7cHNy39OAUz7NwfkhX93Be3wWBUx/xJcBiH9P5coRld8PkPzY810RWPtX39GA7EfplwB3Vt7pj/sR+3dQDr74jhr3jRBg+la1s+dPXm1fpfBN37N2tAEdn0Rw+I29Q985DvlsDSP0m/wXa8CAf8f8sP91xuc8nn7fPxZA+vHnfc1f5ssA/6x1iHf4ngAyQ+Z/0t8zLKWnH2/rq67we9fgNQWYfh7vnO8MoHl653KRbwcQX8NJn0coh8onReDLBYjlSYbe5WkC9Y0FLeWnACQl0AWP/T1CQ9/Hkn7kjaK25hv3rQd8EuDx+XzIZ0GuM96+b+b+b1pNPyZ+TfDIPwy+c9s+KVeU9PcAH1EG3/vY0LJbfhIznf2I+dM+CCBnvvyIiA96u572ZedzmXz91vgKn3nI183il5QxX26AQlW/5tC89mWEMX9jQiy+bIT+t1dEAR5H/cRvoy4Y7Xx+JPnkb+MYEUb8KuxgXoL9EZx+GQolGPDZ+HXBi78da/oiwuD+N/jcinLUar+VYMgPzC/AmC8SHPfRLy6fJRjx9fS1zwKo5dcRjvsf+suwXzJ4fNXbj+WHIf9334+WH67w+8V81mX6W9M/wwv/Qx5wH58Al/plolmjpLUBr/XrW79YDd6M7/ND5QNf8m/16YqGuge4//khX83zQ310/TnLGz57pHfFN/sB+PoO6Mf8APkf9MVlkPonAkTbr0H0TSfnv9u3//R3+G3+P/cb9af7nuV3+IcDnPTjJf756f/vN+pfVppXHQBAAAA=" + - id: "rats_2020" + name: "Rats 2020" + material: STRING + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "curled_ox" + name: "Curled Ox" + material: LEATHER_CHESTPLATE + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "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" + - id: "cute_bunny" + name: "Cute Bunny" + material: EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "egg_time" + name: "Egg Time" + material: RABBIT_FOOT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "distinguished_ghost" + name: "Distinguished Ghost" + material: LIGHT_GRAY_DYE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/83bS5abOhAG4FF7H9LAI85h3nO4i/D+93FBD1RVqpcETqKck27oxN+vQgiZxtu27bltqO1X27buJ2TPfzcapHh/j5Hup5Ee8uELQ74F4Cty04cB2osjP6JdnX8jQOeX18f9TwHEEfG0fwhwIwdgj9L9ALyPGwnA8Pf8wQCcPx1A9mNsLArA+rMBRD+2Vre+5nMBIg6wn3+n73h+NoDkx0gD5H1/1G85ZL9ODyhviPEBHyfZufqHyLa0e8DvA0Q2AB1+Ap99VwCr/rt89scg8cX3BNDHP1eAWA+7zFffEUDQ+wB1d4hb3qPwl28HkCdfUHbsE4OL0fZZvtLxWBOg+g/6VgCp35fbNrHfcjAB4K5BH4oMfwUAfh9g3sddZvgjQDiBqw7rCrRwbB4NZpr32yDA/ybkBIVflrVqp74cLSdwTQLS4KOzHg5wVT0UL6SW9eS3Goz7oBC8v2ag8lWsG2WrlGWy/0oBqtJ40tar3fB3yW/Mb7D8o435pACqv6xm/7/rS+2O3wae4ge+XSfuqI/GGpkBGF/gA5waR3yi6fwu8/Ta8OvzO0/2z+XCEuNxCCJt5z7umhgsn77QDi69vZ7WPmmUUf302QDaFNAOPk7AtrbkpgHqdhsD8KJk+45hh3x6CNoWPRWOHY76+/wdvuWQG14P+I6/fdojP03tpdP5S57sZ3wy/jV/B/4vnPEUXw+A/N3tnyT2P5/PjL/BAH6/1B344vF3+HStL/s7HH8CT2chs/47ueh4/SjwZA7w+Pxa3/Ijx0cyC9rjnwZQ+BSAeh1fKxCiNf3A67+Lt/0Q0fVQ59H6w8OfAdQ3voTXdbL+6XByr6fs0u47QH7Y54rNNSlAYcF5ad4VG/fPUS8ugOhK1LwtN8Uv0hK0Xwo/7Uc462j8Wv4YAbBn+pHMum2oCbwVgGi9nwYW4OFl59h6vV4/P3mewYW/1t+LzwenWMejhvzXKwVIg5/yuTDrqhagq/S4/5N9wrdRYft0jmn++2iyv6Tyv3of8nqAfpQhnplkiP/D9X+Fa2D1CsSM8RE//vxwPLoBFbVZmDnFm595cgxo/0sA6uPQI/6GfeP41/oTn1Zt3N+GfDr6u8M24G8jfj7/8MnP3hQd8OuFPgVw9T8gPTXfEBD9/M3llyH4Pt7+c/3v9JTAEYD3NzArvIv7VvzA8TTAiL9h/+31ybGyJwHJB+3duk/9YPj2jXiHf14EDB+V/7wzy/nsZcDjg+OA+M+H85fz/Kd1eMDPZUDdZ/sv+1yAAT83zqe3gVn+XEQ97a9r6j7rdxMg6w8n4HzCL93QK7zwbuBpP/N+fygAqTTjR+AHzItvh6b9tRt+H9j9QHh5KfiYj2/DYv2BALaP1p4YVwP4Eiw0QPdLoHUBS9+OV98NPOKD5Rfn3wzQY33/qx+Y8lt3BEZ95pdwaykAz98M0OE9D34fvLKvoQfQE9g++vXfjK8m6DWu/7p/I0DHz/Tf86yYz5eOv+G7Hlab9R399z0sN1l/T/+dT+tN+Z7+Twfofe4ZhMf8LoFy7xXdhTR9//OS+L8RrMzzUuNgZS3qCEBo2Fy+vhi2Ewg2n0HkhXcjjgQa3gXg+dyByQAGjwPweu7E2BG4EgTmnY0UQOJTgGE/J4jw4TdOF/3y81rGbS6A7qcf8T7DTzwzbT58EAUf8Vv9Oh5gxA+Uj4T/TgDGrz/ZaPuuHzDPLIa/4XcBrv1/3kezdc/PfGpg2L/2/2Wf4ac+NfHP+5HlH/MHC6Dxk59aGfFV/kt+dFZ/+mNLXr/t4fnpz435KmDy8x+cMwPg9rg/lkDib3121p9A5O/53gAyf9M/E/ze0O/7Zg1U/QlfjWDoD/lCBhN/0kchPPI3/Kv9bd+d4H+sCGTlAEAAAA==" + - id: "spooky_skelington" + name: "Spooky Skelington" + material: BONE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "menorah" + name: "Menorah" + material: GOLD_INGOT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "mistletoe" + name: "Mistletoe" + material: JUNGLE_SAPLING + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+WZSZakIBCG96zUG8jCRZ4hpe/Qx6jH4/Wurt9EMMioYSaQPYRlWiLwxR8BSGUJccMYY3AyvHJ7dQUDjIXGo7sRfHbGH+DAp/lH7g0/vh+G/2/jH+EUZ0ofA/nMzX88LT8o684P1ef6R/HFwVfH6B/HR7pkchuu3+Z5WZiSQm4S3FDhmOjMN7Ys08KkklzqIIwMgFW5TNO0LFJuSjsRqO/NdypncGCSXJtcdC7G6TdK53lBD3QQMBRiUP69/kl7oM95Ml4MC4BVacDzMmMElnnUCuj1W+GaPoMN0o8KMdd68IFBECbk2/Ix8rVpuNI/4ECsv6cHwZsP+DD5cRzEb8WOfL/4K1j3gG+OcfrNYfhSr79KYSDY8awn32gHM3z4BXyAl5Aaol9Z/MHHqy7n+qdv/kGdpsC+wyRfug+tHXwxm4GODqB+jedcWen2QwkdEWHGQT+8Tz9HtTYIHLKhGC5IfQeAGd9KaK4+8argJQwBYEKyzuMfteO+U9lsO/1KhtvAXng7+iHPCEf9UAqfqvsKwJiPgOGjfgiHZOZW9NYvmNUL2iEChq/MmNC7UdlVv1v9vXxm+TgvcG52DMCx+kO2OYbf8jmD++75R20oF5YgMw2EwvEXfRHRiW9mP84AZvWbUY8J6T3+3Zuf+zedMis/M++D7lsApz6c6bHurhGwuY+2WrWzi7Fj/3t59MC70U249sDfOno4QMi7PzvgP6yfprzfCvhp/cEfnyfXfn+G39PfnH9r9H8+/+31X+c+ufZx4G/Jf2MH7qr/ePg/rr+1AzdGvrm2xX9W/wxfOHurI4NKuklDOjhw5UIIN1/LNvJgdrYcR4TGnAcPfYPG/NCNTH0EbslPO7VdJw5UarXiT5nF+Px5a/628shi/fGzdWvHd/iUz90sz/Ga384Bw9f4lM9r6jUfHGjIn4r8I/xF/tScnxyH/uxRF35iJvfmzB6256cWj//8eVt+JnANRj8rBGBtx59mwPM785+DA/CvuQb8CeWneC7C/KczABzA/w2+zwc86kf7/raE71i/L/52M3DFf06+z3fhT/nC5x4+U75LwPv8yY6+2/rXVvqD8FPz7xPwPl/MZvKZbp9QYj8C/UHxoX9tgredWXzIDyIQFAcOQJQa4KGzn9oA/4weFrbaT3AAaluX2/B/omX8wi4f+KZ2S/4Q/eW6bjCZ9IcOPF3+w7KnGQDrWf6roFKhfZ1wxw/Mj/7YjgkAzYggkW2ijolc5Qeiq/yilfi1uoFtEeeY/1Hxdt3P+iI/csC0svP/Fv51Pr/e/1B6KfPRgXwjkzT1+5+k8Xnt6Hna2HfBs11GwXdrsf4yvtQce6jwCe29iWP1Y9XJU/O/xBf3+Gf7vyt+EX+TH7dtxT8de5GR9Re6/XP10/v5N/NP7yf8+qGdfroDL+o/GX/5BDjriJ5/4vC/GYDX9F/zqQ5Ef35Q+QT9RAfS998NfMp/OCPl3XXFHkw3YQ9zJTVx9qhYYaWs+ZN2Uq5TsWs+QYpR705am1f1F7Y1hbZE9VnbL2f5d2xFPtwzXZ3h4a6lWmXbvmLzjhS+5Mv4RQVB9K7521aL/5kDkcW5D8YAwU7wVAdqrd/GgwM1u1IfR6Dezyne2o8fSQHLi646YFd9nti+O6y9sscuwvvCNTrFHt2HfZL4Ii+60bxYW1Q7+Mps339ZY+7chZ3rpFPsQVsw6DPnJPMfDWrv4ldq1iWC9qB2aNolYuNi811YpwjtddVCBzvBfw8TaQT23RVdtxciE6A7JAXQwQoRcEbwPzff4wX/pAtS8/PWpPFT6Yfa8sQFchfv2wfRt+038xIFngBAAAA=" + - id: "snow_jerry" + name: "Snow Jerry" + material: EMERALD + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "sleeps_and_treats" + name: "Sleeps and Treats" + material: COOKIE + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "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" + - id: "easter_sweater" + name: "Easter Sweater" + material: LEATHER_CHESTPLATE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+2aQXaDMAxEdz6IFhyjh8hLztE1nL7QALWtkSy7bUSePYum0ehLxsFACCEM7brdojdEr3HicGzExH861+nvPf+HlqXeeW9+WWIn/d/ivDvfsz6Hupb3/ncRTYGqHd2rA6eJhGzZ0b1KcA1IAxAd3asDrzABUq6+jaJnAmkXmxESHd2rBCnRmTYRQUf3GkDcn2VGZRSvAUzeP+j8cDI9zjqa1wDiZK2H5tWDWUhKJaUMaf1LIM6taxFsJvRQNhioNjPasItgeUjloR09msGhbrV0Lu/595ZwXOhG3vM/VFLzKv2b5d18mLCB4AK9XIZngV0Z9md56EvHzj//3rcq9yUKBb5ykogMYjIvs0eeg4/KHFvDl24aEUGJzMv8DGDTx6r4ZMGPHXlEAGUyt/MB4PYih0GNzO2skFBE+QYJTrEaqfWfaXm+1PSfNyQBdRJfiM+b6HjhRQQOgQVS+CLwjZ8v9v4cbOtP8/PNHIVM/RnY2L8cEvobYqO/lmAOgSRjTKssLFnj+rfFlARwzBJDIMkYExNCVQgkGWPj+rd3ef/+NOQr7/3PW9q9oR7kPf/e8l5/3vKe/wtpPP83nv8L7/j83m/59Dzwfs/v/ZbvWd7nnyFfee9/VxGFqckLTRxziCaxjuaFJo45tEbkMrIXmjjutG++1t+8+VoZ1dNuoMkc2Pw1Am7YlbwtXs8lzh5INMG7jdzLTRuXxlHumizWiT3QxMCx/vTgyWcZxQOmgcscnKu0iDefmQYO9OeSp1H5+G0ciDb2AKaFY1EwVmm0WiUjx2IwVfjRMGnSxOFSQ73qdXcarynv+R/ylXCk7Ebe8z/kqy95AqnMAEAAAA==" + - id: "egg_decorations" + name: "Egg Decorations" + material: EGG + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "lazy_bunnies" + name: "Lazy Bunnies" + material: RABBIT_FOOT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "rabbit_celebration" + name: "Rabbit Celebration" + material: FIREWORK_ROCKET + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "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" + - id: "bunny_lantern" + name: "Bunny Lantern" + material: REDSTONE_LAMP + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "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" + - id: "monster_under_the_bed" + name: "Monster Under the Bed" + material: POLAR_BEAR_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: EPIC + item: "H4sIAAAAAAAA/+3ZS46jMBAG4H2v0soJhkWEuAEblPgkCN//Du1XGdtU+ZUiaNRdPWrNEPD3u2xIlNm2v/rvS6q6mHd1eYBLMsi0rvY/HAHzP5kA98MEJ8cpBji5I5Qv09c/7cvj6yeDmE8sysn0rqE9OZ/2Gpap3nvDttdLGKg1gD+7H3csPADaArzFhgG2dCN+1D/yjQvAkCAZ7Sp+Cw9kYU5e7oPW8pJRd2BwA3yq73GAbatr/wn8mz5DpAYf+Tx5tc8VoM5H3rB4/ChLQwCWLdnvM90SDW8/1IVM1ebzPxBa1/+3+dnrrvO5enMx3/n2W1gbNr9w0dn++XyPz8lnffO6/3UKX/TpC67xmfnW9efmG/3C2nD79LclXHzvNyB8flcARr60Amfz2QDECR/yqVN4edInT2P2iQDkmdw87tNns/tYAH6kyf+EWeHD95XZgXr9TIAwY6Ebvc3K+fE5cOBpChmnK0B0HbH43t+kEE+owzBdCWp8G0AfEsIEmNVPFKB/vx5megiw7YeFgABz3IH+Gybnp18OaVwKZAnQpjX49LcwtgHAq39AB57hEuCrxuEHAURQ8RZAe8bkb+b/KnbenGYDqHqpohatxc99CxhNX8pBFSzBy9UbCaIrMN4VTF/zEgK8XkQCdl/I1Bch3xPANTe8IDN754vB9T/12wMg5xemL50PN8FLqJ/uPdDg+97rDBJa8RQvEUTYZl8d/lbov+ElTN35pnyAOSxef0N8tf/jADt+19WxALS/wdbXjwDh3wSiAMM8qD/AlwP0+P5GeAa+D6D54X5TP3u1LACpq/VUsNn5wTuQ990CDAPwVRFqff12ryraeolvE+gG3e83U1GMygXI8hBAorxI+KDoBLW+2lND2AKE1wEInw5Q5eun7DyEATDd+Rh/u1H7oMY3D3m4sWb7uQ/RlU/ye4CbfZ3agXj39foPYYADbUrf/SUfAuxV9mFjD24RcF3zM8UH9+LheIF/7L4NIPDmz5X8PT1a4B8PxQ1BoZN3D/0Cr/96iFT0TXn+keGRBu8U3o+C/wjK8qYfiD6HY6YYsRj2nsz5A6B74ZOfCTyzFep933ssQMBnYRS/m2dSre9jhHI0+1a8y//30GR4xIz/rUoP+N2AW58OgPOP5IiyIUBSJdz5cYB1L08sSxjg6FMBoCkFX6547fwS8JifScDs4/OHZrf6ssZfauZPJqDxcczz6zqqSnxy/n6/VfmjqQK/2rOW5WtZ/GLQ88cj4F0fJ+/T/Ar8l26BO5b3/TLcKN/OWfvTWODXaZq0bwOk24Lyc/33H728n+PB/4oa0O2Hnz31yNrP8qs+x/qZBpjxSn762df5eR7zzdWpHhbi+52e+gXe+n4BHF5b4Ad3Wq+vb8ClCYcy+ET5Vf0f18VUl69GmPp9fbG+dpqWqYsnfVsFXu5+J0/5pYWHADAKp19ph8Xod+hv+eYRWn6nOXX+xu/G1Tao9ZHk4L/D6/mr3+anFnaXFs+o4aWZQMT3D9fBa9/N/4Jys74GdwGumvtf/dUvqx/9RP8qAEAAAA==" + - id: "party_crasher" + name: "Party Crasher" + material: CAKE + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "pumpkin_farm" + name: "Pumpkin Farm" + material: PUMPKIN_SEEDS + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "gingerbread_jerry" + name: "Gingerbread Jerry" + material: COOKIE + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "one_of_us" + name: "One of Us" + material: FEATHER + currency: TOKEN + cost: 0 + rarity: EPIC + item: "H4sIAAAAAAAA/+WbzXLjIAzH73kLfPLkGZo7uWb6IBkfO/Hk1RdkwCAkIfzRdGa1O23iCP3+yBgbhd7vgj0ej58f98Nmxyzr3Wf2ASY7LT4F8ij+3do23yK81fDVCq2zRoPo0mPnN1htmqhwnQFVWf2T/GmiBPyWGWOmyf34HH7hf0iAAw/OPsYfkvW1O2oGa/PpGfYg/jB8+9wb94sR4O8eP0jAjmu94g83MDYBD/r2cQw/4XkBtsYfZv60f315+tcXOwSs3XD/UPnDsPNsr2HDNbCTHwe+n3+3XYSigJaEgeIfJoDnx+NDJmDrLLSDPzB2lABBmYQ/W4D9z/nREs4E+wTfJDooMEfwFQuSyC/xUcBefH27ZPgYHwTs5WsTUONBwD58EKCY/im8F0D59tz9tHfLnv6fcfc/q/+7BND4/sXYRgEM/iRz46TEw8A550mPxlt7s8mWlz185ZUu4Gt+hwA01fUlLjBvScD6Us8vE9AlIHT5Fru9vtSHQFNd31XC5r8zRPYW85/Pp1DZsHdLGOs+TS5chzjAPxulFU+cwVpdn4DfJeDp7+at2s6cTHQLS4Qe/nN5nHINVXhRQFoidAiIz3MSf551Aob+BZrmkXaedQK0j8f53Ttr8q3EswK+SX51tyqeHxeyqFnNH7Jg2SGDvbIH6CgX1vZ01EvNv9CeUCMoEhAe3wsvEwVkttQWooDyCp8vSIF7z+ChRoFjmzIDywHsY9ykkbwK/gWIubEJgCBVaJQALC+Ya5q8cn4kFv13RvEhCGltPkwdib8quDBG4YsKBSeA80AyN/E1kfv4+NyvY2Afv7oCYFFH8UkB5BwQguC4zf4bmU+Nf5lfiUB89LlQUyDmHn4OIgKmt83+0/yZFUDMQRxf1X9DrekvMyfgQiQgRunsf/xihTj//lzj2SfMwHN9CcYoVAJKt4of1nU1P8y+aPpbft7RTB2jEAAyTRhff7eUhjse/nEKKvhpeVoIqE7sMGREk+NpPj3/A7+8UZIhiVpVNQA4/PjiZl9vrxF/wVIwmbOPBJisvlI6XT1fEPByfOdEn4FyIsT9qtFU769Xx2cFuI/G6xW3KasU9eSbKUB4DAf+yGbA0UfgYwm1gJoe7Vb8wr33/Fcw1HMwEFBlgI5br9nSUha+VeMEvF/XF2nX19s7UHgImMITfLyUpta0ENwl4M3x3+PiciUjo/D5E9X6cRJKKljiOwHvV5kE9+Yd8SNLR9ETn1FYCVjObkzC+w1nwmX97d74g+GjkcFXwZkUCafACRgDxGvwIvz/ZP6okHwuMpbJ4SED45W1sex9R2QV3eMlAYBHAlJkjLjX1nRIGggJI8HOI2dFI8aJsrpOGXMQ/uUvef5WC/vf1gPLtT2Stn5+IJ8r1FLwE4z/SiZjnoNftsYx4wUTT1Dwa9X8P8vPFPRuc8P+GzqT86e+jXa1+65kmlDC1fp7X9ckf37bwx/SJhM9HgRkxaOdfOahWeI3qteFiepSCel7YKqRpd1CtTMrXh3Dhw1fTXrYDtXFF09QXkLT8IfD+asprsGi3LeVv7YsF429/DyOVkuk1nRVh8gmPbmgYuzhd58MKMcfz+/4gp6oWWoFsPRePqOAaZGGL0vv4BuTqmZaAfXOwAIPK3+tAK5iw/Ftu/tMOUXm0wI28NlyToNPCpDbivhuPiWgmy+Us1R8JEPPX9tv5hM56Oo/CtXP35//nfxW3bTB58uZ9A3f/lr/mQcO9yQg9r+Rw/qbVpIvbXFGO7twVxp8qkkH3xdJDC1ANYboNtEUf7sGZlhrFW/ktu3aj5UFtCK02jYFpOrXth40mhLNcXXHsgqKTV7s8AW7sfSqXV1e4kqRUD1NTlIKcJ1VqilSO5651vl+OcHazcX+01HQh80FtQId+ZvW5kdVhyRtZ9muzacH4fGf9f4qHja/fopP9/9wCULAE/8sToNX7/PfQ/909VZr/wDdu/1+AEAAAA==" + - id: "buff_chicken" + name: "Buff Chicken" + material: CHICKEN + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "ice_scream_cart" + name: "Ice Scream Cart" + material: IRON_SWORD + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "jerry_island_poster" + name: "Jerry Island Poster" + material: WATER_BUCKET + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "undead_lifesaving_association" + name: "Undead Lifesaving Association" + material: ROTTEN_FLESH + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/8XbTbKjOAwA4D2rmRsAiylg0zfIkiKVKwRygZdUhSWVl7762PKfJMtgeOlqZTqdEMefZIyfX9LT9yEWGicT/5m/yqqCv3GLf1Gcouj3xSLzzF9SvpDArgwSuuPz/Vyw1pHwUQ3Otwls+XtwnECK3+VnD3bN/ZQe+Az/AF9v8Hv8bH7VP637JP7BcYivN3jkCwl8yM/jtV/VX6mot9Qcn/PML9f8ah8c/BUe+6p65d9TUavX9+J7/Cr4v3RI/loCMl+v88GvEv4v9wT8lQS2fYGXfRw/9vN4yVeTjo9/2k/wmX7fp+r/mC/xzu8ln83Cg/4qb/1e8H+5yPNTfL3KG7/f7ye5nT4kkPL9PfXz7eCneO33op+efx/2e+JXn/Evw2XQYX0skmkT+a/UD6C63Fh/UFw0bxIYmM+b/uceQO8vFWICdf16rfrDGbSL4U14P6mjKC0PQQfzyx1WAyS+96xi0LdBqT246ohJAvkoWRuoD8yrwMWHo2L9ti/F26rNM5sA4fVZgbE6RxmUhMcJ4KNx/b4n4NX94NIxnTu/tzyclnNIwdcP/f+OffP024ZMm5PvHpAErA/DPvhpESfAeJXAK1T+HYJWP6AgefgEAk/O0cATiPyX97+/k37Iws2BYWhIAuAHfnD0MLhBDLzof7OQErDnwlwDTYPOwFnz+iIK+bHKkf+b+pKe8M3Y2/qbHiWwgF6j/MydT+CMRp/7iH2tJBCqNfU3bm4Ozg/8xUy9gV59vwFn9ZOy0769ANyF0IPvEhiCP8Cfi50fNIGXTSA98kkf6zCrjO8yqDGv1yT9sn/u69dB6uenPeWHrt2cbkgC4ewznySgFxpIITnt9CH4ORz5vnjXmfMhnG8bXdD0cEtkr7uFBCwu8PqY3QhwnunKb2Pf85fIt93qBBwv12/aPWQeHWxxAsRXK/BgXgwJ+A2O9WVeHQNc3Yg/cNzU34p+rXcI6sXaJrCodz4e0Kn3E/z3y/EPzvc8WhUpH+qvzdCdl2V+QEAC4Kd47atG0Nr37dbw2Ofjb3hTf9uabc15XpbHIySg/QR/N/W71qKKxh9fAKF8/WiA+Wf3VTPhff0J/5HtR/V7vsb1Y9+cfzb8d1q/yvJxz/Bb0a+tX0f+/WGnn9oCXV0w/27rN//t9P0yqHzNY//ufb0BvV5xAuBfb/aAq59dgVs+THT2qn04L77PO+ztr1eSgKr6+3YLR1TDKs/HC7CQHfXVNXgvS7Wzvd5oAsrHvPbLB10AUuWn/aZB/uJ8+M2C8tfrTQXJyfyWss6r1a9tVuv3r876d5NZh/7Vr7+x+sGnh3J83f/G+LeyL/K3nf7G8CNfucy/Rfz++vf6KoHSBBR7Yz6t37bc4IlfsYAG8Mj5pfdNAjda/y32S94p675pNhoQ371yCyLcwhMf6W5x980hf7rRmKYKZ5PpN1s+NLA89aOIcpoyyoerDx0pWegGrX7gfJeA6MeHpD5R7yaBdIMSxt/5ZAUQLMFf6dr2Tv2CBfj6QeSzj950G8Hn/cWdK3+rSeRXsl/QQ9Bqy1/nvT9L/uMRdkRH/OKIv1h/RrxKwPsopU0/DvPdKf4UGg0/9R8knI9Twj70Zfs1yLZvEij2+OQQ8jHvvyfO8yGDn/m2n6P+ifnVDr8K/HH/ZH28Aub7p1WfHjPfXUef+3/Gd+G+Ike889kCNib9OcMviD9Gy2OGP44f8lVPx/xav3vO9r9kvz7u6yFAPnzto++o75Zk48O9a1idoJcs//1+w0vvNzwy/uj9eTE96j9O/gp+hf3QsnK+7dX2n++PCf+L+ywyfHZNiOOPfbud1XsF7Cc2GLbpyviPNGxuWX5GiL7vX/tRUu93GCXBXw74I/ZR/+CzcwLZrfn6CjDbYRPCIq7C7uXgAhy5Px33Z8Pv8at1n863rfn3c5/NPzonWJsxw5cTkPwoAee/XTB/TPpzpl8QX0qA+Vc5dvsF8hN9Xq+ofjv7Yr+Ghmv+5gkofD8xz+dfF5airu18/MjvUKDuu07w286dJszjBGBKLXt8koCbWPBENajphOt0AjGPEoj95x6/s44J/ekqWf875wa+pQlE/lMcAOqzYiwN0ZF/vOBf6LjfIX9ZMC/Wby+ATvRNrcEJU0KIlg4A9+fnc+UEGB+XgxaXUCY+Jym/w/6C60/7HfdHPNnQMOtLL8sX9zlb4bsYp4TfiXPE+ugEHOJVApZP+OZAIoEP+krSGYzIx5e/nADx92x+0BZI8GH2059IG76aaT/3dcHqPiSzo36dwCG/lXvmP5CTfuvrh7N5WtQNsnm6SFyAnbkAK7nnqUXTQZ+RhG9WJ6XMT+hN8wvC077ae2b6LV92JR/X/3xu+EWOj6dDl/Z1juAYHyLHL+1nwCm/ZVLChyH64/7K+E/Yfwp+agJMJoGP1v+nfFp/E2ZFqL866Lst0NTk1t9MyJ8O+YXgkwTW6t/2sybgDr/t7NchLtxxuzwFf8cJYD7uvuErXosCP/+EL3TbTkL9NAM7ZhNZfp57fJXAiOonRXq/EXic2jji8o+FMMbe15Mi4ukAeH7t29REmLcIfhH8mMenRo2l9kv9vxwd8PWtjP2i8BPRz8mkrxMwHR0I/T7JL6Ki1/2DCSTrLyLLHRj1sZH5zx/UD/MYFjOx/jDV7XZD9HVHcLFJF2DiClT3bvhHv5nRf9Hx5z7+YLTA5/+AD+9zfXl/lH27KS3Qx0WFTQCG/xkSyPJLfa/eaX7lGAv7u0fSd6bgw7lEft4KaO5L4puHzh//vl/8HT9MMf9ow3+m/ZUJmPKn0dxy/KL8kV+KvnsWDuf5x07Atv8/x1fyIgBAAAA=" + - id: "gothic_jerry" + name: "Gothic Jerry" + material: GOLDEN_HOE + currency: TOKEN + cost: 0 + rarity: EPIC + item: "H4sIAAAAAAAA/+3YbY7aPBAA4F8rfnIF4l3UQC6xWgQS8kXwDSIEydVre/wxsceJ8wVv33baAulm83jGjm3COedX+VcFV6HeLmsHkwGftHg1L9AObs9wJ62g22ubnA1u2mLPWKcBnWsj3/cAYys2oHtt7+MRgJtw2VFRJGKUz7x/tS8wFHEJSD8VgzjlQ86mENeoB/b5MSJ3VH990ynZ+Lxz1nL5syi8fzUhfRbVf7vdZr6O9Jnxufc50f/bz8/g9dO8boPXkbzxuS9/xC/gUzD2oexuDmZsMb9H9r6tu52CWDd/ttz4j8Pxbgqi6r/Y/U/5NnFb/4DP9KveSPum693sH979meWvjmQcTCQbYGcfU39971/H+wm+SvlwZe27Ya/fCZ9th2Okb6/sxp+dARmDVgQh+3ff3/ujfEb6Ki7XqxoSUTdpZJH6s+4SyN3Ma26CC+kv1v/R/ONHvmkDxV8g/a+vExVfX9l+yDNXezcD9fkkLxuQ60c8czTae0k/bILE5d8Efzrl+bFufL//1CW4XKMSQP6n0zcVuT4VnWUfKnBJ+yQvG6D9MogsH6cPH8nT9s7/If4pP9R1C3J9twtN+cP5y703kvVePNO3kToly1e4bwB8KnJ90+eJ3JH/Q9b/57Qv9HArzLBz71njz209r+kSDORfVDDgbDNs/xcZvl0BzeFEf7PZ7I5H8yXsuNuo4509LrL6n1M3Xq7/8fGxs8lK/0Md7zLyt9sPXYVk+hdY/Pr9A3S68gvlyzpk+PhLR+okP//J+IZ/3+6TjKJSRUa+6Yec/P2md9hP3n9q4Dn/MGL8o4mnbwJA+dv0v23yev0psO/ugzF+h0/vpBPzzxHV/2BuhMz5H02+jseLSLCkJddf7Gevf377TfJlvLASFZjlE8O/16cqMCt/Ho3+1X20AadiZb+7/3y5H+5/X+yH+++J+beGbo3fZPrB/jej/6NN5aDvmrCEXwYBfhP57cFFT/7h/n+u33j/uI5P9z/lE6eu4qutSNPCF1/znutH37+y6390A7FSi3HTwoMHeCd92Q9L+Or6cjcpLwgfNoS/W9mXuznw1b4u1z/6x19z+l/tJMCHD1P85NfvSeNPgU9wm8Z8qOjx5x8/knq2j2/sjv+EAgjRtELgaULguN0SPOXLZELf0PBq/f3e5q+IXl+1gG4CxVO+KYPzG19/AJSPSy+iIBsQ6nrjOuCrU5pWn9k8rf8c9MkGUPwEv5R+Gfgl+pNsQOCbp4n9vjrlAfOu8uHEJvTLrAYs48uRp959D3THoh+PUQOm+g3l+1Ef6kn/3I15+QMU26hlYQMm+9AA5z//q7745/9B/jnl4/UPGgm+bIdG4H2+r+LXwPr/S0erXqz/WMuPH4BY/9HKaBTcPh7L+r0NMLxqAY42BCf7cr9ELJ5BKP+Joo3AiX5VlcEFDijQxfUgLO34i8FJvkw94JN+uYJfEUtXv+/Wn4TvFsMcvyKXTuFaEPxQ+Y31UwNF/2SW7ysQ/Gwv7wbl6w1H/Gu+HEJM8NEVfS6Uf+z3BVxsjt89dJ+y/HI9/5zvD9dfHbzRZ+/12cv8aML1/Nv8Yk3f/laPz/7/vvjj/J4VZbQvevmET2eP4nzWvhjyxQA/3T+f3fOXngVoiM/wyVC/6p6/JOOGYj0fPenoPvgob2IBP1l/vPOlzxQ34ZpA2+v6N9SAdOreJ6nZ+Yv3+TAKRbZPbkFn+qYCmT5xE1H/uVr+K/jvzl/k5M/enD9jtxFxHpm/yPCTBaByH+dn5d9pQvgEGx9N8HPyx37Z9+dF+ScvvGz+dW31uk7wwVFtIse/Ob+ulale7938a1Ybvkb5L+QL5KsGKP7eqUKNYvn8Oz7EHSpB8HUi/djnM/y6Rg2op/p8lg8NuAPPx/sT6+8krhtwtwf8JT7Hfk3497XzrzF4ru/dPnmZj7v8PX4i/g6/W3x8tKp/f69/Rz6YPIo83549zo+1f/57/d/mPT5xAEAAAA==" + - id: "haunted_conscience" + name: "Haunted Conscience" + material: IRON_SWORD + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "angelic_jerry" + name: "Angelic Jerry" + material: YELLOW_DYE + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "turkey_day" + name: "Turkey Day" + material: COOKED_CHICKEN + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "bee_that_chicken" + name: "Bee That Chicken" + material: CHICKEN + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "H4sIAAAAAAAA/+2Zy27kKhCG97NqKS+QZtGyvckLnLA6auFtJO/a7zHy0x8obgUUF9OOO9LJ78hiqjFfVVHgy9zvVuMgj3GaRnncX6BxHF7Nl4fiT+Peax+v5D8irZH+f/zHE3yJ7+SvPv5HJx8S0MdfMb83/nHs5h8w/+CAwu9a/zHe8x96HhrHGTr5+fh38/UGfBh/Z/6Hn8AH/E7++mL+q+M/lq9cOJjf5ALit+w/MaVBrfym+v9x/OS+18cfG9d/su0WKuA1/Eecj9xQ60/hq+13B3+Nd77O/OtfXsMvV2zh6o76oxzo5ZfwPzX+1/EfWQfGZhX5YSkm9Ec2/jP4pfw3gNUjQcKPM947/738o+rvoPynfMIJkn+7fRM/deDU+Bsn4Ez+ofGTg7lbWPMr7F4+Y6zK3/MJQ499QwqgDLSf3/wKl+PrRc+MFy/iM5eG0/kubNds5O94hM/w3Zwjvmyr3pV3KcNvfYSj+Zq6sW3bEr6k7+cvyx6+wW+biX7btCMm7cW3CPcIH71CFxyg+YBklq4TYR1wl6aexPwPA/7YybdED0/51Ey4Tzgu/qWWAGr+N765GkAlMFb3c8tHnxCWlB8sIcNfMZ9v3Ey9XwE6Eb38YAYyfOuCXH8GL9PgqlGriR/u/2kCYn6U1duN6+Wv0sAwPVyRxB2R+oSwVONP+dzeeGL8bv5itZcvw+duGrr5ixeEo7ut7gT8KVTE5zyJ3zwQW/7axEcOrGj19vCj+Fd3jj9hMCdw4CqPp/iL5esMGK5PZ57PPqQDV6lmPi/xUfx6Ha52MJx/huX564q8buIvhm72JavcY7YVxY/7UPwbwZeXb3ZfPpIvaSn/lsn/dhZ/WTCfuy0AZe0b+csCNwKi/kL+VBC30mjGrlpxPzp+oyXgr2s7n3PkQC9/gUowDshfFtcH85MBDuKbWVBu6B88fjonfpcFBQz6VPn/WEEBKPXyl7TH3vif4t9MjwAX8d3O4PeIGP80vxD/RvDH8Q3EcnwR8YU9iwAtYv4c8IXFp/zL26XCF54/5/ki5s8BX+T4gCf5AvGF1ixaNSd9K/Ff9QGSt7DcqO1q5V8U/+rF1U4m/3agmpThb4q/oYUIP6pzJ2cOQv+SKvNJ8ciBZGkRcvwA/+ePcUBH1cwPHWChpoklcg4EM4/j5ylnyPMDB/6ty2eAFoX/W+JjB5J3mFRZB0xBUHjJJ8yWjxzQId7h5OU3DGU2Dszz7O2oImh8KX7kABkx2q+uNgNK2O7qgcQPYzF+braBucZfrnoKtGJ+CV+On3OTvgJ/cfFTeanhK/ELmu9Xnecbwz24j1ynGcTYhv8Ung96/ZMOGPxsZcbO5B/6RvbF2sGDNHrz2YCOP8bPKRnxTe+Eb+zyZjz/jcXtSxoVP9/mSDAqDC7uIUfzPz8/ec4+QQYSPMSv1n/igDQRfCPhPIApeb/KIw0f2eVyMIPAPwcleFuD8HUzxifxe6lytPVg4nx/u1yCOkntMX8L4g9c4FT8mI8xESdn14LhgQ8twA8cOWCbuPJ0vB79LN/fdAf4fxBOKs9POTDVZTvJB/xQ488B37Tlk6LRuwGV7Vp61hUVsjwMphYrfEIyPMRRKttN/ECFoFVzKKjKZwlHZOwofrT+bKuXfw23ecdP7ZEDKOfd+NkBGOYL0h45gOe8Fx/tMxYjMvacNrTNtUDzDtTtlHSZ6wVeLXnicnRusZ/GhyceLgTesWi+f0jm0H8f33OQwCLsOT+mYWK+vaDFEbiEu3PA9/bsUCEzbLfyg3cM6qd8JJbpnjEFauYciK0kvEkC8VGbDifvQL9SB7Av2awdxi9+R8lfdIYHpUuO5BNOHDz4r351sqol/M01Xhu+ekt+ml8e/lk+fE2sEY7g073M19SmEfaNTPVKe3591RNwjDKPQWfhc/q9S/wK6dW1cB7/P5s5yzAAQAAA" + - id: "painted_dragon_egg" + name: "Painted Dragon Egg" + material: DRAGON_EGG + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "H4sIAAAAAAAA/+2aSbbiOBBFx8a78MjHI9bwVyIdDf4m4LD1Uq9oJdnArxpUkGQaN7rvRaixIZ3zYUDYGL+fDhsbLpCADGD36xK/aYinfYFvIT9pAHzN/9Za2KRm+wEuuchncb/4/hT/avwdH9apZSDzAUvi+83/iP9xTbdL9W8wgR+2vuY/ND3lP7xPOJt7/+v935zgm1D/z74+6t9fd9o/51sb+f4fkR/qtv1KtYyaXdpur+3z/rdNmfSTgsksbIr/wfjve3LlQjeqfDDxhf6fU+DCpPE1/71XFWD8n8/3/9Gk6xwQ4Ixyfn1/2r9zUEBIwR+O/1+ELzUwvQwo/Pucf8iKexwXEFqZ919GcEthp/5IIEXDGph4/jZf/57/Dfk3hl0sCej5R9ej+qPmw6nCpIsFcAUwA5+uf6i4oTGfAT8DRvhU/48SuvhqhXdCIwrYtrf7Pz8ltjYp4PT4R7Ujnc9aTUDmSwLe8E8qb2FMCzjtX0q9FfhIQeFzAZf9o0OMrwu4+2vB+7z/jeMtw2cBNtzLIT7NwDX/hhwR+FVA6Q/5bIw/y6fe8wGJjwW0u9k3/SO6Lfs1PhRQKLj+JX+Yrz1/lNTbvM/UpmU8FpD2veO/fih/n+OnvXAEyHx7tyK/bhK8xC9XEwEWZ+CUf4K3BjTK+ZbxSyv3FpVfaZwfNwQ84FuJz3tgUXDJP8oDNS3y6RCsJybv2/3U+Ad4zhTGXxbA6h8FnPfP8YY1y/hShP5tWf0HfMfwhDjNj+OrZoDSFb6Av8h3mW+A/0k+5tAFd46f12Mbp/Lp+jf8Gb7UJxvfnqj/2L6wQ/DvEP9X4Ofj5UFOxc/wB/5jAuDEqvqv/N6EI/jXBWQ+q395/sr8JGHK/rkOmLbvZbPvf8r+ZAHaAISbXb5kf44v4fP8Z1Ep5vh9/Kz/AAZ4Jz5/An6d+gbLzWQHTAfIUBzyaftiw3XnM4X3rwgA+BFftN/lP1uoAlyHH47e6/fP8/bz3ufznIAZ/1P20+7nkwnQh2EZCuz3n8o/kX6ZH64WJUC+Vf2L6e/wnzRSo7oA227UXIc/utlIwehVgRWykPlJBPa/ZL6c/gv8EujSbB/3Qc6fxt9E/q0nwNYbQivw3cn0325UQthjdAEWrkcC/1T6bxkIgyeACMDDUOJzosxvQOzfR0fAFF+714RDeJ6PBLBpAPCV9NePaA61Nz3MUADmL4AvJNwQfLq+w6df0/MClJYjf5niOxSWdT3YCR1RAFrk/IXyaX8zHO8c7/tgDLRqMgGIbxcUHX7lmsZXxl/hywIGfCH9gG/yyzl57qvDwDEFyL8V+Ur5C9+kAZoEPHsCbs8qVRZgRQEdvnOwMb894tczpQJYlS/hEx95CenXBdxSAdKZjglAMc3H346EnsYmv9Ijw7t5X7sCOH7Of4SzCfhW97dz1yYgF0AR0OUb6r+g+fAjU/C6ZgVtHjvPx/85JPpHAx4mAPN9w1XAFF9+1MSzyf7ozP4hHjsorFugAKcNgD7fvMHPAuxH+Efk9wU8Iv+o/CgArCMS33T5UMBxeH5PgD+6+7MaPvDhMnqSDwQcib/3MuDpe+Ifhe8FyOnHfGn1Iwk4jsh/lKDGU+xFwbKkDr9A/6f5QMCaBLwex0OL4/GKJ6UC5Hv+VU7/OscvAhI9JODV4b/2fNpR0u/5cvrP8L0AP5Xktr2AV/SKnT+894LfS/obn9rHw6/DLwLsSX574hzYl/jlXhNWIHWsXIQg4pW6gi/6y3+K++vhhfhFn5zAN+hpo8z2+XHFJz90gaBgz4A99IQowr+PFnukL9Quwg/4aMFLT65rjL0KUCPi95R9JWKTAL+Qpx884QeucxU/EJDw+649ONdKcL6pPS1+yC+TzljiWgpEiPAY/pxFhxf8gN/6QllGljW9cg5CGvZkt24dmS/jXWQL9peSceQf8OMsnmJdWg6ECAePRfqNvrATfx3xoX8H+CAHCj/2Z6Xq5S+Fb8Bk3/w7xNdzkLqHP7oYQUDlx7GH8P4CR/n4QsCPC2qW0CLj45G2nsv8WH0soD2tMP8O88v2KkVutTVF+K3zU//tHrvPZ7VoNamWjMivAhJeFcAKUFeCup5KfNCZLOD/pDZ+moBUfYIPmp2SgHahm+DHC1pf+skBE7Gy9BMBlG/J7ygKH11QvgTmeCn9vnimPbBKAhR+26Zn12+hCV1M/5IfU9jvgIqChq+bDKPGCvqqIkBOgKWTAZQyS2dzT+UnAfC7A/H60ovJvPwmvj2qlhQ4TQDOBeYPqyD1/cpfgfckZJ4/lwAdDwSQXqD9skb4XCydCOEcrfBrCsAvkk1FUlL1UL5hZAMkrAN8XVNK/dlXyVRIVJCv9RvsVH2F6gtoXxvpUWuS6fExt88uq/OMgBkJOQ11WcpTiLYyD+FEwKSI9p9v+eUNPIkXmxgKoqvCCv5cib4EUUcUYK7hror4roAV3WUuwksuxwclLL1OU0R8WcFYH1Pwh/T/4/34B4Jnn6cAQAAA" + - id: "sea_bass" + name: "Sea Bass" + material: COD + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "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" + - id: "sloth_burn" + name: "Sloth Burn" + material: RABBIT_FOOT + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "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" + - id: "surfs_up" + name: "Surfs Up" + material: WATER_BUCKET + currency: TOKEN + cost: 25000 + rarity: EPIC + item: "H4sIAAAAAAAA/+3aO3LjMAwA0N4ze4F0Yu2ZPQVVWz6DRr3HlZzLr8QvAAIk9HGcYpEijiXxASD1cZK+B2F+Pj7Mmw/zv8j/CP97/M/w//3P8r/F33Fk15Wv3uOzw3ddYLsjvOh3eVh+/A7Ee3zmZZnfQV7yUfkV/2j5ptl+vsNdxd+UkFw+8ktDnP1aR8ZR5Zc8HbLhdzw3jkUCIk98sh/2u+LgMQfmFT4sq+P9boOfRJoO8MsBiN9r/a70R8hzPlqyaF47we+JXxzurclF8qdxYtcfPdvTwIQHPkwA3wqAP4UI1a/8JPod1UEUN0mVP005AdcHoX6RLfw+HwQSAFfo9B7iYwj163neBw2o8j6F7X5P/Z74Rfc7mWfWP+snoEeReOS7UwVOo8Dr609CX/gMT2NCvpESGN1o3PLrxYg37Kov8/5sCLzoy3yKev1Vf4r8mgDnK/iq3+BdAvFizEy/hu/JEYVvav6U7wxn+ORnxLL8eh6KvoqHIM2nzacEzvCLfjS7nxNgfCVPr0/C7MvhEmCuP2rfm7QdNvHWfdUTKP0NPNsOaz1vbSOBXD94ztjP95H3onXRTMD7Z5Tvh8F8SEHkp8I/wC/jeBDx1QSCnzM4xPcSLySwbBjx3fQY3xe8kRPwG5YF0OcETuCRb+QOhA3ZPx4SzyUQNyxn4Nv47Iu8Pc+v8TSB/PZpfp23iTf47DjLL3nsw/rh2yf6ZGhcPs+fVn8QZD4mYAp+s39ndYsLE3hS/Ub/fl/wewpcPRq34Hl/3OLfi9jAW7F8pV/qw3AKr/MZffAJWDr1HG853vlW5QcP66tfFs/y9JkE8Eo/s0lffEaSeca36vpp611wFBv+3Gd5e8S/L19anq9eVf+KfoXA/hq7+MX33yZV/YlfEsg+aErLp+si8MtGVf3D1yUG71cy4Kq3idfWj318PlaXI8uDjTr/ejWXizHX6+rfc/0DCJEQzsrD/m0Y6r5xHwar/L7+Jx9kU/qRl/xpk3+73Tb5RsUf8En7B6Kb0IJq97X+UPT/Rnnkq3mdn4sOL6l+h74JuoZX+vjyX+rZd7/afC0xPx6PNt/2170hdis7H3yT7Nfr4eKwn/YXboEwlVcOr7/mNl/z4cHU9yUv/q30Pb5OQZsX/biGOP+e/KGsP+kqnvUNwV0CA/GLAI3X84XP2cEfWj7UV55PIH0WIb5fv0LO0gKMJ/8SEF/9mb/zZN7/qjSHRFf91/LjLfrgFDCOr3wSCwlU0cL3N31wD7h5f8kA4qF6+YOge1l/NuF8123o//nzel4u63PhTHjb4u2O+r0P+v/19Yz+vK36+GuxXX5K4Pr3+bxe/y4B/GXq092P4fOP+vqN6M8z9VeeLR/rG+Z/He7lXPcJBPhzDsx/f1OeFL+h/mU4N/LFzfQMfIZ/ze5U/jZ+CUrFp/cUerilBv/5XJdcWHOFnvhvBd+s312fpjj01c30ws/YRyde5NuVivMPbw9Zj/4qXuOao7pfet8Kvf63qRxp7MeD87E+s1dxocuaBGzC10jTHX2is7w0x54X/1HBHYYe5oLBLTqo4xQqK8zxor/uYRBeidnz4NE7GZIeeNYPexitvqBzqJ3wom7j3+AlfOV1pYOnB8wrdOSjPYxp66HtzWcXGvB/0xja+yoc6OoU0L/GjdJe6aor0qh0rT7SkP01ZjmcvL/vLT9mwOawecYFvOqDFMo4B2/5JAP/Dt54xG7XT0V2+368XT+wzuv5Lv8N9ht8PXy2v1k+yd/pHvEPkhv8MyXBZ3N4v7s//N+Nzh+2XnnYat/Daxfe+bh2zb8F1/vvmnVlPj+CV+v/oP1J/N20rP+ALPk/RsMMfhr9Hy7+ARoAPXIAQAAA" + - id: "vampire_jerry" + name: "Vampire Jerry" + material: BAT_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "murder_mystery_poster" + name: "Murder Mystery Poster" + material: IRON_SWORD + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "sloth_santa" + name: "Sloth Santa" + material: APPLE + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "skyblock_winter" + name: "SkyBlock Winter" + material: PLAYER_HEAD + texture: "68ac19a2ddf44b6025de1f8335e2b08dfdf039f88786137e4140e509fe798269" + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "naughty_list_certificate" + name: "Naughty List Certificate" + material: COAL + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "jerry_s_workshop" + name: "Jerry's Workshop" + material: VILLAGER_SPAWN_EGG + currency: TOKEN + cost: 0 + rarity: EPIC + item: "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" + - id: "joyride" + name: "Joyride" + material: FEATHER + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "carrot_minion" + name: "Carrot Minion" + material: PLAYER_HEAD + texture: "2c459fc8849bd8f38c577907b9983fdbef406285437082bfa4845cd3d75065c9" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "golden_carrot_cake" + name: "Golden Carrot Cake" + material: GOLDEN_CARROT + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "ugly_easter_sweater" + name: "Ugly Easter Sweater" + material: LEATHER_CHESTPLATE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+2aS5KDIBCG7+LCC7DPkiqulMWcfQKDItJgM9L8VPAvK9H249U8BEXrufUzudD+X8BCl19NLrT/x5D5CI469uXVG3VwAMt4a/TDGIe+UsmjZhcBxrgAagyD/GNlUHD58fUfMoxq//D+Dx//Hk2q9/tN2foZU3tXY7giJ8Pixj0PYTZ+yGsPIzb92w68aUS3P3T/S2ydhV5/oYX2/+zvX9D1j9cCPWYXuv2j1f6NZp3Q5c9IuaNwW+m98dgTdYEXb5NBLgNsrZfTiguE7wZEt9jPc/3G/Z3giKFii+9lc3XtMZ+4Yviqwv++KreDrldf/Vv58w2AFRsRTIXf+2LGZjsjsz9KoG4wWHEoPP3VihepBEqOyPQALYHST4e1G5p5PFGuk0Bdnhb/G6NJnBIoSVklRZJBLQhGMyJL1Rp1fZTWusqjBdAOIOJonnOslkaLYDJ2tUfR6ZdRreXRsQSZf3l4hPlnz/n3mOuPfuuvTAD0+rOXLgYpcaHLjxbVb+bS8/4VKXT7f76/zC20/9Hfn9Hf38MV+TCmjJmnNhuNjPUbKA7ThmOpdrP0/o+26df4qgTe9n9sevZ/PBpD/E2cbPICPG5WNUX2X2QRPG3UzZPnLb1skgtaOdboc4gUrCIJkOC2aL3YZH2UWfQIx/uYi2RdlAOkj/Y/vv3RATr3v3MAe957/EnFp9lkXQa+W+j1F1po/7d/o1kndPnR71/QQvsfrV84yk+GAEAAAA==" + - id: "carried" + name: "Carried" + material: SADDLE + currency: TOKEN + cost: 100000 + rarity: LEGENDARY + item: "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" + - id: "dragon_slayer" + name: "Dragon Slayer" + material: DRAGON_EGG + currency: TOKEN + cost: 100000 + rarity: LEGENDARY + item: "H4sIAAAAAAAA/+3ayXHbMBQG4LN5YQtQBajAF5XgGQ07yQHVhyS2t2ITSPlgZOIJJQjfj5WMksV8tHztvx8fK2eEUgXXWto8VtXzeoi5vlD1kAuj4NzWVOoJvH1UvcIvB3AJ/4AP7bMi84vz3+jrAUgTkq+Xdl8NgJuQ1t+9Pn53nq8FQE2wOnf4OMBl/lCAmf5IgDv8UoCpftseuNDvD3CTrwbo9el9t30A5ADv+sL7ku20U7jfL7+PA2gxp/lqgCy/XlthlC7xgf2ib5NW3velAK9YRB3O0e4rT5Ta+qolPEpRp/vvMl/nia9VLEdX/Urv6fk326/zc33y8RrP7j8z/crC9y1M9M9NzvUCz58/xn14xLxeTfpEP55wL4RbW2vhMcePOrKP0tyBd33Brgag9+cpviWlncd++SQOJfFWtIs+49/xZbsQAHxa8+nbetn7r5dmfth3RV8NMMWP9+XeADN8+FAwMABv+eyBZMIA1NY/tslJEahl+b7Wd6IeA+y84CsBir5cX8ODf/CtASrnj+ir+D2+jvsAi+o3BXjbD/0fHYCW8S/4W8mXA8z24wIQjgOxReH+L5bsNw2ADWkqAfr92vMJCgATbEoA6otF9MWceQfiAJvmN33/B/wUQB6nYwUAf0M+D/CWf164Bw0AJyAG2BSf//2n1Y8X6gAAH+Wo+OKv5B9X8cKEK+Z7L/twIoQAwGH9J+s/X8TY/loIQCXdL33/KfsO+xvzBUk7BJC/0glw7tuXo2r44/cpxvdDGB5A5isTsLL+cz8wofdhYTT7wgAU1p8y/o6+boQZ4P4mBQir2nd/ZeOPHTRvLm1FWPN4sc/P3rqy/qPx33/DACAK2okbP22BTwLA/pv6+uO3Hz/7DzQAG92A+QzkPlx/5D8kSPPPfRNWAKyxLMRPo0AC7B9NhU6/vP4o76f/EcfyrLDfBNhAaT4Yf9p/0+bnGudHDj/MWYsP+i/4rBHuw53gP2KHfT4BlGf/hJ7HJEzFFu6BCs98sP/4/4kpcCxP6L+VffkILI8/DZCOOtq31JbLPg6gHMFV39AOGjVASFfw+WNQ3TfgpEuviAnyDWBhE+Dhkf7vHKur+5u/AZ0BoAROwH7fsapGCuD804D1ARZ4BltwAnb7JjxzkdeEo3hLvu8t8NMsDPjmHFf2GjsbNt3P/Ih/3mIMeszQN4EFBb837pu88yoBCv7Y/kejsJwlPQked7r0QmgPfxfK+Vm+a/It48d9l56Hsp+vN+rvuWb7S+7uwf9ztPvAX8JXkdN8x4Y/+Oiwj74/ATOnrMkun4w+mg/igy+iJvm8+07o/mW+xEv+xnz6ZdCwz4c/5wFNyv6760/oPs6DA6AvIjv987Dn5z31WR4YAH8RigLU/LMtpiuLDy0HFsBKAdp836ItFNoOCYD8nvvvqI+eynwAWrvBd3H++30SAM55rN/Sf5NHodNHD+vpeZcGqPho8cWPPuHPvei+032bx6Xip0VvPfWMcuAVH2+CphI3G1x/YOudXOR9gGe8or4b4CUf7nww3HHo0xVvpxf3E0R8R/zcexKG+Z1uLB39t4X+d/e7zX/y8Zfm3zaUQT/PQFr/d/oWb787fLj/Q8/Tjzwa03274s73nL8X+eVVfJHf09BHfCHD7b76LxwDfrgH9PnSLDSX3+T7DH++sfb3+f9Q+YT/s5fzxw9JcItv7Z8f/Um27K+i/+PLHf5qVkvvvz+ouCvL4bP7/yf8XHglc1VZD/uDvg/xtcdY6dK4pRzw+vUfCcnx6wBAAAA=" + - id: "loot_chest" + name: "Loot Chest" + material: CHEST + currency: TOKEN + cost: 0 + rarity: LEGENDARY + item: "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" + - id: "vip" + name: "VIP+" + material: PLAYER_HEAD + texture: "bde7fce0eb5d6cd9ba7cad1af9a7d578b2be03a96dd59a78bb3b59687a99fd" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "mvp" + name: "MVP+" + material: PLAYER_HEAD + texture: "3c1dc0dee5099c2ecb366c1f15692dc46828a53b443f43199955476a77" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/9WbSXLcuBJA1+5NXYHCBXwDH0GK4Jqn8AKLDBK8ehM5JwZWSZbj/05bqhLFwssZA+1/lu+Q/NUP/ri+3v5Y8iW3N2zbNrqMKnwPvtFgU9GfJgro9z/BQ9RgCzLk88+V/IdeQDw4DS7W+/v1DTZ+J/43h7zJmz/ns/VJNRAqANQ3pEDwyXfyBZ+y+kAwsAm/k+D/P4m/w2evwbuAGZ84HPxdk2FGflpRDf7kd6zBO4sanMQnAFYVc34WeQV/XvhLriQ88/UCQQH6noTP9ifJyTE/B3kFf/nghHPfSRHjk6SUujy4sR/9KLGc61Bvu3Bo/aXG9bWnc4een4gfVaAxpnzWAeY64F2Ez1UD1MHZL2FIJKJAkpx8wq+jnJ0jxtaL7CjBcYJnBTariSmf8YD8LI6AqIPhr5jvSeEtvxZHp8B2w982cj+QO7N49TQlOutr3tHXRRdNTWuvQZMBLb9e5/Aj/Tw5uUwJ5e97SpWoKpzg4fzG+0ASYMan68Kv2ER8F2RAByC/4pnsDc9ZI5e1I6W2I035ojSZzeZd3I5PeLylCzvxSXnRS/jAfajj02VzPzAfnPWQlY/CiXd97/nSFrwGtQUjB/r8w8s+/GK5KHLqLK/e5bwf8UGVUA1IZ+nDT+y3gtLUluGNj/C+7E5pIayF+UBmoK3r/9wYyKraTbmkTizx3adX5PdlT16nQdgDtkIxBQKfFwukMn5Esut0rn+Bz22D3kj+1hI82xWK41NfFD4NsEt2YRJ6vCbAxT+Oo95xgCBP1SO7mSlhr4oaGH/Txpw5qcz/FRH8++b4hwoE/IleA+FXPJqTvAYtn6JPfGDXHsJPzSJ7whe3sP4kaP2Vxnva1QfKv17ZfM0+TDYX24pPCTz+rcEzXz+GfPtsQl2SLySpP+Jj7uOsDaKheOCgISgEz/iAd7WqJ+SmXedotoX9z7lHqwYrNEB6lURTjVdgwMd0hZ35nJiceoh3gpTKp9W44zuR8Ql/vboQjMO/m+n16k6ZT3qoM7VcLz7mIft/xEdsSqzGYQpM+Jq11zUeJeHPqbIPcsrB1SR8rb9OAXag4A9T4JZfGW4Yst74Yr743/F7BQLeFBjz0WGU/0Ek9r5Zaf4hXJaorMDHByuQcHOleFVgzt+PI3eilmNkAp9sRz5cX5X8USUaQPhS5LNz/4/w5fCi60jl+/3Ch0jgH5Hf4B3/OHoFSilTPna+y3RgPHRwrFWC26eZX1o+ZsCUj6/WyZmP9kPwgLHrIgsqv+AoxRSAw+zS+B9N8tdAEbZE/lvLr0Lpx/yTFnh11qJBhCYriRIvXXeWyOdCJcv51uImso5PvyI+gE1ftbuyFWaB4xezn1qWEMR8dB3dbuYLH7aA5+pzeFx+nGLGJXDDx16RXZ8uRUKnH+Vfqv3bu9Ch5fPKpQ6vOUCjGL8In66kpApkrL0ieqv5W8eXVAcLgOHZAYUTHhUAkCGNj6iKL1mXiUW95vC2/7CFDxVa5DMeUxDTS/hF8OYP8j/iXQ8oBp/wQfBZX4SveEyB03heIp/wpbR0lzi0+tus/6nxDd/hd3LATJSPzq9BKD088t9s/lHjT1Ug09zDeJ4zT7Z2PO7lL3L+9XOaq6n2b7r+zXrgcDoHAOF5n3/vANB4VfIxwq/P+byEBkuAXY4Z7hVYqSEwfmZ9wPf+5w0rFZvyFT/jr2oY3ODXaH6y/S8v+/PJW6iM74hv+NpXhwqsax2a28cEv4a78iYn4J5/nur/kwOgZzy7TjLIr0OhPcqX0l07/Nprmd8Cn/1/2pkTzjcfcsYjdFUAx0IdUI36F6jdVX4asPmbmR/4fJ7GBQA8333wGY/RUQHh+7Aq/5oSUmArugZfGsymTwACn498Tt1ryf46rpxQATOOKMpPxkM99S53fqHp3/KhblIRfwo/4qsLLQOr4zkCtDOrAbDUoLck4RR38/WHf9R+3mnKgQO0+GIZsBb3t969vEkGcsaLjpHO/GvnYU9e0FQ8M6jts9ZaCnxZPVIOsU0u/Gx/cID8qqU39nv/82YHt3y7KYAG8SuSVAF5KcpHB8ivSm971uOfyn1wAITPe1Xc7Cjfp/GKpur4gS8BWCX/R7br4dOG5Ie3f9d9dpIlLRwhlQrH2mUWq8FH3chXZWd0fQrm82+405Q1jnTQVRygYNVElw92cRh4PoKt/OXxMP9z7He/0yQ8WK6tnGyM5F+U4mjgXAMDuj6EuyLweJj91fl01CPLXKAlHriYCj8jXIrgai5GAxcW6Okb2BEsPnkV+xOfUySqN17nnczXniIRAFYAKPrXNXWACwC09A0c/woA/wOGysdeK3iCn2S/2FQ44OgAWK0S1/p+kACsEj93ABVR5uHyL2nmy57ixA0F1eEqUdUmQELswLcIkAPckw+AqEOwvxCeJgu4PI98bsRq/+f42EbHCqD9nl/xMllR5lf86bKqaMGRUhyHFWNhOoG2ptTwO/Nd/SXDY8gp+HrwDdhPnGPrD1iJZL3jqwPqQkIDgM9eMp0oSP55+yuee/3Kq2lZizIfvGc1vdQbdN9i/LoaXs0B77TLcvW/BP8n2VrJgMXzcWu6tkKtyJtfBzO+z0ApRfV+w3frJY65ZD8OGhML4eIA95iYB1O8ZqBFZxvzpb0Yn3yOYy49HsQB4cmj8RlPfPMh8rc7vi2nMz3NX5xRwvUZkAOe78XgrxgBl5fIt+4b+FLfflRofArWd0H8P+Qb3iZGuf+GL0smpUa82F/LHnrrs89m8r75yKaoCV/XGRh1uR6sZyXq5YHzhU8KKH51HfSev0Z+5n9ZZ58GarbccWd4y0BNEnD4KX/l9GP/O3+CJZ7MeQN8w1e89U3PX5RP+78yWEtJ7oPrvOT9fGO+ZMDayYh/vX3Pum5ddYLnapU0xIbPMx1d8ApyuAK/gwf+8owv5UL2ex1afM8PBbNa4Wr68W0XH5XJcdWygs9X4lsV6ymhS5De/n6yEPudmsjnx37MpvzTStNIQM7+IX6+4+chf80v8IsutIy/RH7o9m0OOvHLMJ9+E/7q7KdFDazSf5mqfAjT4pgOrmhX3y4jf9H0Uzhli+dLSCNfSlPFpUjwPrbrPOEvln7mK/DRD2E1Pl5Jv0zA2a0hX7Vd5zzmL4ovYrqPfm7qyvGvb+m3k9TnnXQMt0aa8b39+BKLrPHCAG980GmyjrIyPrfp3/Cj1jN+0MS7/xJzALox7o+e8AuHizzmJ5gbPPweO8ASn4YYu7+1P9NantWI/EGJdXhRwOV//gx/zS5jrc/M8PXfFDWS9HddVd7zB6N788f4XwMZjBM16fhbuKfXW2Ldy2v8Rlo+P3y6vT9rpf36PYJ+RoEhn3sK2Q06yzb8X4h/psHreJ7/b/mGf07GFpBS+h4+OH5iz99q4DPju/hi/jPjx1n5Mv9W3Yqf0p/UQ2gAn+eL+aP6BI8e3jDoTEvLpwWonFDQWgi/8MhgXvs36Ml9g4lE+fJfJib8gYyNFtLcm0F+0vrHSYW+v8C/tfpzfBbvB+YvL/J7T3+dL/sRvDblpxn6VoEZnzZEn+XP0/GTfNkP9vxlwn9SCV/kmy/iva/gR7X+Sb7psHT32sc7/rzXvMrX+Dtec2P9sCbDHfpOgQ4f8j/wW+n4U7Tw2Yqc88Cdyv85R075k+RrCvDv8V+T7+X7s7jP86f/QfZ1/vIV/nJj+n+PL+N9D/9R5/6/z5+F/lFlefx9/kSY/3hy2/8d/1UFno6D8f8C/1vl8aO64ef/QjAAP/4FtBlcpwBAAAA=" + - id: "doot_doot" + name: "Doot Doot" + material: SKELETON_SKULL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "gg_wpumpkin" + name: "GG WPumpkin" + material: JACK_O_LANTERN + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aTXLrIAwA4AO8me7bVWd6iiyApY/gcRe5BtevjfmRQLIB4aSvEy0aigmfwH84ye32iqq4V8Zz9YsycP3aEAHKK0LxEt/CuPMVV/gFZ/mKi3ybc0VF8ocnADrPfFABShf699zPE3n5f9vHF5+i4nn+g47/M//Z5/9gX2/R6rs3jeP7/CEJFD5//qX7r/cHJKBFvjgBLfSlCYh9WQK60Y+hhySgT/w5VMxrcL4gAeTfV2OnXcEnMsdaZv4FCWjsB3uPrWJOEXw/D3pAAjrz71EO001WEH5fAoXvQcDkFSN9TfjVocUJZB1MTZHzHQkM9lsTKN4v5BsToDoQ6XwCCxVcH6IgpeWTiEt4rSnqs3L2h4Rg7z/Qv4z/T/ybUuENqjao5rrYXu2T/Z36py3qfdXGV/hqkL+tQuje3SZqW4+vGJ8zRvphAjieMFxry231TWr5MAGMvhHFsR6Gzycg922lTycg9i3yddY53k7xQt/CIHy0fYiPCNvklwm0+OUJYG2jX2TQtALDO8DkXbsEst6JNqZ3+Ng33b75Ez65A2p83ODhvhnmEwkcXZ2I4Tf6t6xzyj+6PBXD50+/bzIyv0zg3Mebtaahb/qp5Mwvlyd5Czx8xT3+LHXjz7snVgeHw+fH/0ZG6Zsm32TDX30aeqs6/vIZoFaHxoAci3e3fgKw90j5mxP5UFhfzB7k6Pt8hf0QKl0a1svOXvQVsA14Y7dvcT+x4zjqbV+ACtwq1Li/bXzw2bWke0k7++Dhwx77zGHpx3Log6ON9eOVgHHemNNShQlgHyjCoeb+nPuMw1z/lho/Bf/wF3yG4SP6xwnsL6wfhy/w+Ue6FL/Ut0P8igT4p2V/LejzaxNgPi2wIn/rMlz0OdhvoX2wDvjX7C/It643ErCFHxoCv53PfGIeQC30Yzt7gZ8ywLUpATRhFbv/i4v9mCaW/qVuw4KobOx9Vvn64EIxE7AmQNRx1d5nlY+DOzDnt4T3G+/+ewLbnAp9t/Tp42/oQ7UWE+R87pNfSrjo3AFoHex9Hvl8Z2Pfcyb1W8mv0xbaur2/+jzyfnABQD4aVpaQgUX3UbSvCH7H5Sc+A/qeQK8xH5NMUHTXY786228Oct/4LySMgeM0YJsBvHubSX4XD3ZAWGCBiU3pxBG7OQGfWYQHAbGP1nd+wauUn+YwYr8QBfcnE1vJ/LUbeHc1Bj7fATJ/7lFjfJX1WjqYy0NLfWGM8I9/7UAG8Dv5mECHnjIQ8IuI9wlI/EXui3gXbT/9QCGlf4vvr/muT/Dq6tAtcYqbLvLLki0SSKWX/yAfsanNKD/2DcaJXtMRmdqM98Fkp0G+/Cf601Qef1f404lvAXrF8d/hjzz/f4tfxDP8CXMF/xwf3vbj/y9/lO/63H/rPs2h5I+2+YH+PMch7+XJlycqBvrxl/ZZeQJT8RQfTMU187+cjn/O/Hnk6Z9PAC6SfjgeBvlL4Zz4/v9R/NL1DDRQvzR+ACWMxEMAQAAA" + - id: "skeleton_says_hi" + name: "Skeleton Says Hi" + material: SKELETON_SKULL + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3aO3ajMBQG4B24oYsat6zIB68gqKWY7Y8thHTfugKTpODOOYljQN+PkITt8bJcddVVV1111VVXXXXVn6xnq6YphN/ip1ynJZBRoqcA5yQQz1aok31DLv4pAVwnf7LfPPmzz59iQqLTfIkTrsiJ589P9md91wA84t9utr8Kj1zwD8X/6rFzGf5z9f6lyv76uEbA/ldXgvtdz5D4ghN/jSD6XQne/l0O8AQa6//8LL/+L/7VmjvCir9/6j662jXD1iPMfyfwBpjne+6A20zquUnysC89EgI6LAfwJXjtX4ah6DuK+GsA5zD4Lvo3K7+PDus5/3zp769/fOO++2++/K7ev60TME3CD/lJ99hLmf4Kz+9/IZXp98z+9brfldm/LJIjJQB+z9KzvNEXvz74jP/R+ms+LXH9b9QwDL3+Q1wC0wIsrf8WnarTfzzK7QeWev8x7b2+XJ7+H1h1+mqAclVUn9t7fHjDr7T2+suSd/ogBHvtJ/kWvts3CvgN+lTfY5/hpyXRi/f4vgDhPH8J7jrHdyfo4KFf3t8dDbDPL7y1fCNnAnfhw359e9u6f0CfJeixoQ95w4eHFr/XFHzEywHYoYf98VU+Xzz8iD9uRf1Afb2Nvf4Ia/PR+pUDNNrp90de22mSFdS02fjfAxN/wb7WJICnzSdz0Of2+eiMy47wF7n9tWHiD4NxC+Nv82D/C5vc/FiHmdEBYcpvPfFah57CCdw+UPQAYSpvflUfpXj9/qAfVp/OUeEGNFXfGWBQAzD+Cf+Xhxe8AOnnQX8LkBpjH/2q9gF/kPzcNv/wWbGr7wog+TBAad758TesJh5jFP06AurZhScs0y0HNexIfTYCAR8C84Ug5JqYdNMPtF1y+vInYvBIS7Z8+uFaaVf3xQlh29yXOwA3XU1xTRICyLLokwD4MW0/+4H1fPUt2uEHGgVt2nx60kf8kfmUL1uRzzY7AwB5LXJB8dmiua8vBMEfAMhygFRjEBZA1cc9Zvt8dRD89KzTZ4Oh1+cB8pPiBZBt/wVw+PVJ0jb2Ay1XB+j+BPlReMlhrj/eDhD8UfLRGSGfgyH6O6Dpj8Wn4wz7cFP0d4Dkj8Af2/5EK8R4zK+jLf2VduRvMzQ/xOjvANOHty7+Nsvy3R0g+2My8J4V3grdfmqQWP12AMUX7tlB9tmUy7F3+9qefH4Lfqi95gvgkUmAciE2H3UM2d3nN2TQIhyB2UejkuVt+j57bRDPgLePzrLHz18P8OtwCoLRhgY6njO6X7+e0OUHzNORX8Y+8KXrD78e0eNH8RNf2Bc0r+Tjr2d0+ZGLwsSz/bnl+6LBeWilpT79WouqNyKAIaf50vCjPBHYZj3BLt9un281Evj8ye/Luhpgj281rvJKgKbv6v7Z2GQH2OEbTZu8GEBeconf7P7ZxUsBPuk3eSFAyw/MV9t18DxAXf+ieDP9QV/cyzf8Zi/PAlRf3u23fBigPfxmN08CgOmv7fdbPgtwtp9ff/Ad153Kn0d9+EJH/mw0sKQf9LdXXSkC8ctD3lPxo341Cz9tJXZAI8Aef8UmVnv8/++2lZQAQAAA" + - id: "watcher" + name: "Watcher" + material: PLAYER_HEAD + texture: "17db1923d03c4ef4e9f6e872c5a6ad2578b1aff2b281fbc3ffa7466c825fb9" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "snowman_rampage" + name: "Snowman Rampage" + material: PLAYER_HEAD + texture: "1fdfd1f7538c040258be7a91446da89ed845cc5ef728eb5e690543378fcf4" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "chocolate_feast" + name: "Chocolate Feast" + material: PLAYER_HEAD + texture: "819f948d17718adace5dd6e050c586229653fef645d7113ab94d17b639cc466" + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3YS5KkIBAG4KuMtWVtLbkD3EaDwKsPT0mSBKHKKCdi+BfdWlp8CYLardTMzMzMzMzMzMzMzMzMzMzMzMzMv50d5UHahj+q7/xXPqkb/kcF1Plf+LTu+R/4FX76/4n/9Px7bABeL+AzFlRm8wv/9XotS/BPE27X/OM47uFNAcBnff0/XG7Rk99//Y+jq4CrE7y+uAuQBv4u//qM0zeJfE//jx6/p8So2+1W/+mmv/eTHn2y/zReNp59cDROhH7c9tzGtsKv8lnLyKmdVk3wEH/pH9mBDl9KWap76wEw7BfnAF9KUABwSn9z4TzUV/HVmC8lKIDs8JYl8LzdsP2d7dV8KUEBLTfy2TWgGj6yAwO+zHVUQLj4YQxKX0rYdK8vYVD39w1P/cI/W3bfpwqoXSZn1/3NjX85F3icBLkfGhjyZZFwa3czbCsXPuWrzJflmOta4leEEHGT86wAyj8XAScbq2otPlQgBM8LqA9/1e8qwoKlLzKfbxRf88/GugoQYMgF7W80D32etejb6hoAAXxx+u4X0El+57z0s15cFyAoXwC/Zlf81FDfDGj54oI//TQBEjrkC9o3FbT4Xr9VwIXfwJHPcz+fAHaJpbyZ+1kvIG2N+XghZXvQNwW8va+UPXY+etLX/NYFn09AciGnvcx3NVi+lUv9yhdwJ/nvHr899DvHPgd3MtH0TQFvPwc0Ekd1NAFKX1T9sBk4HckeHPCFL0pfED5LFcQ64p0G6zy8YlI6ugAa9djvKcxTvlbUXT49fis6GgCF++xeZAvf6tjX8L0yd1o89Lm/mmY5hwLA3Dp77q6+n/yUvxVIU+fuup0DQCwjDXntuq2I3qcCEHDFQ3/f8YoOMxxcefuB4ZUuaqD9DaTgkY8LKPsIxqM4Pu57JT9Ymr0Z9tWzvsr97SMeLIRPfVjAkG1nICsK6PXVHT5jLD0JyE7WfLjK0vF+3MpvdyNevR7bQUbFR/eX2nqrdt3+//a9mhj/nRWABNoHTX2g26FfGTO2wdfzTcxreHSpAkYoOt52/rqCnlgjv4US/vf86bsf8UNFpfRv4LW79qvrffQXdO8u+eIvTSqMeLRRBdier24YwidLKsDukuPQ5l1POn3mC4i+1FIsOnsqEdfiuk3N+ny78h1ubwP+7ybno4zo2tmMerUo23VTz4SFAUBvaFQN160O+Go9Y/cXuSxE98H5HY2GF8ueE0OX7Ow3a1Gr5c/oHYwM9V7bKsC9iGWz/lu+b/hhEV+rmd/b/1DAjbjGD/RHEkZgbBhus92yVn55/1q3sznM43tnVX8BT8kzMzMzMzPt/AUzxwxwAEAAAA==" + - id: "sweet_dreams" + name: "Sweet Dreams" + material: WHITE_CARPET + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+2ZO5KjMBCGz7BXmGyPoMSHIHHqzIVDQpfLZ18EQmr1S90gPMG6a6ZskOjv7weSpuZ+/9rXvva1rx20n81+EQ3sV+GfUyDSz1BAHav4vgoY1y16TwWMZwu+k4IWY4p2moJmiNP058/8e5KAJn6GLz/nCLBEH9M/888oQRMfi58EnMBXuO/CXwUoLbhbgIJ/vwt/aUCNv1OAFn7FX+q/NeDjA/zXGwvYwn88Hn878ZXwX+/XG3bAho/02fpkoMVPCkLGPxKe4+9QwKMj9/1a8As/hDSwwMeZPo68AK8C1sfz+Vz4r60AGz+FPo6jmAGnAAGfBKQbOfxx4Y9aBZwCOAczOgrIeMAfl8x3rIDAjwJY/pr5fhUIzPNL2z0vNP1RgKECLn5YvQNG6v7LheV3rkDYbCO/1rZ/zXyKN1bAm4CQEenFX2zzVvFNFfDw7xCfE8Dn1VoBF/8O8DM/LnoK3lQBH796CdYCaHxcAboVhxYPy6wKnDddJQGwAm4+zRPi6/i6AnE7xHidD2ayfIOVCjweswZEN/PzvBB8ClIFVnrND3v4bQFofBx5+oo38kPF1wXg4Yin9IQ38et5DQFkdBwLPY+FJp74DICvCKCDIPaAzJL74hjwRQW6OjuecWIRYBC3F1+asN6IWf8Gutp6xUEAj9+xAEhC3hvwRudDt5RfK1BMhLf2nQDDzj6qCaJZxDXwZZWTn9Jce+m3aE3nnEphihuO+JwDMVPsuBGe6YiPHfDwprVc3G4iv3p4J16wG2uy/r50Ac/yT7H/kQ8BH+cTAgF252eAMcRT+J4Ui4M/6+H/58f1x5q/xPxgvQnv5fOjfv6eDOjaWl623d/Pb+kyKoAHqQ4rsdwUgpAQuBNgByySICaiOgmdxAeJoHdCOYftxdv4gqY+ZwA1TlVArzNIYRNFNOgyDg4h7SV6mqbBrYmDl2HwveluGFz0Oy1La3wolv7RU+HvbgF3nV+t1QO2WkD8WunxSDBMI/ikIPNh+vWe9qvg4EnA5nYabsOgcXUJ6uhN4g8Zf4tirPzGtkg2Z5lfiHzwz9WsuiSDEWN++oRanqz1EYD5OBeXxRj8cv8wf0L8CfOzhhp8gA35GM/zswZgR+jx7WL5V0WAZv6OmGr8NX1cr1CRj+5SEDHTyrpG23RcYUpMDl1vRZ6zLPYDxuOSGFy6XssyaZCN8G0u23w4i+HGLFy3Dlzzo/hkVoQy2fDEVLEnwofxU3cyXVSMJkzVqwe+r51Z47G/Jr7Nf5YOzPzleuHjDlD43Nrc5g/5yJVsvd7ukhasHQJmtTfkC7o8EvxAJEAxmI8W3Mt2l90ZuOWZ5dMkDJg/sHy0HVA8KUC9h2L3sBVNfEFLCdfKH9AlTkAOTeYXBTDddIqcAFpvH58aQK1a8DFG4KNx0Fh7+CRHVAAXLbHjBw5GQGUa/dhRr+bLCkTrcd7araDPcQ8JQOuGCu6JpwJEBafQ7QJOotsU9IBbHmU1dAra5ITkoV/ObW5ILbrzY0r9Eui0tThePqirQwPP9gmQeltLCANnXs102xhOa67V7PF3biSv9W7kg/xPC+j/JrvA8opyrhAZ20dBflzwZOIf2cxQdvfQd4to+XHhdwho+eIG/gFhuhSZAEAAAA==" + - id: "ox_costume" + name: "Ox Costume" + material: COOKED_BEEF + currency: TOKEN + cost: 100000 + rarity: LEGENDARY + item: "H4sIAAAAAAAA/93aXY6jOhCG4UV4M6DeAI6vkkjZRyYSd9n78GcoV31VNoakpbZ0Rp2ewPNiDIdEc7n86eGn8Xv6982m+dCOHRmm/4EAB4bKN8087+OfZ5x/hGsJfvIn9zKyM32kQddlwcA0S4AsqyqwdVYwEE2jBlz2B+R1WjAeIfH9Nv/b35/E99NgAePuGyvAnIG2bcsPvk8DtpNA/ZlLZmCHb055rwU0yQRkUd03J3z1RUBDA3z+qClPAzIT3msBpb64I6R+dsKVgIaOFQYB/LbYJr5+wq2AQSz1Pb8vJ77kASd91zTYF1e+9zygpQHANwIKfD4D3vMC6iPeCCDvYQGa74XfEh/zJODGhhpAVI917reGPwdcuZ4UsBOAfG/6bavyU8B19u/3e7SnH3EA8D0fwNdDFv56v8eA+GPW96bftHBw/7r4w4h+/BEEpGsO89HHAZLf4f8c91vh33L+FPAzDXLKT/GvRf5PHMmKS6YC+QUnAPk31WfY13wHea/dgGr8Ub3fTF+nNB8GCB/e/m7ch5KH94CLMQFNI30tYHsbnmeiKX7D8Qb6SoCTAcCfRHhS0oDlFuIcCkAJTvoKD08Je3JrqP98vrifJgyvHPfLcOKDABf56CcByeB+Ma/6695K/Pf7fdinBWRnI7/6SsD7nQTU+vDRhx4+Lngvg6+/sgjLf44j5XnBexun+8PEj/7wH/3tWx0f8F/T6d+uQItfA5j/Wkbd8S8bm/7wXCp9pmsB9vor8qfncu5LHgdczACx+tgRrzwJUHkYYPpy9bMj3vgiHwTkfAd8Is4v3sz3Cg8CdP+FLn5xyMmpWHxf7dOAcfm/4NW/HPHmJj7ZufRFgOXPqz8JkBedvAFYPPa3DrH8kovPvv0c8lHA9L++/f7L4EVAxnd85HkXjWI/WQnHfTcpWN/lu3pfH4vbdR3z4RKUQ7HpdVrodwuaroWc/3wqPLlM837XLQHg27CcjwrS21QhPwagr8Pibv7FwX1R8GS3yYzfrYP7UwGlZYMMmH9T7ndkcH4KkDopeMaR6AlvBCQ49D3WyRQ8wXCFfpfzVV2eA1XXAzgvfIunCzHDKwF89oVv8/+YoeKKzxffUd8cis8KdvEHA/yv+ivyLd9h3vCz/D7fMX3Rvuc7Pu/YXytO9+nD+OoBv1P5+QZT7W8FneqvHSq/Fez3HVt0lf4cUcHPBVRk/haS9bV7bXZ06qDPQp/zjQCSAvyuO8cvKkD8PHbx2+ZqQBhGSUDq78OtgJ1+2XELnRckPAo4yIP1gwM0nwecwMOAQAIewzjDV/Q0IOFnv+9pwQd4GRACLZgDHiBgh2/x3A+p341fZaGCs3geEEJaMH+Zx8/CnrWf4WkA4zc/CdjGKTz1g/BjQA/8c3gSEAwfBJzu84BxPWz/tKjGL+EtPwRy/PymeL7PAqb1sPH8rnwSn9yE+RKI/uPR9zzgO36I/BRAE07i0wcBEBAe4+SvAeFkn22EAuI07PPJR5MT/FDhlxSIzUx/z/pjH89KfSMgWX6Fvl2AHlzP8rfvwXQdPjhb57/KRwnGxwaNX/xYkfX5V5HUtT412f70qsoHA25m8IE+oB/3le0sP+zwcwHaZjofkgf0YwH6VoZPRtkTUAVf6A8FJQEgIbdBqR/KfNIAfnvAT/6BecXQ5gMc6Qf8oJ4P7IuA8Xf1+jCO+fOTYb2+y5cB8cG8Fic+D9D8nr1cflOHGxOA/NDTgj55FQquabjfPT4J6CWfC8C7xD5+L/kslupxNztt6j/L3h6gHvAk5vcGffP9QazDoF9FBXuTfo43dlLhi40P8HV+3MMv8ofG8w/7/wGiuGW/AEAAAA==" + - id: "trick_or_treat" + name: "Trick or Treat" + material: CARVED_PUMPKIN + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "candy_cane_sniper" + name: "Candy Cane Sniper" + material: RED_DYE + currency: TOKEN + cost: 0 + rarity: COMMON + item: "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" + - id: "chickens" + name: "Chickens" + material: CHICKEN + currency: TOKEN + cost: 0 + rarity: COMMON + item: "H4sIAAAAAAAA/+3ZTXLbOgwA4L1XySZrU6tQPkFnPFppfIJcgtz3/o9/IAEQlCi5sjyvRepY1t8HghSluOPowqSw/mXdP/8aD4pwcv8vxPjPJ76FzUfxb+jT8p/g27fyjx1+0bfgRw13v4UdDosV37zSD/WHBAxsObD8IyTwt/pj6uHsm+KX7j/RD79P81MfvN4vs98pvjXYP5CnfrwQLJ587QsmwNo35/gjvvzjRr/tZfUXLz9jT/MPfvhb9O35fsrhSF727bPlfzSWN/nQBXv8x6Na6vTL7Asl2OdHd97rl/I3QqlfSqkBBdr4cO4cwi1tmH8M8tH9V+QV43ECQY8puAJ0+5Z3f/PhR+KHAdffw4/AL/YAef7q9lVdfebPyY9d0Nv/aPjlP36arW/7fP1CApJvVv1fi361XrUTaPj2ifZXqwfVTiAhLV/u/0W/5pd9K/t2r1/zzncJqHWfXf7Nmz/xf6gvND/5YgLMJ7Nvn//bR3R+y80HX0pA9u0GfwDfve3xjegvDb9G/we+8n9+it+Yfxt++6uXpfH3vF+6f/nmU/xpmu7hZX8sln1sr/9mf8q+SwDMZ/x8V1y8+4F/9zbEWPwd448+ezYffriPElgc/0ICtW+f9XNnTPc78+sEKp8+e+7wy2DICRS/SgAudMFvf/VBh98dJXAPfo7a5wlIvu3zB+TnWPVZBtRnX/u6kIYTiy6fRL/fwe/wVa/fww/qA/HjcMd8w2czceWnFLp458eIzaLlqPxrlYGq7j/gixgde9QPPUb4uCdu+TVnkK5/dxhqPyq/iEs5JT/+AUTGg6p9lEHwFfFx9w9qoJyIR//T/cD9V0FBPpTo4xrErqDzfy4/81v8EPnPfp9lYKymdz/x0i/7V/4nb39c8QG71j7JQGtLmi/6zdZ7P0TxE1/7pNn5g7bEd+m4l9Z9nU99Hf0QfkRW7acZMN886Ws96hUfzQCyr3OovtHnovhal88NH5UgLXh1hP/5xD420QnkBIZev2QQ34AsFYi/CbXU/By9PmQQfcYTf6nRVSjwYwIfZYMQPgPs8xFgTNzvkmOVL361RcwAfOiAUfALf5nW+I1+Hn7AC/4F+9PaSdd9MvHD5acDOgr+5UITaDSk3yfzD/gmNT/78T3yw9BIIH25uNFHGcC70Q3/wn2UAHyzRxLAPh61TMYXn/dN4lH9w/VX+zmBeZYSKD4+Bt9/UCbXclSswPd3jz9xHiWQfTpuLlLxr+iY1APfPgOYfY25CDGFBCgPCcTjBB4nADDmc3T6nE8JZL8+TCmSwfV6RXoxoQfiGGz5NR99v937tO/jZ7BZQunS3+NjfnjkE2va+twbRIfPGuPZX6v/wHnnoz2kw9xqog8xARNGXhH7/HlIUw/omG8lMJG5dAgVYE88/FPTn31VwfZL8ZTQ82ICU72WFp+2fr3/4zwTkrjs8o2ufKgCXBVLfql/vZOYADuPYWOvuBv9NUpaOXlfVz5/Aurx59W21uuW9cP9Zuvx/CNmMKH5L4VAyf5UliT9OwT34/cohN/tT4ut/05RRiBsmVh0+MLVDuvCyBfmnX7/ywXoX1+yX5UAHb/kw2yMK1TlENwYc6PUPAGs17WPs0+3j3tAqHTELvFHaH3bv4Xg9YF84AzuI/KJwywe/KzY9xl0+YSfc0MhiQV+1S/Xn5RBzEFzX1Ron/llcHirytzX44eYtYbx9/WHfZpDkdOe6UMsgDH+BSKuMPRWOQ++2mibYvhev91WfVg/z/o4H55DcA/Q3uAZ8aX6CKnmUu3P94tNzyafS1ov78uPwo7c9nN82IP2AK5Xv9T2i/1uPp+FokJ7Y1/gPqW+NP7P8G83uAOVuxDV8Tn26PQM5anvPfxWH3CdZ8UzrE28XznLjcU7+Xwels9Et/K96LqlGV+Os30fvO7y2Xsz2Gaf75f962uoN/iRW1p/ts/zWJPoO41ypnf1+XxQgs4Vbb++t9RH74nX+L19QftF6hV+TPhy/Q/F2b6UUf0Me6T3fv4rtffz/y/xH9XhdJQAQAAA" + - id: "sabeetage" + name: "SaBEEtage" + material: YELLOW_DYE + currency: TOKEN + cost: 0 + rarity: LEGENDARY + item: "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" + - id: "pumpkin_pals" + name: "Pumpkin Pals" + material: PUMPKIN_PIE + currency: TOKEN + cost: 0 + rarity: LEGENDARY + item: "H4sIAAAAAAAA/+2ZS3LbMAyG13Vu0ckmk0VuwC2PkA01WnQ0jOOd7r+oRPEBEAAJ2q4z0zHcOrIM8vt/8CGm9f4Zz7hfnPb4WfrPKTidflTA6fSjAk6nBwqwIX6Gb3HweFbAns02voVvh/i8+JJR/bwvnwpYtpvL9rLhvbzqz0sRxfSxvyi/7mGp2/rsnxaGK4+9a/29gm8r/zbnepJV4an7xaeGvsmHn8RB9CXNswXgW/rCh21FPvIvFCtl9EZ/8Ug24pNOe/65pO7uw/dvG3w74B9UgHW/cHx78MUYsJ9LwJvHTT1qy4Erb4IAD3PYly09gI5jyUuf3oJvwc9OAXx/D7flfXTDt7X3SoDHNaLe2RjTgA0PtuRGdpgvaUHB+yf5PvAt6q7VbaVXmQb8oyZp1pEni5JPuwKhWe+CUjaJ5jNWWr1KfF1iAajr1Jj/sKlaKMy33bwGvho6X3pU8q2C31z/uGnpUcO3ijzPCpById92+X2dXngO9PorZ6rGI1hbJ9UDt+anftt8C/hiJu+fSeb47fCILyVx/rk9CxRf4qM7XZ3HfQSOz/3UylMmXAE692JmPNV2pt1Ir17KbER/3x9zlZXAwv4p0Th2aBSo+KGysGvAF/HksdtdBW2lOv9lACQf1/Jjt2fGPz8DVHyr4Xvg//xN/Fdth+a/ugB+OeL8vb1B/8tSN42ZA/zuuK4kkH98sBhYfhm/BH/YV4kENTCA/7CJJRGLVfhP8tKU8Yx/W7s3hgrI45/5ivHHpzqbfVL/dv8D+eAajD/sPHVm2QVPBwBsLdA/6BQwf6VYdz47ddFjt6fgKD/jH/MNy4ePMeg/TKiR5w/nPz3PIt8c5U//tpD4aP3ibUjPb/lP/Oj/4+P3Rv/98RH4rY2D4XMPhJZ/a2z4C8Zfyf/U8hv+y0ID0x/XP7Ap34t8Kkj0bwh/Pfjb5Cv8Y+dBkRpRPhOi/9RLl1/Xf83paj7nP9J7/Dj+YGSPtbJHdSD5A6uLaJz/lZYfToBfBvCtwMcB+fiGT4cIyGei3v7Z+Y/8T7L/Cfh3i4q/YrzAX4v/adoUsP73L/InN02+zcfjEKLBjzHhgHx8g+EHplT5PWDP39/gwxX8KfmQ/ceVoODPqc2s5nuWb9a1bPyEDwUkvgt/5hjTjfxsvFH/4/o7qNvhztXUQxbDdyp+c/zT9hBmSrhJ8e46fg+/C1hNBucrNd/p6t/yT75gJr1q/LmUBn8F/CrMbXxwS+SvNT8pCu838kt06h9TDPzqar4rUeHBZYsP/DsxID/eiM0YfpxcsBK1LiX/Xeantjn3AgTsT3mgJC6t+prnX0Ic+PfwaXur+ZfCT9l34F+qeH9PV5B/3EhtS/ZXEOD23SHyN1UvLy/bdSxRuJ7+LT8I+NgiIWt+nCjc/Kf8M88/nzn+VxoB1+EHCQP+N1zb/+sr5G/dZ/7n52e+di/gensCifx0Fx2d+vXfBCR+DsT/RPxJ4ueb+ASv4RMBEv+YhAzfXUzFrxXUfEf4VQ1opCzCdwLfNPnHpvGFBGQVbzI+CAD8eXbbq8cPB7TMD23cfovh7/H2Rm7J/D1G+Sm+gICysM3bG/hQn3EQ/7AP+XkFAH6kpclbqhr5ezQewGggZsg/KumczJ9BpM4dI6Bi4x+IjyLeJPz8WyFqKfDPW9TW0Y9zSt8zCX9S87HowHcCHxXzDIMuDTep+I7hu0fy2UB8Y/j6H/H6yvKdsv59vmnzBf+P4h/2e/y0NrV8d2f/o/zi3/wLPheCf8QfmP8CXw4N/3b/6KhI+FOHfwf/uB/CnyDfJbltvtPysX0lv19/gU+e/2uXDycAx6f+3Y5m3cMDCDj/avkhBP4RXAPM3wUUEfNj+dWZIJ02HsdnBVzHN9z4d/mcgNv46xifUTDINw3+zLVoSgg9DvDn9F+O7PqflQIqR3r+cThfwbKp+FRA59e1Uf/ldL4SPoe/hS8IyBoMPv9T/KTAt/isCnYToefl+/EVKuTe78YX1uPt0eDHe3mu3Z29D1CXX7baB/PNf8/f48l/8p/8J5/y/wK3HyUYAEAAAA==" + - id: "ouija" + name: "Ouija" + material: ENDER_EYE + currency: TOKEN + cost: 0 + rarity: LEGENDARY + item: "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" + + ISLAND_TOPPERS: + items: [ ] + + DEATH_CRIES: + items: [ ] + + SHOPKEEPER_SKINS: + descriptionKey: bedwars.cosmetics.shopkeeper_skins.description + favoriteable: true + random: true + defaultSelectionId: blacksmith + items: + - id: blacksmith + name: Blacksmith + iconMaterial: VILLAGER_SPAWN_EGG + rarity: COMMON + custom: + entity: VILLAGER + villager: BLACKSMITH + unlock: + method: FREE + + - id: skeleton + name: Skeleton + iconMaterial: SKELETON_SPAWN_EGG + rarity: COMMON + custom: + entity: SKELETON + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 5000 + + - id: zombie_pigman + name: Zombie Pigman + iconMaterial: POLAR_BEAR_SPAWN_EGG + rarity: COMMON + custom: + entity: ZOMBIE_PIGMAN + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 5000 + + - id: zombie + name: Zombie + iconMaterial: ZOMBIE_SPAWN_EGG + rarity: COMMON + custom: + entity: ZOMBIE + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 5000 + + - id: villager_zombie + name: Villager Zombie + iconMaterial: ZOMBIE_SPAWN_EGG + rarity: RARE + custom: + entity: VILLAGER_ZOMBIE + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 10000 + + - id: wither_skeleton + name: Wither Skeleton + iconMaterial: ENDERMAN_SPAWN_EGG + rarity: RARE + custom: + entity: WITHER_SKELETON + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 10000 + + - id: blaze + name: Blaze + iconMaterial: BLAZE_SPAWN_EGG + rarity: RARE + custom: + entity: BLAZE + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 10000 + + - id: bed_salesman + name: Bed Salesman + iconTexture: 574caa78ce6a461416407f41d9f5726fb7bd2b8a257c7472d26bededeaffd9c + rarity: EPIC + custom: + textures: eyJ0aW1lc3RhbXAiOjE0OTc1NDMyMjE1MjIsInByb2ZpbGVJZCI6ImRiYTJmMTE1NmNjMjQwMWJhOWU5YjRkMjdmN2M4OTdkIiwicHJvZmlsZU5hbWUiOiJjb2RlbmFtZV9CIiwic2lnbmF0dXJlUmVxdWlyZWQiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS81NzRjYWE3OGNlNmE0NjE0MTY0MDdmNDFkOWY1NzI2ZmI3YmQyYjhhMjU3Yzc0NzJkMjZiZWRlZGVhZmZkOWMifSwiQ0FQRSI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzVjM2NhN2VlMmE0OThmMWI1ZDI1OGQ1ZmE5MjdlNjNlNDMzMTQzYWRkNTUzOGNmNjNiNmE5Yjc4YWU3MzUifX19 + signature: null + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 25000 + + - id: creeper + name: Creeper + iconMaterial: CREEPER_SPAWN_EGG + rarity: COMMON + custom: + entity: CREEPER + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 5000 + + - id: witch + name: Witch + iconMaterial: WITCH_SPAWN_EGG + rarity: RARE + custom: + entity: WITCH + unlock: + method: CURRENCY + currency: BEDWARS_TOKENS + cost: 10000 + + KILL_MESSAGES: + items: [ ] + + GLYPHS: + items: [ ] + + BED_DESTROYS: + items: [ ] + + WOOD_SKINS: + descriptionKey: bedwars.cosmetics.wood_skins.description + defaultSelectionId: oak_plank + items: + - id: oak_plank + name: Oak Plank + iconMaterial: OAK_PLANKS + selectionValue: OAK_PLANKS + rarity: COMMON + unlock: + method: FREE + + - id: birch_plank + name: Birch Plank + iconMaterial: BIRCH_PLANKS + selectionValue: BIRCH_PLANKS + rarity: RARE + unlock: + method: RANK + requiredRank: VIP_PLUS + + - id: spruce_plank + name: Spruce Plank + iconMaterial: SPRUCE_PLANKS + selectionValue: SPRUCE_PLANKS + rarity: RARE + unlock: + method: RANK + requiredRank: VIP + + - id: jungle_plank + name: Jungle Plank + iconMaterial: JUNGLE_PLANKS + selectionValue: JUNGLE_PLANKS + rarity: EPIC + unlock: + method: RANK + requiredRank: MVP + + - id: acacia_plank + name: Acacia Plank + iconMaterial: ACACIA_PLANKS + selectionValue: ACACIA_PLANKS + rarity: EPIC + unlock: + method: RANK + requiredRank: MVP_PLUS + + - id: dark_oak_plank + name: Dark Oak Plank + iconMaterial: DARK_OAK_PLANKS + selectionValue: DARK_OAK_PLANKS + rarity: LEGENDARY + unlock: + method: RANK + requiredRank: MVP_PLUS_PLUS + + - id: dark_oak_log + name: Dark Oak Log + iconMaterial: DARK_OAK_LOG + selectionValue: DARK_OAK_LOG + rarity: LEGENDARY + unlock: + method: CUSTOM + customResolverKey: bedwars_tournament_hall_unlock + customDisplayText: "Unlocked in Tournament Hall!" + + - id: acacia_log + name: Acacia Log + iconMaterial: ACACIA_LOG + selectionValue: ACACIA_LOG + rarity: LEGENDARY + unlock: + method: CUSTOM + customResolverKey: bedwars_tournament_hall_unlock + customDisplayText: "Unlocked in Tournament Hall!" + + - id: jungle_log + name: Jungle Log + iconMaterial: JUNGLE_LOG + selectionValue: JUNGLE_LOG + rarity: LEGENDARY + unlock: + method: CUSTOM + customResolverKey: bedwars_tournament_hall_unlock + customDisplayText: "Unlocked in Tournament Hall!" + + - id: birch_log + name: Birch Log + iconMaterial: BIRCH_LOG + selectionValue: BIRCH_LOG + rarity: LEGENDARY + unlock: + method: CUSTOM + customResolverKey: bedwars_tournament_hall_unlock + customDisplayText: "Unlocked in Tournament Hall!" + + - id: spruce_log + name: Spruce Log + iconMaterial: SPRUCE_LOG + selectionValue: SPRUCE_LOG + rarity: LEGENDARY + unlock: + method: CUSTOM + customResolverKey: bedwars_tournament_hall_unlock + customDisplayText: "Unlocked in Tournament Hall!" + + - id: oak_log + name: Oak Log + iconMaterial: OAK_LOG + selectionValue: OAK_LOG + rarity: LEGENDARY + unlock: + method: CUSTOM + customResolverKey: bedwars_tournament_hall_unlock + customDisplayText: "Unlocked in Tournament Hall!" + + FIGURINES: + items: [ ] diff --git a/configuration/bedwars/maps.json b/configuration/bedwars/maps.json index dfe19e64d..545a36f1b 100644 --- a/configuration/bedwars/maps.json +++ b/configuration/bedwars/maps.json @@ -6,22 +6,21 @@ "configuration": { "types": [ "SOLO", - "DOUBLES", - "ULTIMATE_DOUBLES" + "DOUBLES" ], "generatorSpeed": "SLOW", "bounds": { "x": { - "min": -100, - "max": 100 + "min": -100.0, + "max": 100.0 }, "y": { - "min": -100, - "max": 100 + "min": -100.0, + "max": 100.0 }, "z": { - "min": -100, - "max": 100 + "min": -100.0, + "max": 100.0 } }, "teams": { @@ -29,19 +28,25 @@ "shop": { "item": { "x": -34.5, - "y": 63, - "z": -87 + "y": 63.0, + "z": -87.0, + "yaw": 0.0, + "pitch": 0.0 }, "team": { "x": -44.5, "y": 63.0, - "z": -87 + "z": -87.0, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { "x": -39.5, "y": 63.5, - "z": -87 + "z": -87.0, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { @@ -58,26 +63,34 @@ "generator": { "x": -39.5, "y": 62.5, - "z": -89.5 + "z": -89.5, + "yaw": 0.0, + "pitch": 0.0 } }, "BLUE": { "shop": { "item": { "x": 45.5, - "y": 67, - "z": -87 + "y": 67.0, + "z": -87.0, + "yaw": 0.0, + "pitch": 0.0 }, "team": { "x": 35.5, "y": 67.0, - "z": -87 + "z": -87.0, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { - "x": 40, - "y": 67, - "z": -86 + "x": 40.0, + "y": 67.0, + "z": -86.0, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { @@ -92,64 +105,80 @@ } }, "generator": { - "x": 40, + "x": 40.0, "y": 66.5, - "z": -89.5 + "z": -89.5, + "yaw": 0.0, + "pitch": 0.0 } }, "GREEN": { "shop": { "item": { - "x": 88, - "y": 67, - "z": -34.5 + "x": 88.0, + "y": 67.0, + "z": -34.5, + "yaw": 0.0, + "pitch": 0.0 }, "team": { - "x": 88, + "x": 88.0, "y": 67.0, - "z": -44.5 + "z": -44.5, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { "x": 90.5, "y": 66.5, - "z": -39.5 + "z": -39.5, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { - "x": 77.0, - "y": 67.0, - "z": -40.0 + "x": 77, + "y": 67, + "z": -40 }, "head": { - "x": 78.0, - "y": 67.0, - "z": -40.0 + "x": 78, + "y": 67, + "z": -40 } }, "generator": { "x": 90.5, "y": 66.5, - "z": -39.5 + "z": -39.5, + "yaw": 0.0, + "pitch": 0.0 } }, "YELLOW": { "shop": { "item": { - "x": 88, - "y": 63, - "z": 45.5 + "x": 88.0, + "y": 63.0, + "z": 45.5, + "yaw": 0.0, + "pitch": 0.0 }, "team": { - "x": 88, - "y": 63, - "z": 35.5 + "x": 88.0, + "y": 63.0, + "z": 35.5, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { - "x": 87, - "y": 63, - "z": 40.5 + "x": 87.0, + "y": 63.0, + "z": 40.5, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { @@ -164,28 +193,36 @@ } }, "generator": { - "x": 91, + "x": 91.0, "y": 62.5, - "z": 40 + "z": 40.0, + "yaw": 0.0, + "pitch": 0.0 } }, "AQUA": { "shop": { "item": { "x": 35.5, - "y": 63, - "z": 88 + "y": 63.0, + "z": 88.0, + "yaw": 0.0, + "pitch": 0.0 }, "team": { "x": 45.5, - "y": 63, - "z": 87 + "y": 63.0, + "z": 87.0, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { - "x": 40, - "y": 63, - "z": 87 + "x": 40.0, + "y": 63.0, + "z": 87.0, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { @@ -202,26 +239,34 @@ "generator": { "x": 40.45072943525783, "y": 62.5, - "z": 90.40293169875406 + "z": 90.40293169875406, + "yaw": 0.0, + "pitch": 0.0 } }, "WHITE": { "shop": { "item": { "x": -44.5, - "y": 67, - "z": 88 + "y": 67.0, + "z": 88.0, + "yaw": 0.0, + "pitch": 0.0 }, "team": { "x": -34.5, - "y": 67, - "z": 88 + "y": 67.0, + "z": 88.0, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { - "x": -39, - "y": 67, - "z": 87.5 + "x": -39.0, + "y": 67.0, + "z": 87.5, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { @@ -238,26 +283,34 @@ "generator": { "x": -39.44410483123021, "y": 66.5, - "z": 90.53311018391065 + "z": 90.53311018391065, + "yaw": 0.0, + "pitch": 0.0 } }, "PINK": { "shop": { "item": { - "x": -87, - "y": 67, - "z": 35.5 + "x": -87.0, + "y": 67.0, + "z": 35.5, + "yaw": 0.0, + "pitch": 0.0 }, "team": { - "x": -87, - "y": 67, - "z": 45.5 + "x": -87.0, + "y": 67.0, + "z": 45.5, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { "x": -86.5, - "y": 67, - "z": 40.5 + "y": 67.0, + "z": 40.5, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { @@ -274,26 +327,34 @@ "generator": { "x": -89.45613002996294, "y": 66.5, - "z": 40.45822771042927 + "z": 40.45822771042927, + "yaw": 0.0, + "pitch": 0.0 } }, "GRAY": { "shop": { "item": { - "x": -87, - "y": 63, - "z": -44.5 + "x": -87.0, + "y": 63.0, + "z": -44.5, + "yaw": 0.0, + "pitch": 0.0 }, "team": { - "x": -87, - "y": 63, - "z": -34.5 + "x": -87.0, + "y": 63.0, + "z": -34.5, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { "x": -86.5, - "y": 63, - "z": -39.5 + "y": 63.0, + "z": -39.5, + "yaw": 0.0, + "pitch": 0.0 }, "bed": { "feet": { @@ -308,74 +369,92 @@ } }, "generator": { - "x": -90, + "x": -90.0, "y": 62.5, - "z": -39.5 + "z": -39.5, + "yaw": 0.0, + "pitch": 0.0 } } }, "locations": { - "spectator": { - "x": 0, - "y": 64, - "z": 0 - }, "waiting": { - "x": 0, - "y": 118, - "z": 0 + "x": 0.0, + "y": 118.0, + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 + }, + "spectator": { + "x": 0.0, + "y": 64.0, + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 } }, - "global_generator": { - "diamond": { - "amount": 1, - "max": 4, + "globalGenerator": { + "DIAMOND": { "locations": [ { "x": -39.5, - "y": 61, - "z": -39.5 + "y": 61.0, + "z": -39.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 40.5, - "y": 65, - "z": -39.5 + "y": 65.0, + "z": -39.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 40.5, - "y": 61, - "z": 40.5 + "y": 61.0, + "z": 40.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": -39.5, - "y": 65, - "z": 40.5 + "y": 65.0, + "z": 40.5, + "yaw": 0.0, + "pitch": 0.0 } ] }, - "emerald": { - "amount": 1, - "max": 2, + "EMERALD": { "locations": [ { "x": -11.5, - "y": 65, - "z": 12.5 + "y": 65.0, + "z": 12.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": -11.5, - "y": 61, - "z": -11.5 + "y": 61.0, + "z": -11.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 12.5, - "y": 65, - "z": -11.5 + "y": 65.0, + "z": -11.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 12.5, - "y": 61, - "z": 12.5 + "y": 61.0, + "z": 12.5, + "yaw": 0.0, + "pitch": 0.0 } ] } @@ -391,6 +470,7 @@ "DOUBLES", "ULTIMATE_DOUBLES" ], + "generatorSpeed": "SLOW", "bounds": { "x": { "min": -100.0, @@ -412,38 +492,42 @@ "x": -82.02040193311008, "y": 66.0, "z": 26.41980214690541, - "pitch": -0.9002611, - "yaw": -0.3010254 + "yaw": -0.3010254, + "pitch": -0.9002611 }, "team": { "x": -82.03912265565305, "y": 66.0, - "z": 38.52496280339181 + "z": 38.52496280339181, + "yaw": 0.0, + "pitch": 0.0 } }, "spawn": { "x": -82.45194161144515, "y": 66.0, "z": 32.51095973557253, - "pitch": -0.9000542, - "yaw": -89.387085 + "yaw": -89.387085, + "pitch": -0.9000542 }, "bed": { "feet": { - "x": -69.5, - "y": 66.0, - "z": 32.5 + "x": -70, + "y": 66, + "z": 32 }, "head": { - "x": -70.5, - "y": 66.0, - "z": 32.5 + "x": -71, + "y": 66, + "z": 32 } }, "generator": { "x": -86.0, "y": 65.5, - "z": 31.5 + "z": 31.5, + "yaw": 0.0, + "pitch": 0.0 } }, "WHITE": { @@ -452,40 +536,42 @@ "x": -37.57120528835294, "y": 66.0, "z": 82.97098866205523, - "pitch": -1.200244, - "yaw": -90.00214 + "yaw": -90.00214, + "pitch": -1.200244 }, "team": { "x": -25.504363571226587, "y": 66.0, "z": 82.96805231054407, - "pitch": -1.9502572, - "yaw": 89.39459 + "yaw": 89.39459, + "pitch": -1.9502572 } }, "spawn": { "x": -31.489605948109872, "y": 66.0, "z": 83.4640637242984, - "pitch": -0.15010078, - "yaw": -179.40198 + "yaw": -179.40198, + "pitch": -0.15010078 }, "bed": { "feet": { - "x": -31.5, - "y": 66.0, - "z": 70.5 + "x": -32, + "y": 66, + "z": 70 }, "head": { - "x": -31.5, - "y": 66.0, - "z": 71.5 + "x": -32, + "y": 66, + "z": 71 } }, "generator": { "x": -32.0, "y": 65.5, - "z": 85.5 + "z": 85.5, + "yaw": 0.0, + "pitch": 0.0 } }, "BLUE": { @@ -494,40 +580,42 @@ "x": 38.651112821199156, "y": 66.0, "z": -82.0636611406802, - "pitch": -2.1000006, - "yaw": 89.842865 + "yaw": 89.842865, + "pitch": -2.1000006 }, "team": { "x": 26.513876353954437, "y": 66.0, "z": -81.96871672001237, - "pitch": -2.0998929, - "yaw": -90.00635 + "yaw": -90.00635, + "pitch": -2.0998929 } }, "spawn": { "x": 32.44825455698304, "y": 66.0, "z": -82.21619659979275, - "pitch": -1.3502306, - "yaw": -0.28649902 + "yaw": -0.28649902, + "pitch": -1.3502306 }, "bed": { "feet": { - "x": 32.5, - "y": 66.0, - "z": -69.5 + "x": 32, + "y": 66, + "z": -70 }, "head": { - "x": 32.5, - "y": 66.0, - "z": -70.5 + "x": 32, + "y": 66, + "z": -71 } }, "generator": { "x": 32.0, "y": 65.5, - "z": -86.5 + "z": -86.5, + "yaw": 0.0, + "pitch": 0.0 } }, "GREEN": { @@ -536,40 +624,42 @@ "x": 83.02754376288796, "y": 66.0, "z": -25.50247371161989, - "pitch": -0.8998925, - "yaw": 179.69226 + "yaw": 179.69226, + "pitch": -0.8998925 }, "team": { "x": 83.01808132101671, "y": 66.0, "z": -37.4449225565394, - "pitch": 0.7500627, - "yaw": 0.89160156 + "yaw": 0.89160156, + "pitch": 0.7500627 } }, "spawn": { "x": 83.52472511460185, "y": 66.0, "z": -31.47239674724424, - "pitch": -1.9499904, - "yaw": 90.308716 + "yaw": 90.308716, + "pitch": -1.9499904 }, "bed": { "feet": { - "x": 70.5, - "y": 66.0, - "z": -31.5 + "x": 70, + "y": 66, + "z": -32 }, "head": { - "x": 71.5, - "y": 66.0, - "z": -31.5 + "x": 71, + "y": 66, + "z": -32 } }, "generator": { "x": 87.07588737864218, "y": 65.5, - "z": -31.54334025712658 + "z": -31.54334025712658, + "yaw": 0.0, + "pitch": 0.0 } }, "GRAY": { @@ -578,40 +668,42 @@ "x": -81.97052279318929, "y": 66.0, "z": -37.314472093522035, - "pitch": -1.4999375, - "yaw": -0.00012207031 + "yaw": -0.00012207031, + "pitch": -1.4999375 }, "team": { "x": -81.90479994981206, "y": 66.0, "z": -25.66597099278967, - "pitch": -0.6000788, - "yaw": 179.39453 + "yaw": 179.39453, + "pitch": -0.6000788 } }, "spawn": { "x": -82.25697683329115, "y": 66.0, "z": -31.5320875690394, - "pitch": -1.2003078, - "yaw": -89.97522 + "yaw": -89.97522, + "pitch": -1.2003078 }, "bed": { "feet": { - "x": -69.5, - "y": 66.0, - "z": -31.5 + "x": -70, + "y": 66, + "z": -32 }, "head": { - "x": -70.5, - "y": 66.0, - "z": -31.5 + "x": -71, + "y": 66, + "z": -32 } }, "generator": { "x": -86.0, "y": 65.5, - "z": -32.5 + "z": -32.5, + "yaw": 0.0, + "pitch": 0.0 } }, "RED": { @@ -620,40 +712,42 @@ "x": -25.54262467705194, "y": 66.0, "z": -82.05912286154171, - "pitch": -1.4999728, - "yaw": 89.54819 + "yaw": 89.54819, + "pitch": -1.4999728 }, "team": { "x": -37.470634976194255, "y": 66.0, "z": -81.95370501834397, - "pitch": -1.3499578, - "yaw": -90.30185 + "yaw": -90.30185, + "pitch": -1.3499578 } }, "spawn": { "x": -31.429089110829988, "y": 66.0, "z": -82.53114534212739, - "pitch": -0.90005803, - "yaw": -0.12023926 + "yaw": -0.12023926, + "pitch": -0.90005803 }, "bed": { "feet": { - "x": -31.5, - "y": 66.0, - "z": -69.5 + "x": -32, + "y": 66, + "z": -70 }, "head": { - "x": -31.5, - "y": 66.0, - "z": -70.5 + "x": -32, + "y": 66, + "z": -71 } }, "generator": { "x": -32.0, "y": 65.5, - "z": -86.5 + "z": -86.5, + "yaw": 0.0, + "pitch": 0.0 } }, "AQUA": { @@ -662,40 +756,42 @@ "x": 26.505141024953048, "y": 66.0, "z": 83.00298652272173, - "pitch": -1.350118, - "yaw": -89.855774 + "yaw": -89.855774, + "pitch": -1.350118 }, "team": { "x": 38.456872802559054, "y": 66.0, "z": 82.99083246172962, - "pitch": -2.2501745, - "yaw": 89.84564 + "yaw": 89.84564, + "pitch": -2.2501745 } }, "spawn": { "x": 32.49501313553803, "y": 66.0, "z": 83.53070551834745, - "pitch": -0.9000198, - "yaw": -179.5393 + "yaw": -179.5393, + "pitch": -0.9000198 }, "bed": { "feet": { - "x": 32.5, - "y": 66.0, - "z": 70.5 + "x": 32, + "y": 66, + "z": 70 }, "head": { - "x": 32.5, - "y": 66.0, - "z": 71.5 + "x": 32, + "y": 66, + "z": 71 } }, "generator": { "x": 32.0, "y": 65.5, - "z": 85.5 + "z": 85.5, + "yaw": 0.0, + "pitch": 0.0 } }, "YELLOW": { @@ -704,40 +800,42 @@ "x": 82.98866742168755, "y": 66.0, "z": 38.39515375216421, - "pitch": -0.9001085, - "yaw": 179.6955 + "yaw": 179.6955, + "pitch": -0.9001085 }, "team": { "x": 83.0012612940198, "y": 66.0, "z": 26.688584248556545, - "pitch": -1.6501008, - "yaw": -0.4545288 + "yaw": -0.4545288, + "pitch": -1.6501008 } }, "spawn": { "x": 83.44142018547358, "y": 66.0, "z": 32.516950785630655, - "pitch": -0.29999876, - "yaw": 89.557495 + "yaw": 89.557495, + "pitch": -0.29999876 }, "bed": { "feet": { - "x": 70.5, - "y": 66.0, - "z": 32.5 + "x": 70, + "y": 66, + "z": 32 }, "head": { - "x": 71.5, - "y": 66.0, - "z": 32.5 + "x": 71, + "y": 66, + "z": 32 } }, "generator": { "x": 86.0, "y": 65.5, - "z": 31.5 + "z": 31.5, + "yaw": 0.0, + "pitch": 0.0 } } }, @@ -745,69 +843,84 @@ "waiting": { "x": 0.0, "y": 98.0, - "z": 0.0 + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 }, "spectator": { "x": 0.0, "y": 80.0, - "z": 0.0 + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 } }, - "global_generator": { - "diamond": { - "amount": 1, - "max": 4, + "globalGenerator": { + "DIAMOND": { "locations": [ { "x": -31.5, "y": 65.0, - "z": -31.5 + "z": -31.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": -31.5, "y": 65.0, - "z": 32.5 + "z": 32.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 32.5, "y": 65.0, - "z": -31.5 + "z": -31.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 32.5, "y": 65.0, - "z": 32.5 + "z": 32.5, + "yaw": 0.0, + "pitch": 0.0 } ] }, - "emerald": { - "amount": 1, - "max": 2, + "EMERALD": { "locations": [ { "x": -11.5, "y": 66.0, - "z": 15.5 + "z": 15.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": -2.5, "y": 56.0, - "z": 8.5 + "z": 8.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 3.5, "y": 56.0, - "z": -7.5 + "z": -7.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 12.5, "y": 66.0, - "z": -14.5 + "z": -14.5, + "yaw": 0.0, + "pitch": 0.0 } ] } - }, - "generatorSpeed": "SLOW" + } } }, { @@ -819,6 +932,7 @@ "DOUBLES", "ULTIMATE_DOUBLES" ], + "generatorSpeed": "SLOW", "bounds": { "x": { "min": -100.0, @@ -840,40 +954,42 @@ "x": -90.01983756947546, "y": 66.0, "z": -39.42647039169151, - "pitch": -1.650027, - "yaw": -0.44920057 + "yaw": -0.44920057, + "pitch": -1.650027 }, "team": { "x": -89.968787336429, "y": 66.0, "z": -27.526147971256428, - "pitch": -1.6500026, - "yaw": -179.699 + "yaw": -179.699, + "pitch": -1.6500026 } }, "spawn": { "x": -91.50789125537915, "y": 66.0, "z": -33.4614884673225, - "pitch": -2.2500162, - "yaw": -89.69918 + "yaw": -89.69918, + "pitch": -2.2500162 }, "bed": { "feet": { - "x": -79.0, - "y": 66.0, - "z": -34.0 + "x": -79, + "y": 66, + "z": -34 }, "head": { - "x": -80.0, - "y": 66.0, - "z": -34.0 + "x": -80, + "y": 66, + "z": -34 } }, "generator": { "x": -94.88180199559939, "y": 65.5, - "z": -33.47895599279666 + "z": -33.47895599279666, + "yaw": 0.0, + "pitch": 0.0 } }, "PINK": { @@ -882,40 +998,42 @@ "x": -89.98054541737716, "y": 66.0, "z": 28.467331158132353, - "pitch": -1.3499774, - "yaw": -0.29211426 + "yaw": -0.29211426, + "pitch": -1.3499774 }, "team": { "x": -90.0204986863301, "y": 66.0, "z": 40.539796055189804, - "pitch": -0.5999382, - "yaw": -179.84265 + "yaw": -179.84265, + "pitch": -0.5999382 } }, "spawn": { "x": -91.52177451771917, "y": 66.0, "z": 34.55702213652238, - "pitch": -2.250019, - "yaw": -90.14459 + "yaw": -90.14459, + "pitch": -2.250019 }, "bed": { "feet": { - "x": -79.0, - "y": 66.0, - "z": 34.0 + "x": -79, + "y": 66, + "z": 34 }, "head": { - "x": -80.0, - "y": 66.0, - "z": 34.0 + "x": -80, + "y": 66, + "z": 34 } }, "generator": { "x": -95.00606472183632, "y": 65.5, - "z": 34.472998109442024 + "z": 34.472998109442024, + "yaw": 0.0, + "pitch": 0.0 } }, "RED": { @@ -924,40 +1042,42 @@ "x": -27.561475984770826, "y": 66.0, "z": -90.03896114532824, - "pitch": -1.650014, - "yaw": 90.00113 + "yaw": 90.00113, + "pitch": -1.650014 }, "team": { "x": -39.45869286910505, "y": 66.0, "z": -90.06382595988917, - "pitch": -1.2000538, - "yaw": -90.449036 + "yaw": -90.449036, + "pitch": -1.2000538 } }, "spawn": { "x": -33.48309695078257, "y": 66.0, "z": -91.54055720728049, - "pitch": -1.6500056, - "yaw": 0.30688477 + "yaw": 0.30688477, + "pitch": -1.6500056 }, "bed": { "feet": { - "x": -34.0, - "y": 66.0, - "z": -79.0 + "x": -34, + "y": 66, + "z": -79 }, "head": { - "x": -34.0, - "y": 66.0, - "z": -80.0 + "x": -34, + "y": 66, + "z": -80 } }, "generator": { "x": -34.0, "y": 65.5, - "z": -95.5 + "z": -95.5, + "yaw": 0.0, + "pitch": 0.0 } }, "WHITE": { @@ -966,40 +1086,42 @@ "x": -39.619789596622844, "y": 66.0, "z": 90.99516710124517, - "pitch": -2.400028, - "yaw": -90.1427 + "yaw": -90.1427, + "pitch": -2.400028 }, "team": { "x": -27.537757646848167, "y": 66.0, "z": 90.99331226247274, - "pitch": -0.15004088, - "yaw": 89.258545 + "yaw": 89.258545, + "pitch": -0.15004088 } }, "spawn": { "x": -33.41090708421141, "y": 66.0, "z": 92.54655583931589, - "pitch": -1.9500283, - "yaw": 179.25671 + "yaw": 179.25671, + "pitch": -1.9500283 }, "bed": { "feet": { - "x": -34.0, - "y": 66.0, - "z": 79.0 + "x": -34, + "y": 66, + "z": 79 }, "head": { - "x": -34.0, - "y": 66.0, - "z": 80.0 + "x": -34, + "y": 66, + "z": 80 } }, "generator": { "x": -34.0, "y": 65.5, - "z": 94.5 + "z": 94.5, + "yaw": 0.0, + "pitch": 0.0 } }, "BLUE": { @@ -1008,40 +1130,42 @@ "x": 40.398926387768824, "y": 66.0, "z": -89.99768047458974, - "pitch": -1.6500026, - "yaw": 89.55142 + "yaw": 89.55142, + "pitch": -1.6500026 }, "team": { "x": 28.46443708132082, "y": 66.0, "z": -90.01183225196914, - "pitch": -2.8500068, - "yaw": -89.998535 + "yaw": -89.998535, + "pitch": -2.8500068 } }, "spawn": { "x": 34.509823644268536, "y": 66.0, "z": -91.5133869660805, - "pitch": -2.850025, - "yaw": 0.30786133 + "yaw": 0.30786133, + "pitch": -2.850025 }, "bed": { "feet": { - "x": 34.0, - "y": 66.0, - "z": -79.0 + "x": 34, + "y": 66, + "z": -79 }, "head": { - "x": 34.0, - "y": 66.0, - "z": -80.0 + "x": 34, + "y": 66, + "z": -80 } }, "generator": { "x": 34.0, "y": 65.5, - "z": -95.5 + "z": -95.5, + "yaw": 0.0, + "pitch": 0.0 } }, "AQUA": { @@ -1050,40 +1174,42 @@ "x": 28.41990219468591, "y": 66.0, "z": 91.06331403239552, - "pitch": -2.7000225, - "yaw": -91.04541 + "yaw": -91.04541, + "pitch": -2.7000225 }, "team": { "x": 40.36172087467049, "y": 66.0, "z": 91.06411210174763, - "pitch": -0.90007347, - "yaw": 90.15213 + "yaw": 90.15213, + "pitch": -0.90007347 } }, "spawn": { "x": 34.524004250348334, "y": 66.0, "z": 92.45408851220344, - "pitch": -1.2000084, - "yaw": -179.84644 + "yaw": -179.84644, + "pitch": -1.2000084 }, "bed": { "feet": { - "x": 34.0, - "y": 66.0, - "z": 79.0 + "x": 34, + "y": 66, + "z": 79 }, "head": { - "x": 34.0, - "y": 66.0, - "z": 80.0 + "x": 34, + "y": 66, + "z": 80 } }, "generator": { "x": 34.59259801675937, "y": 65.5, - "z": 95.53276513823602 + "z": 95.53276513823602, + "yaw": 0.0, + "pitch": 0.0 } }, "GREEN": { @@ -1092,40 +1218,42 @@ "x": 90.97755565005453, "y": 66.0, "z": -27.37446350690706, - "pitch": -1.1999909, - "yaw": 178.95184 + "yaw": 178.95184, + "pitch": -1.1999909 }, "team": { "x": 91.01148627742812, "y": 66.0, "z": -39.56285225865746, - "pitch": -1.3499583, - "yaw": -0.14828491 + "yaw": -0.14828491, + "pitch": -1.3499583 } }, "spawn": { "x": 92.35244930696713, "y": 66.0, "z": -33.540694954234894, - "pitch": -0.9000325, - "yaw": 89.85184 + "yaw": 89.85184, + "pitch": -0.9000325 }, "bed": { "feet": { - "x": 79.0, - "y": 66.0, - "z": -34.0 + "x": 79, + "y": 66, + "z": -34 }, "head": { - "x": 80.0, - "y": 66.0, - "z": -34.0 + "x": 80, + "y": 66, + "z": -34 } }, "generator": { "x": 95.59669657935473, "y": 65.5, - "z": -33.41313094325075 + "z": -33.41313094325075, + "yaw": 0.0, + "pitch": 0.0 } }, "YELLOW": { @@ -1134,40 +1262,42 @@ "x": 90.99918379500014, "y": 66.0, "z": 40.58232810998059, - "pitch": -0.45014584, - "yaw": -179.9967 + "yaw": -179.9967, + "pitch": -0.45014584 }, "team": { "x": 91.0230495348164, "y": 66.0, "z": 28.463560410301472, - "pitch": -2.4001167, - "yaw": 0.7530823 + "yaw": 0.7530823, + "pitch": -2.4001167 } }, "spawn": { "x": 92.47357850698647, "y": 66.0, "z": 34.47878025929901, - "pitch": -2.100014, - "yaw": 89.404785 + "yaw": 89.404785, + "pitch": -2.100014 }, "bed": { "feet": { - "x": 79.0, - "y": 66.0, - "z": 34.0 + "x": 79, + "y": 66, + "z": 34 }, "head": { - "x": 80.0, - "y": 66.0, - "z": 34.0 + "x": 80, + "y": 66, + "z": 34 } }, "generator": { "x": 95.45996664371597, "y": 65.5, - "z": 34.71001348863422 + "z": 34.71001348863422, + "yaw": 0.0, + "pitch": 0.0 } } }, @@ -1175,69 +1305,84 @@ "waiting": { "x": 0.0, "y": 118.0, - "z": 0.0 + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 }, "spectator": { "x": 3.5, "y": 81.0, - "z": 3.5 + "z": 3.5, + "yaw": 0.0, + "pitch": 0.0 } }, - "global_generator": { - "diamond": { - "amount": 1, - "max": 4, + "globalGenerator": { + "DIAMOND": { "locations": [ { "x": -38.5, "y": 71.0, - "z": -38.5 + "z": -38.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": -38.5, "y": 71.0, - "z": 39.5 + "z": 39.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 39.5, "y": 71.0, - "z": -38.5 + "z": -38.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 39.5, "y": 71.0, - "z": 39.5 + "z": 39.5, + "yaw": 0.0, + "pitch": 0.0 } ] }, - "emerald": { - "amount": 1, - "max": 2, + "EMERALD": { "locations": [ { "x": -10.5, "y": 71.0, - "z": -12.5 + "z": -12.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": -10.5, "y": 80.0, - "z": -10.5 + "z": -10.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 11.5, "y": 80.0, - "z": 11.5 + "z": 11.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 11.5, "y": 71.0, - "z": 13.5 + "z": 13.5, + "yaw": 0.0, + "pitch": 0.0 } ] } - }, - "generatorSpeed": "SLOW" + } } }, { @@ -1249,6 +1394,7 @@ "DOUBLES", "ULTIMATE_DOUBLES" ], + "generatorSpeed": "SLOW", "bounds": { "x": { "min": -100.0, @@ -1270,40 +1416,42 @@ "x": -85.0108875529608, "y": 65.0, "z": -31.495267847506838, - "pitch": -0.74988824, - "yaw": 0.014282227 + "yaw": 0.014282227, + "pitch": -0.74988824 }, "team": { "x": -85.0596923424721, "y": 65.0, "z": -20.629669566674032, - "pitch": -0.15006073, - "yaw": -179.98706 + "yaw": -179.98706, + "pitch": -0.15006073 } }, "spawn": { "x": -85.40322458207508, "y": 65.0, "z": -25.536412033357305, - "pitch": -1.5000191, - "yaw": -90.13562 + "yaw": -90.13562, + "pitch": -1.5000191 }, "bed": { "feet": { - "x": -72.0, - "y": 66.0, - "z": -26.0 + "x": -72, + "y": 66, + "z": -26 }, "head": { - "x": -73.0, - "y": 66.0, - "z": -26.0 + "x": -73, + "y": 66, + "z": -26 } }, "generator": { "x": -87.5673901168893, "y": 64.5, - "z": -25.483414467520394 + "z": -25.483414467520394, + "yaw": 0.0, + "pitch": 0.0 } }, "PINK": { @@ -1312,40 +1460,42 @@ "x": -85.04315008957276, "y": 65.0, "z": 20.63051632450276, - "pitch": -0.6002544, - "yaw": -0.001159668 + "yaw": -0.001159668, + "pitch": -0.6002544 }, "team": { "x": -85.02157519497271, "y": 65.0, "z": 31.600896188308486, - "pitch": -0.1502753, - "yaw": -179.70134 + "yaw": -179.70134, + "pitch": -0.1502753 } }, "spawn": { "x": -85.33047397827768, "y": 65.0, "z": 26.50267595410961, - "pitch": -1.1999936, - "yaw": -90.59955 + "yaw": -90.59955, + "pitch": -1.1999936 }, "bed": { "feet": { - "x": -72.0, - "y": 66.0, - "z": 26.0 + "x": -72, + "y": 66, + "z": 26 }, "head": { - "x": -73.0, - "y": 66.0, - "z": 26.0 + "x": -73, + "y": 66, + "z": 26 } }, "generator": { "x": -87.49264594588892, "y": 64.5, - "z": 26.52547932011008 + "z": 26.52547932011008, + "yaw": 0.0, + "pitch": 0.0 } }, "GREEN": { @@ -1354,40 +1504,42 @@ "x": 92.04099251477956, "y": 65.0, "z": -19.512879069070113, - "pitch": 0.15020467, - "yaw": 179.57922 + "yaw": 179.57922, + "pitch": 0.15020467 }, "team": { "x": 92.03963698940655, "y": 65.0, "z": -30.640048146160893, - "pitch": -1.3498296, - "yaw": 0.026367188 + "yaw": 0.026367188, + "pitch": -1.3498296 } }, "spawn": { "x": 92.4755666172137, "y": 65.0, "z": -25.491783290995787, - "pitch": -1.3500005, - "yaw": 90.17285 + "yaw": 90.17285, + "pitch": -1.3500005 }, "bed": { "feet": { - "x": 78.0, - "y": 66.0, - "z": -26.0 + "x": 78, + "y": 66, + "z": -26 }, "head": { - "x": 79.0, - "y": 66.0, - "z": -26.0 + "x": 79, + "y": 66, + "z": -26 } }, "generator": { "x": 94.50786462929776, "y": 64.5, - "z": -25.561788917213132 + "z": -25.561788917213132, + "yaw": 0.0, + "pitch": 0.0 } }, "YELLOW": { @@ -1396,40 +1548,42 @@ "x": 92.00019708368568, "y": 65.0, "z": 32.52003900590035, - "pitch": -1.0499948, - "yaw": 179.56714 + "yaw": 179.56714, + "pitch": -1.0499948 }, "team": { "x": 92.05260636514082, "y": 65.0, "z": 21.62810314464048, - "pitch": -0.90015817, - "yaw": 0.01953125 + "yaw": 0.01953125, + "pitch": -0.90015817 } }, "spawn": { "x": 92.5016778646452, "y": 65.0, "z": 26.503177814113776, - "pitch": -1.0500311, - "yaw": 89.869385 + "yaw": 89.869385, + "pitch": -1.0500311 }, "bed": { "feet": { - "x": 78.0, - "y": 66.0, - "z": 26.0 + "x": 78, + "y": 66, + "z": 26 }, "head": { - "x": 79.0, - "y": 66.0, - "z": 26.0 + "x": 79, + "y": 66, + "z": 26 } }, "generator": { "x": 94.52302376614784, "y": 64.5, - "z": 26.495665102706702 + "z": 26.495665102706702, + "yaw": 0.0, + "pitch": 0.0 } }, "RED": { @@ -1438,40 +1592,42 @@ "x": -16.42898002455651, "y": 65.0, "z": -87.95377324913402, - "pitch": -0.6001133, - "yaw": 90.47034 + "yaw": 90.47034, + "pitch": -0.6001133 }, "team": { "x": -27.56787077510041, "y": 65.0, "z": -88.0152493117479, - "pitch": -0.15003474, - "yaw": -89.38147 + "yaw": -89.38147, + "pitch": -0.15003474 } }, "spawn": { "x": -22.519568104899527, "y": 65.0, "z": -88.48850061662141, - "pitch": -0.15001334, - "yaw": 0.9182129 + "yaw": 0.9182129, + "pitch": -0.15001334 }, "bed": { "feet": { - "x": -23.0, - "y": 66.0, - "z": -75.0 + "x": -23, + "y": 66, + "z": -75 }, "head": { - "x": -23.0, - "y": 66.0, - "z": -76.0 + "x": -23, + "y": 66, + "z": -76 } }, "generator": { "x": -22.5312774980518, "y": 64.5, - "z": -90.57548230296806 + "z": -90.57548230296806, + "yaw": 0.0, + "pitch": 0.0 } }, "WHITE": { @@ -1480,40 +1636,42 @@ "x": -28.574379786349034, "y": 65.0, "z": 89.02285078530015, - "pitch": -1.0500664, - "yaw": -89.836914 + "yaw": -89.836914, + "pitch": -1.0500664 }, "team": { "x": -17.461621765421107, "y": 65.0, "z": 88.943122501835, - "pitch": 2.5499506, - "yaw": 90.763306 + "yaw": 90.763306, + "pitch": 2.5499506 } }, "spawn": { "x": -22.471525601515623, "y": 65.0, "z": 89.57296851701679, - "pitch": -2.8500109, - "yaw": 178.80945 + "yaw": 178.80945, + "pitch": -2.8500109 }, "bed": { "feet": { - "x": -23.0, - "y": 66.0, - "z": 75.0 + "x": -23, + "y": 66, + "z": 75 }, "head": { - "x": -23.0, - "y": 66.0, - "z": 76.0 + "x": -23, + "y": 66, + "z": 76 } }, "generator": { "x": -22.412900889637193, "y": 64.5, - "z": 91.23618220055619 + "z": 91.23618220055619, + "yaw": 0.0, + "pitch": 0.0 } }, "BLUE": { @@ -1522,40 +1680,42 @@ "x": 35.485826946930615, "y": 65.0, "z": -88.04529512429717, - "pitch": 0.14996125, - "yaw": 89.87683 + "yaw": 89.87683, + "pitch": 0.14996125 }, "team": { "x": 24.622361774925704, "y": 65.0, "z": -88.05656319005925, - "pitch": -1.3499969, - "yaw": -90.5741 + "yaw": -90.5741, + "pitch": -1.3499969 } }, "spawn": { "x": 29.49428195060743, "y": 65.0, "z": -88.48868721971608, - "pitch": -0.90002465, - "yaw": 0.17382812 + "yaw": 0.17382812, + "pitch": -0.90002465 }, "bed": { "feet": { - "x": 29.0, - "y": 66.0, - "z": -75.0 + "x": 29, + "y": 66, + "z": -75 }, "head": { - "x": 29.0, - "y": 66.0, - "z": -76.0 + "x": 29, + "y": 66, + "z": -76 } }, "generator": { "x": 29.49800786315674, "y": 64.5, - "z": -90.49292341421382 + "z": -90.49292341421382, + "yaw": 0.0, + "pitch": 0.0 } }, "AQUA": { @@ -1564,40 +1724,42 @@ "x": 23.46475353590089, "y": 65.0, "z": 89.00416751918755, - "pitch": -0.90002316, - "yaw": -89.68347 + "yaw": -89.68347, + "pitch": -0.90002316 }, "team": { "x": 34.48868965579855, "y": 65.0, "z": 88.9687709421603, - "pitch": -0.45002592, - "yaw": 90.31177 + "yaw": 90.31177, + "pitch": -0.45002592 } }, "spawn": { "x": 29.51989114105056, "y": 65.0, "z": 89.5076579294666, - "pitch": -1.5000246, - "yaw": -179.83789 + "yaw": -179.83789, + "pitch": -1.5000246 }, "bed": { "feet": { - "x": 29.0, - "y": 66.0, - "z": 75.0 + "x": 29, + "y": 66, + "z": 75 }, "head": { - "x": 29.0, - "y": 66.0, - "z": 76.0 + "x": 29, + "y": 66, + "z": 76 } }, "generator": { "x": 29.51437547667322, "y": 64.5, - "z": 91.54059238014068 + "z": 91.54059238014068, + "yaw": 0.0, + "pitch": 0.0 } } }, @@ -1605,70 +1767,546 @@ "waiting": { "x": 0.0, "y": 118.0, - "z": 0.0 + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 }, "spectator": { "x": 0.0, "y": 103.0, - "z": 0.0 + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 } }, - "global_generator": { - "diamond": { - "amount": 1, - "max": 4, + "globalGenerator": { + "DIAMOND": { "locations": [ { "x": -48.5, "y": 67.0, - "z": -51.5 + "z": -51.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": -48.5, "y": 67.0, - "z": 52.5 + "z": 52.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 55.5, "y": 67.0, - "z": -51.5 + "z": -51.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 55.5, "y": 67.0, - "z": 52.5 + "z": 52.5, + "yaw": 0.0, + "pitch": 0.0 } ] }, - "emerald": { - "amount": 1, - "max": 2, + "EMERALD": { "locations": [ { "x": -6.5, "y": 65.0, - "z": 14.5 + "z": 14.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 3.5, "y": 87.0, - "z": -6.5 + "z": -6.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 13.5, "y": 65.0, - "z": -13.5 + "z": -13.5, + "yaw": 0.0, + "pitch": 0.0 }, { "x": 3.5, "y": 87.0, - "z": 7.5 + "z": 7.5, + "yaw": 0.0, + "pitch": 0.0 + } + ] + } + } + } + }, + { + "id": "haven", + "name": "haven", + "configuration": { + "types": [ + "THREE_THREE_THREE_THREE", + "FOUR_FOUR_FOUR_FOUR", + "LUCKY_BLOCK_DOUBLES" + ], + "generatorSpeed": "SLOW", + "bounds": { + "x": { + "min": -125.0, + "max": 125.0 + }, + "y": { + "min": 0.0, + "max": 100.0 + }, + "z": { + "min": -125.0, + "max": 125.0 + } + }, + "teams": { + "RED": { + "shop": { + "item": { + "x": -5.643081030208206, + "y": 48.0, + "z": 105.00760245533807, + "yaw": -0.45004654, + "pitch": -89.55029 + }, + "team": { + "x": 6.513037234763775, + "y": 48.0, + "z": 104.95045523360692, + "yaw": -0.60003746, + "pitch": 90.29947 + } + }, + "spawn": { + "x": 0.4566740272757841, + "y": 48.0, + "z": 104.57865104045052, + "yaw": -0.9000152, + "pitch": 0 + }, + "bed": { + "feet": { + "x": 0, + "y": 46, + "z": 90 + }, + "head": { + "x": 0, + "y": 46, + "z": 91 + } + }, + "generator": { + "x": 0.48311192527610214, + "y": 47.5, + "z": 109.40563123435935, + "yaw": 0.0, + "pitch": 0.0 + } + }, + "BLUE": { + "shop": { + "item": { + "x": -104.00200548536833, + "y": 48.0, + "z": -5.511538167515957, + "yaw": -0.8999911, + "pitch": 0.1472168 + }, + "team": { + "x": -103.97642442586424, + "y": 48.0, + "z": 6.530339403426724, + "yaw": 0.3000191, + "pitch": -179.70227 + } + }, + "spawn": { + "x": -104.00035970966859, + "y": 48.0, + "z": 0.4982683648858232, + "yaw": 0.44997922, + "pitch": 0 + }, + "bed": { + "feet": { + "x": -90, + "y": 46, + "z": 0 + }, + "head": { + "x": -91, + "y": 46, + "z": 0 + } + }, + "generator": { + "x": -108.44139800163269, + "y": 47.5, + "z": 0.5066969091555289, + "yaw": 0.0, + "pitch": 0.0 + } + }, + "GREEN": { + "shop": { + "item": { + "x": 6.452209881084259, + "y": 48.0, + "z": -103.97213185082639, + "yaw": 0.14998366, + "pitch": 89.99768 + }, + "team": { + "x": -5.486204346304282, + "y": 48.0, + "z": -104.06431278356358, + "yaw": -0.6000095, + "pitch": -89.552734 + } + }, + "spawn": { + "x": 0.4816414347717442, + "y": 48.0, + "z": -103.96215353598399, + "yaw": -0.4500038, + "pitch": 0.14782715 + }, + "bed": { + "feet": { + "x": 0, + "y": 46, + "z": -90 + }, + "head": { + "x": 0, + "y": 46, + "z": -91 + } + }, + "generator": { + "x": 0.47573204880919545, + "y": 47.5, + "z": -108.50300788140555, + "yaw": 0.0, + "pitch": 0.0 + } + }, + "YELLOW": { + "shop": { + "item": { + "x": 104.98711045888756, + "y": 48.0, + "z": 6.566614067860879, + "yaw": -1.0500069, + "pitch": 179.09155 + }, + "team": { + "x": 104.96962792336748, + "y": 48.0, + "z": -5.542657550120672, + "yaw": 0.6000119, + "pitch": -0.4584961 + } + }, + "spawn": { + "x": 104.90221295849302, + "y": 48.0, + "z": 0.5618568772327801, + "yaw": 0.74996793, + "pitch": 91.04187 + }, + "bed": { + "feet": { + "x": 90, + "y": 46, + "z": 0 + }, + "head": { + "x": 91, + "y": 46, + "z": 0 + } + }, + "generator": { + "x": 109.46146206656485, + "y": 47.5, + "z": 0.5320753244557163, + "yaw": 0.0, + "pitch": 0.0 + } + } + }, + "locations": { + "waiting": { + "x": 0.45753038265154733, + "y": 120.0, + "z": 0.49395332083443444, + "yaw": 0.0, + "pitch": 0.0 + }, + "spectator": { + "x": 0.0, + "y": 70.0, + "z": 0.0, + "yaw": 0.0, + "pitch": 0.0 + } + }, + "globalGenerator": { + "EMERALD": { + "locations": [ + { + "x": 0.5, + "y": 51.0, + "z": -8.5, + "yaw": 0.0, + "pitch": 0.0 + }, + { + "x": 0.5, + "y": 51.0, + "z": 9.5, + "yaw": 0.0, + "pitch": 0.0 + } + ] + }, + "DIAMOND": { + "locations": [ + { + "x": -42.5, + "y": 48.0, + "z": -42.5, + "yaw": 0.0, + "pitch": 0.0 + }, + { + "x": -42.5, + "y": 48.0, + "z": 43.5, + "yaw": 0.0, + "pitch": 0.0 + }, + { + "x": 43.5, + "y": 48.0, + "z": -42.5, + "yaw": 0.0, + "pitch": 0.0 + }, + { + "x": 43.5, + "y": 48.0, + "z": 43.5, + "yaw": 0.0, + "pitch": 0.0 } ] } + } + } + }, + { + "id": "one_block", + "name": "One Block", + "configuration": { + "types": [ + "ONE_BLOCK" + ], + "bounds": { + "x": { + "min": -100.0, + "max": 100.0 + }, + "y": { + "min": 0.0, + "max": 150.0 + }, + "z": { + "min": -100.0, + "max": 100.0 + } }, - "generatorSpeed": "SLOW" + "teams": { + "BLUE": { + "spawn": { + "x": 18.0, + "y": 72.0, + "z": -9.0 + }, + "bed": { + "feet": { + "x": 18, + "y": 71, + "z": -9 + }, + "head": { + "x": 17, + "y": 71, + "z": -9 + } + } + }, + "RED": { + "spawn": { + "x": 18.0, + "y": 72.0, + "z": 8.0 + }, + "bed": { + "feet": { + "x": 18, + "y": 71, + "z": 8 + }, + "head": { + "x": 17, + "y": 71, + "z": 8 + } + } + }, + "GRAY": { + "spawn": { + "x": 8.0, + "y": 72.0, + "z": 18.0 + }, + "bed": { + "feet": { + "x": 8, + "y": 71, + "z": 18 + }, + "head": { + "x": 8, + "y": 71, + "z": 17 + } + } + }, + "PINK": { + "spawn": { + "x": -9.0, + "y": 72.0, + "z": 18.0 + }, + "bed": { + "feet": { + "x": -9, + "y": 71, + "z": 18 + }, + "head": { + "x": -9, + "y": 71, + "z": 17 + } + } + }, + "WHITE": { + "spawn": { + "x": -19.0, + "y": 72.0, + "z": 8.0 + }, + "bed": { + "feet": { + "x": -19, + "y": 71, + "z": 8 + }, + "head": { + "x": -18, + "y": 71, + "z": 8 + } + } + }, + "AQUA": { + "spawn": { + "x": -19.0, + "y": 72.0, + "z": -9.0 + }, + "bed": { + "feet": { + "x": -19, + "y": 71, + "z": -9 + }, + "head": { + "x": -18, + "y": 71, + "z": -9 + } + } + }, + "YELLOW": { + "spawn": { + "x": -9.0, + "y": 72.0, + "z": -19.0 + }, + "bed": { + "feet": { + "x": -9, + "y": 71, + "z": -19 + }, + "head": { + "x": -9, + "y": 71, + "z": -18 + } + } + }, + "GREEN": { + "spawn": { + "x": 8.0, + "y": 72.0, + "z": -19.0 + }, + "bed": { + "feet": { + "x": 8, + "y": 71, + "z": -19 + }, + "head": { + "x": 8, + "y": 71, + "z": -18 + } + } + } + }, + "locations": { + "waiting": { + "x": 0.0, + "y": 99.0, + "z": 6.0 + }, + "spectator": { + "x": 0.0, + "y": 99.0, + "z": 6.0 + } + } } } ] -} \ No newline at end of file +} diff --git a/configuration/i18n/en_US/bedwars.properties b/configuration/i18n/en_US/bedwars.properties deleted file mode 100644 index 8697635ec..000000000 --- a/configuration/i18n/en_US/bedwars.properties +++ /dev/null @@ -1,10 +0,0 @@ -bedwars.kill.died.default=" died." -bedwars.kill.died_by.default=" was killed by ." -bedwars.kill.projectile.default=" was shot by ." -bedwars.kill.assist.default=" was killed by 's ." -bedwars.kill.void.default=" fell in to the void." -bedwars.kill.void_by.default=" was knocked into the void by ." -bedwars.kill.bed.default="was destroyed by" -bedwars.kill.final_kill="FINAL KILL!" -bedwars.bed_destroyed="BED DESTRUCTION > Bed ." -bedwars.bed_destroyed_self="BED DESTRUCTION > Your bed ." diff --git a/configuration/i18n/en_US/general.properties b/configuration/i18n/en_US/general.properties new file mode 100644 index 000000000..e3b0ac9b5 --- /dev/null +++ b/configuration/i18n/en_US/general.properties @@ -0,0 +1 @@ +general.not_implemented=This feature hasn't been implemented yet. Open a Pull Request HERE to get it added quickly! \ No newline at end of file diff --git a/configuration/i18n/en_US/official/bedwars.properties b/configuration/i18n/en_US/official/bedwars.properties new file mode 100644 index 000000000..d0377197d --- /dev/null +++ b/configuration/i18n/en_US/official/bedwars.properties @@ -0,0 +1,4279 @@ +bedwars.click_to_play="CLICK TO PLAY" +bedwars.1="Bed Wars Solo" +bedwars.2="Bed Wars Doubles" +bedwars.3="Bed Wars 3v3v3v3" +bedwars.4="Bed Wars 4v4v4v4" +bedwars.5="CLICK TO OPEN" +bedwars.shopkeeper="Shopkeeper" +bedwars.7="Your Level: %%format%%" +bedwars.8="Progress: %%format%%" +bedwars.9="Total Kills: %%total%%" +bedwars.10="Total Wins: %%total%%" +bedwars.11="My Profile " +bedwars.12="Shop & My Cosmetics " +bedwars.13="Your Bed Wars Profile" +bedwars.14="Your Level: %%format%%" +bedwars.15="Achievements: %%progress%%" +bedwars.16="Current Winstreak: %%total%%" +bedwars.17="Bed Wars Level" +bedwars.18="Click for more!" +bedwars.19="Solo" +bedwars.20="Doubles" +bedwars.21="Bed Wars Shop" +bedwars.22="VISIT THE STORE" +bedwars.23="Fireworks Victory Dance" +bedwars.24="%%color%%%%name%%" +bedwars.25="Zombie Shopkeeper" +bedwars.26="Brick House Island Topper" +bedwars.27="%%rarity%%%%category%%" +bedwars.28="Brick House" +bedwars.29="Select a Kill Message package to replace chat messages when you kill players, Teams and break Beds!" +bedwars.30="Kill Messages" +bedwars.31="Select an Island Topper to decorate your island with! In Doubles and Teams Modes a random player's choice from each team is chosen." +bedwars.32="Island Toppers" +bedwars.33="Select particle Glyph images which display above your head when selected!" +bedwars.34="Change your projectile trail particle effect!" +bedwars.35="Let others know just how salty your tears are every time you die with these death cries!" +bedwars.36="Death Cries" +bedwars.37="A selection of various effects to choose from that will trigger whenever you final kill an enemy!" +bedwars.38="Select from various Shopkeeper skins, which will replace how the Shopkeepers look in-game! In Doubles and Teams Modes a random player's choice from each team is chosen." +bedwars.39="Shopkeeper Skins" +bedwars.40="Select a spray to decorate your base with!" +bedwars.41="Select the %%clean%%." +bedwars.42="Selecting this option disables your %%title%%." +bedwars.43="If you win, celebrate by riding a Wither - click to shoot Wither Skulls." +bedwars.44="If you win, celebrate by riding a Dragon capable of destroying the map." +bedwars.45="If you win, celebrate with Anvil raining from the sky." +bedwars.46="If you win, celebrate with a shower of fireworks!" +bedwars.47="If you win, a meteor shower will rain down from the sky." +bedwars.48="If you win, perform a Guardian summoning ritual." +bedwars.49="If you win, celebrate with your name in the sky!" +bedwars.50="Killing an enemy will let Cookies sprinkle out of you." +bedwars.51="Select the %%clean%%. This change is cosmetic." +bedwars.52="Unlocked on the store" +bedwars.53="Select the %%clean%% to spawn above your island." +bedwars.54="Plays the %%title%% upon killing an enemy." +bedwars.55="Select the %%clean%% as your Shopkeeper!" +bedwars.cosmetics.shopkeeper_skins.description="Select as your Shopkeeper." +bedwars.cosmetics.wood_skins.description.1="Select the Wood Skin to be used" +bedwars.cosmetics.wood_skins.description.2="when placing wood blocks." +bedwars.56="Spectator Settings " +bedwars.57="Play Again " +bedwars.58="Return to Lobby " +bedwars.59="Defend your Bed!" +bedwars.60="Diamond Upgrade" +bedwars.61="Select an Option or Sneak to Cancel." +bedwars.62="Time Played" +bedwars.63="+%%amount%% Bed Wars Experience" +bedwars.64="%%tc%%%%name%% disconnected" +bedwars.65="%%player%% fell into the void." +bedwars.66="Item Shop" +bedwars.67="Left Click: Cycle through Glyphs/Sprays" +bedwars.68="Right Click: Use Glyphs/Sprays" +bedwars.69="Click to get!" +bedwars.70="Spray Can" +bedwars.71="Melee" +bedwars.72="Items:" +bedwars.73=" ? %%name%%" +bedwars.74="Cost:" +bedwars.75="%%color%%10 Iron" +bedwars.76="You don't have enough %%resource%%!" +bedwars.77="%%color%%7 Gold" +bedwars.78="%%color%%4 Emerald" +bedwars.79="%%color%%10 Gold" +bedwars.80="Left click the Spray Can to cycle through your selected Glyphs and Sprays! Right click to use the selected Glyph or Spray!" +bedwars.81="Spray Can " +bedwars.82="Sprrrrr ..." +bedwars.83="You have no spray selected! Use the emerald in the lobby to select one!" +bedwars.84="Now selected: %%option%%" +bedwars.85="You cannot get another Spray Can if you already have one in your inventory!" +bedwars.86="If you get disconnected use /rejoin to join back in the game." +bedwars.87="Utility" +bedwars.88="%%color%%1 Emerald" +bedwars.89="%%color%%3 Gold" +bedwars.90="%%color%%50 Iron" +bedwars.91="%%color%%150 Iron" +bedwars.92="Fireball" +bedwars.93="%%color%%5 Gold" +bedwars.94="Upgrades" +bedwars.95="Gain Mining Fatigue I while within an 8 block radius of your bed." +bedwars.96="Cost: %%cost%%" +bedwars.97="Creates a Regeneration field around your base!" +bedwars.98="Your team will have 2 dragons instead of 1 during deathmatch!" +bedwars.99="Increases the spawn rate of Iron and Gold by %%percent%%%." +bedwars.100="All players on your team permanently gain Haste %%amplifier%%." +bedwars.101="Your team gets Sharpness %%level%% on all swords!" +bedwars.102="Your team gets Protection %%level%% on all armor pieces!" +bedwars.103="The next enemy to enter your base will receive Blindness and Slowness!" +bedwars.104="You don't have enough resources to unlock that upgrade!" +bedwars.105="Armor" +bedwars.106="Chainmail" +bedwars.107="%%color%%40 Iron" +bedwars.108="You will not lose this on death!" +bedwars.109="%%color%%12 Gold" +bedwars.110="%%color%%6 Emerald" +bedwars.111="Blocks" +bedwars.112="%%color%%4 Iron" +bedwars.113="%%color%%12 Iron" +bedwars.114="%%color%%24 Iron" +bedwars.115="%%color%%4 Gold" +bedwars.116="Position Bonus" +bedwars.117="TEAM ELIMINATED > %%tc%%%%tname%% Team has been eliminated!" +bedwars.118="%%tc%%%%tname%% Team has won the game!" +bedwars.119="Win" +bedwars.120="You earned %%amount%% Bed Wars Experience" +bedwars.121="Ranged" +bedwars.122="%%color%%2 Gold" +bedwars.123="%%color%%24 Gold" +bedwars.124="Tools" +bedwars.125="%%color%%30 Iron" +bedwars.126="%%color%%20 Iron" +bedwars.127="%%color%%8 Gold" +bedwars.128="Potions" +bedwars.129="Speed II Potion" +bedwars.130="Jump V Potion" +bedwars.131="%%name%% purchased %%item%%" +bedwars.132="You can only break blocks placed by a player!" +bedwars.133="You can't destroy your own bed!" +bedwars.134="BED DESTRUCTION > Your bed was destroyed by %%tc%%%%player%%!" +bedwars.135="BED DESTRUCTION > %%team%% Bed was destroyed by %%tc%%%%player%%!" +bedwars.136="Bed Destroyed" +bedwars.137="BED DESTROYED!" +bedwars.138="You will no longer respawn!" +bedwars.respawn_progress="You will respawn in %%seconds%% seconds!" +bedwars.you_died="YOU DIED!" +bedwars.141="You have respawned!" +bedwars.142="RESPAWNED!" +bedwars.143="%%player%% was knocked into the void by %%killer%%." +bedwars.144="%%resource%% Generators have been upgraded to Tier %%tier%%" +bedwars.145="Emerald Upgrade" +bedwars.146="%%color%%+%%amount%% Iron" +bedwars.147="%%color%%+%%amount%% Gold" +bedwars.148="Final Kill" +bedwars.149="You have been eliminated!" +bedwars.150="The game in that world has already started!" +bedwars.151="CLICK TO PLAY" +bedwars.152="Select a Slot" +bedwars.153="This cosmetic can be used in-game by right clicking the compass!" +bedwars.154="Saved the %%name%% in position %%position%%!" +bedwars.155="Search results:" +bedwars.156="Search results: Creeper" +bedwars.157="Delivery Man rewards!" +bedwars.158="Bed Wars Lobby Selector" +bedwars.159="playing games on the server!" +bedwars.160="Dragon Slayer" +bedwars.161="%%player%% was killed by %%killer%%." +bedwars.162="Your bed was destroyed by %%tc%%%%player%%!" +bedwars.163="Final Kills:" +bedwars.164="Play Bed Wars" +bedwars.165="Click here to rejoin!" +bedwars.166="Click here to rejoin your Bed Wars game if you have been disconnected from it." +bedwars.167="Protect your bed alone and destroy the enemy beds to win." +bedwars.168="Map Selector" +bedwars.169="Protect your bed with a teammate and destroy the enemy beds to win." +bedwars.170="Protect your bed along with 2 teammates and destroy the enemy beds to win." +bedwars.171="You have toggled the leaderboards to show %%name%% positions!" +bedwars.172="Teams" +bedwars.173="3v3v3v3" +bedwars.174="4v4v4v4" +bedwars.175="%%name%%" +bedwars.176="None selected" +bedwars.177="Tracker & Communication" +bedwars.178="Send highlighted chat messages to your teammates!" +bedwars.179="Quick Communications" +bedwars.180="Purchase tracking upgrade for your compass which will track each player on a specific team until you die." +bedwars.181="Tracker Shop" +bedwars.182="Quick Communications" +bedwars.183="Click to send!" +bedwars.184="Purchase Enemy Tracker" +bedwars.185="beds are destroyed!" +bedwars.186="Cost: %%cost%% Emeralds" +bedwars.187="You don't have enough Emeralds!" +bedwars.188="Track Team %%team%%" +bedwars.189="Targeting your base on the compass now!" +bedwars.190="TEAM > %%player%%: %%message%%" +bedwars.191="Select an option:" +bedwars.192="Click to send the message:" +bedwars.193="to your teammates!" +bedwars.194="Targeting %%team%% on the compass now!" +bedwars.195="Targeting %%resource%% on the compass now!" +bedwars.196="Not all enemy beds are destroyed yet!" +bedwars.197="Build height limit reached!" +bedwars.198="Not all enemy beds are destroyed!" +bedwars.199="You purchased %%team%% Tracking" +bedwars.200="You will lose ability to track this team when you die!" +bedwars.201="Compass - %%color%%Tracking %%name%% " +bedwars.202="%%magic%%MN LEVEL UP! You are now Level %%level%%! %%magic%%NM" +bedwars.203="You earned %%amount%% %%reward%%" +bedwars.204="Diamond Glyph" +bedwars.205="Invisibility Potion Spray" +bedwars.206="Campfire Final Kill Effect" +bedwars.207="Plays the %%title%% when you die." +bedwars.208="Search results: asfsaffs" +bedwars.209="Bed Wars Statistics" +bedwars.210="Defensive" +bedwars.211="Support" +bedwars.212="Offensive" +bedwars.213="Fire Kill Messages" +bedwars.214="Gg Glyph" +bedwars.215="Gg" +bedwars.216="Ender Projectile Trail" +bedwars.217="Grumpy Villager Death Cry" +bedwars.218="Tnt Glyph" +bedwars.219="Grumpy Villager" +bedwars.220="Tnt" +bedwars.221="Bed Wars Solo" +bedwars.222="Bed Wars Doubles" +bedwars.223="Bed Wars 3v3v3v3" +bedwars.224="Bed Wars 4v4v4v4" +bedwars.225="CLICK TO OPEN" +bedwars.226="Shopkeeper" +bedwars.227="Hi Glyph" +bedwars.228="Notes Projectile Trail" +bedwars.229="I Love You Spray" +bedwars.230="GG WP Spray" +bedwars.231="Iron Glyph" +bedwars.232="Thumbs Up Glyph" +bedwars.233="Search results: asfgag" +bedwars.234="Creeper Shopkeeper" +bedwars.235="Green Star Projectile Trail" +bedwars.236="Ding Death Cry" +bedwars.237="Ding" +bedwars.238="Search results: ads" +bedwars.239="Protect your bed along with 3 teammates and destroy the enemy beds to win." +bedwars.240="Social Dashboard" +bedwars.241="Bed Wars Achievements" +bedwars.242="Team Player" +bedwars.243="Water Projectile Trail" +bedwars.244="Diamond Spray" +bedwars.245="Golem Riding Spray" +bedwars.246="Beds Broken" +bedwars.247="Beds Lost" +bedwars.248="Final Deaths" +bedwars.249="Losses" +bedwars.250="Bed Wars Doubles" +bedwars.251="Each day you can choose which map you want to play 1 time. Unlock unlimited map selection by upgrading to MVP+ rank on our store!" +bedwars.252="Click here to visit the store!" +bedwars.253="Map Selection" +bedwars.254="Bed Wars Solo" +bedwars.255="Slime Island Topper" +bedwars.256="Sword Island Topper" +bedwars.257="Bomb Island Topper" +bedwars.258="Chicken Island Topper" +bedwars.259="Fancy Helmet Island Topper" +bedwars.260="Fish Bowl Island Topper" +bedwars.261="Flame Island Topper" +bedwars.262="Gong Island Topper" +bedwars.263="Heart Island Topper" +bedwars.264="Monocle Island Topper" +bedwars.265="Note Island Topper" +bedwars.266="Rainbow Sheep Island Topper" +bedwars.267="Rubix Cube Island Topper" +bedwars.268="Sheep Island Topper" +bedwars.269="Sloth Island Topper" +bedwars.270="Smiley Face Island Topper" +bedwars.271="Sun Glasses Island Topper" +bedwars.272="TNT Island Topper" +bedwars.273="Top Hat Island Topper" +bedwars.274="Angry Face Glyph" +bedwars.275="Bed Glyph" +bedwars.276="Bronze Shield Glyph" +bedwars.277="Burn Glyph" +bedwars.278="Chicken Glyph" +bedwars.279="Creeper Scream Glyph" +bedwars.280="Cry Face Glyph" +bedwars.281="Daisy Glyph" +bedwars.282="Emerald Glyph" +bedwars.283="Gold Glyph" +bedwars.284="Gold Shield Glyph" +bedwars.285="Heart Glyph" +bedwars.286="Lol Glyph" +bedwars.287="No 1 Glyph" +bedwars.288="No Glyph" +bedwars.289="Rainbow Glyph" +bedwars.290="Search results: ^^^^^^dfdsf" +bedwars.291="Default Kill Messages" +bedwars.292="Bbq Kill Messages" +bedwars.293="Love Kill Messages" +bedwars.294="Pirate Kill Messages" +bedwars.295="Western Kill Messages" +bedwars.296="Blacksmith Shopkeeper" +bedwars.297="Zombie Pigman Shopkeeper" +bedwars.298="Wither Skeleton Shopkeeper" +bedwars.299="Witch Shopkeeper" +bedwars.300="Villager Zombie Shopkeeper" +bedwars.301="Skeleton Shopkeeper" +bedwars.302="Magic Vendor Shopkeeper" +bedwars.303="King Of Beds Shopkeeper" +bedwars.304="Holiday Bartender Shopkeeper" +bedwars.305="Blaze Shopkeeper" +bedwars.306="Bed Salesman Shopkeeper" +bedwars.307="Bed Researcher Shopkeeper" +bedwars.308="Animated Evil Eye Shopkeeper" +bedwars.309="Animated Ender Pulse Shopkeeper" +bedwars.310="Animated Astronaut Shopkeeper" +bedwars.311="Black Smoke Projectile Trail" +bedwars.312="Angry Villager Projectile Trail" +bedwars.313="White Smoke Projectile Trail" +bedwars.314="Slime Projectile Trail" +bedwars.315="Red Dust Projectile Trail" +bedwars.316="Random Projectile Trail" +bedwars.317="Rainbow Projectile Trail" +bedwars.318="Purple Dust Projectile Trail" +bedwars.319="Potion Projectile Trail" +bedwars.320="Magic Projectile Trail" +bedwars.321="Lava Projectile Trail" +bedwars.322="Hearts Projectile Trail" +bedwars.323="Firework Projectile Trail" +bedwars.324="Fire Projectile Trail" +bedwars.325="Blue Dust Projectile Trail" +bedwars.326="Dragon Rider Victory Dance" +bedwars.327="Anvil Rain Victory Dance" +bedwars.328="Wither Rider Victory Dance" +bedwars.329="Special Fireworks Victory Dance" +bedwars.330="Meteor Shower Victory Dance" +bedwars.331="Guardians Victory Dance" +bedwars.332="Aww Death Cry" +bedwars.333="Splash Death Cry" +bedwars.334="Sad Puppy Death Cry" +bedwars.335="Robot Mouse Death Cry" +bedwars.336="Plop Death Cry" +bedwars.337="Pig Death Cry" +bedwars.338="Monster Burp Death Cry" +bedwars.339="Grumble Death Cry" +bedwars.340="Fireball Death Cry" +bedwars.341="Energy Death Cry" +bedwars.342="Enderman Death Cry" +bedwars.343="Dry Bones Death Cry" +bedwars.344="Dinosaur Death Cry" +bedwars.345="Deflated Toy Death Cry" +bedwars.346="Bazinga Death Cry" +bedwars.347="Bat Death Cry" +bedwars.348="Yes Glyph" +bedwars.349="Winky Face Glyph" +bedwars.350="Thumbs Down Glyph" +bedwars.351="Sword Glyph" +bedwars.352="Storm Glyph" +bedwars.353="Star Glyph" +bedwars.354="Spectrum Glyph" +bedwars.355="Smiley Face Glyph" +bedwars.356="Skull Glyph" +bedwars.357="Silver Shield Glyph" +bedwars.358="Shock Face Glyph" +bedwars.359="Scream Face Glyph" +bedwars.360="Rip Glyph" +bedwars.361="Whale Island Topper" +bedwars.362="Tree Island Topper" +bedwars.363="Treasure Chest Island Topper" +bedwars.364="VIP+ Spray" +bedwars.365="VIP Spray" +bedwars.366="Thanks Spray" +bedwars.367="TNT Drop Spray" +bedwars.368="Sorry Spray" +bedwars.369="MVP+ Spray" +bedwars.370="MVP Spray" +bedwars.371="Loot Chest Spray" +bedwars.372="Leaping Potion Spray" +bedwars.373="Hypixel Logo Spray" +bedwars.374="Enderman Spray" +bedwars.375="Dragon Slayer Spray" +bedwars.376="Creeper Spray" +bedwars.377="Carried Spray" +bedwars.378="Bye Bye Spray" +bedwars.379="Bed Shield Spray" +bedwars.380="Bed Breaker Spray" +bedwars.381="Xp Orb Final Kill Effect" +bedwars.382="Tornado Final Kill Effect" +bedwars.383="TNT Final Kill Effect" +bedwars.384="Squid Missile Final Kill Effect" +bedwars.385="Smiley Final Kill Effect" +bedwars.386="Rekt Final Kill Effect" +bedwars.387="Piñata Final Kill Effect" +bedwars.388="Lit Final Kill Effect" +bedwars.389="Heart Aura Final Kill Effect" +bedwars.390="Head Rocket Final Kill Effect" +bedwars.391="Firework Final Kill Effect" +bedwars.392="Final Smash Final Kill Effect" +bedwars.393="Cookie Fountain Final Kill Effect" +bedwars.394="Burning Shoes Final Kill Effect" +bedwars.395="Blood Explosion Final Kill Effect" +bedwars.396="Bat" +bedwars.397="Monster Burp" +bedwars.398="Search results: asd" +bedwars.399="Plop" +bedwars.400="Robot Mouse" +bedwars.401="Deflated Toy" +bedwars.402="Tree" +bedwars.403="Witch" +bedwars.404="Villager Zombie" +bedwars.405="Love" +bedwars.406="Dry Bones" +bedwars.407="Bbq" +bedwars.408="Gong" +bedwars.409="Wither Skeleton" +bedwars.410="Bag of Coins" +bedwars.411="Western" +bedwars.412="Dinosaur" +bedwars.413="Island Topper" +bedwars.414="Bomb" +bedwars.415="Shopkeeper" +bedwars.416="Magic Vendor" +bedwars.417="Sorts by name from Z to A." +bedwars.418="Whale" +bedwars.419="Treasure Chest" +bedwars.420="Top Hat" +bedwars.421="Sun Glasses" +bedwars.422="Sloth" +bedwars.423="Rubix Cube" +bedwars.424="Rainbow Sheep" +bedwars.425="Note" +bedwars.426="Monocle" +bedwars.427="Fish Bowl" +bedwars.428="Fancy Helmet" +bedwars.429="Rip" +bedwars.430="Lol" +bedwars.431="Select the %%clean%% for in-game chat messages!" +bedwars.432="Blacksmith" +bedwars.433="Zombie Pigman" +bedwars.434="King Of Beds" +bedwars.435="Holiday Bartender" +bedwars.436="Bed Salesman" +bedwars.437="Bed Researcher" +bedwars.438="Animated Evil Eye" +bedwars.439="Animated Ender Pulse" +bedwars.440="Animated Astronaut" +bedwars.441="Aww" +bedwars.442="Splash" +bedwars.443="Sad Puppy" +bedwars.444="Grumble" +bedwars.445="Energy" +bedwars.446="Bazinga" +bedwars.447="Xp Orb" +bedwars.448="Lit" +bedwars.449="Shop & My Cosmetics (Right Click)" +bedwars.450="Death Cry" +bedwars.game_start.normal_description="Protect your bed and destroy the enemy beds. Upgrade yourself and your team by collecting Iron, Gold, Emerald and Diamond from generators to access powerful upgrades." +bedwars.452="The Spray Can can be used to display your Sprays and Glyphs on the go!" +bedwars.453="Your bed was destroyed so you are a spectator!" +bedwars.454="Diamond Maxed" +bedwars.455="Emerald Maxed" +bedwars.456="Bed Destruction" +bedwars.457="All beds will be destroyed in 5 minutes!" +bedwars.458=" ▪ %%item%%" +bedwars.459="Displaying Glyph above you!" +bedwars.460="Now selected: %%color%%%%option%%" +bedwars.461="You cannot spray on this block!" +bedwars.462="You cannot spray here!" +bedwars.463="Click a block with your spray can to spray!" +bedwars.464="You did not click a block!" +bedwars.465="%%color%%%%name%%" +bedwars.466="Evil Eye" +bedwars.467="Sorts by name from A to Z." +bedwars.468="No Teams Left" +bedwars.469="I don't know what world to put you on !" +bedwars.470="None Set" +bedwars.471="Select a Glyph or Spray to put in this slot in the shop!" +bedwars.472="You cannot use this here!" +bedwars.473="%%tc%%%%team%% - " +bedwars.474="1st Killer - %%player%% - %%kills%%" +bedwars.475="2nd Killer - %%player%% - %%kills%%" +bedwars.476="VICTORY!" +bedwars.477="+%%amount%% Bed Wars Experience (%%reason%%)" +bedwars.478="Tier %%tier%%" +bedwars.479="Miner Fatigue " +bedwars.480="Miner Fatigue" +bedwars.481="Heal Pool" +bedwars.482="Dragon Buff" +bedwars.483="Iron Forge" +bedwars.484="Maniac Miner" +bedwars.485="Sharpened Swords" +bedwars.486="Reinforced Armor" +bedwars.487="Cost: " +bedwars.488="Permanent" +bedwars.489="Iron Pickaxe " +bedwars.490="Diamond Pickaxe " +bedwars.491="Diamond Axe " +bedwars.492="Bow " +bedwars.493="Stick " +bedwars.494="Invisibility Potion " +bedwars.495="Stick (Knockback II)" +bedwars.496="Bow (Power I)" +bedwars.497="Bow (Power I, Punch I)" +bedwars.498="Stone Pickaxe (Efficiency I)" +bedwars.499="Iron Pickaxe (Efficiency II)" +bedwars.500="Diamond Pickaxe (Efficiency III)" +bedwars.501="Diamond Axe (Efficiency II)" +bedwars.502="Speed II Potion (45 seconds)" +bedwars.503="Jump V Potion (45 seconds)" +bedwars.504="Invisibility Potion (30 seconds)" +bedwars.505="Spray Can (%%option%%)" +bedwars.506="Unlocks when all enemy beds are destroyed!" +bedwars.507="Could not use menu, because an enemy is nearby!" +bedwars.508="You must be on the ground to use the menu!" +bedwars.509="Compass - %%color%%Tracking %%name%% (Left and Right Click)" +bedwars.510="It's a draw." +bedwars.511="ITEM SHOP" +bedwars.512="SOLO" +bedwars.513="TEAM" +bedwars.514="UPGRADES" +bedwars.515="All Mode Statistics" +bedwars.516="Spawns in %%seconds%% seconds" +bedwars.517="Diamond" +bedwars.518="Emerald" +bedwars.519="Compass (Left and Right Click)" +bedwars.quick_communication.have_resources="I have resources!" +bedwars.quick_communication.thank_you="Thank You!" +bedwars.quick_communication.get_back_to_base="Get back to base!" +bedwars.quick_communication.ask_defend="Please defend!" +bedwars.quick_communication.need_resources="We need resources!" +bedwars.quick_communication.hello="Hello ( ゚◡゚)/!" +bedwars.quick_communication.back_to_base="I'm coming back to base!" +bedwars.quick_communication.defending="I'm defending!" +bedwars.quick_communication.attacking="I'm attacking!" +bedwars.quick_communication.collecting_resources="I'm collecting resources!" +bedwars.530="Sorts by rarity from lowest to highest rarity." +bedwars.531="Sorts by rarity from highest to lowest rarity." +bedwars.532="I'm coming back to base!" +bedwars.533="I'm defending!" +bedwars.534="I'm attacking!" +bedwars.535="I'm collecting resources!" +bedwars.536="Select an option: " +bedwars.537="Click to send the message: " +bedwars.538="We need EMERALD" +bedwars.539="We need IRON" +bedwars.540="We need GOLD" +bedwars.541="We need DIAMOND" +bedwars.542="I have EMERALD" +bedwars.543="I have IRON" +bedwars.544="I have GOLD" +bedwars.545="I have DIAMOND" +bedwars.546="I'm collecting EMERALD" +bedwars.547="I'm collecting IRON" +bedwars.548="I'm collecting GOLD" +bedwars.549="I'm collecting DIAMOND" +bedwars.550="No Teams to target!" +bedwars.551="Please wait a bit between Quick Communicating!" +bedwars.552="Please defend" +bedwars.553="Thank You" +bedwars.554="I'm defending" +bedwars.555="Spray Can (Click a block)" +bedwars.556="%%underline%%Chat Messages:" +bedwars.557="Island Toppers (Page 2)" +bedwars.558="Sprays (Page 2)" +bedwars.559="Glyphs (Page 2)" +bedwars.560="Click here to rejoin your game if you have been disconnected from it." +bedwars.561="Play Bed Wars 3v3v3v3" +bedwars.562="Play Bed Wars 4v4v4v4" +bedwars.563="Play Bed Wars Doubles" +bedwars.564="Play Bed Wars Solo" +bedwars.565="Bed Wars 3v3v3v3" +bedwars.566="Bed Wars (3v3v3v3)" +bedwars.567="Bed Wars (4v4v4v4)" +bedwars.568="Bed Wars (Solo)" +bedwars.569="Bed Wars (Doubles)" +bedwars.570="No favourite servers available!" +bedwars.571="You've already purchased this item!" +bedwars.572="I don't know what world to put you on (Player)!" +bedwars.573="%%player%% %%kill_message%% %%killer%%." +bedwars.574="You must wait %%seconds%% seconds until you can use /shout again!" +bedwars.575="Golden Forge" +bedwars.576="Activates the Emerald spawner in your team's Forge." +bedwars.577="Emerald Forge" +bedwars.578="Increases the spawn rate of Emerald, Iron, and Gold by %%percent%%%." +bedwars.579="Molten Forge" +bedwars.580="UNLOCKED" +bedwars.581="You have already maxed out this upgrade!" +bedwars.582="You already have a higher tier item." +bedwars.583="TRAP TRIGGERED!" +bedwars.584="Your trap has been set off!" +bedwars.585="Your trap has been set off!" +bedwars.586="You can't place blocks here!" +bedwars.587="You can't break blocks here!" +bedwars.588="You didn't pick up any more Gold because you have too much on you!" +bedwars.589="Limit of 2 Golems per player!" +bedwars.590="All beds have been destroyed!" +bedwars.591="All beds have been destroyed!" +bedwars.592="Sudden Death" +bedwars.593="%%color%%+%%amount%% Diamonds" +bedwars.594="%%color%%+%%amount%% Emeralds" +bedwars.595="Sudden Death" +bedwars.596="SUDDEN DEATH: +%%num%% %%title%%!" +bedwars.597="Game End" +bedwars.598="3rd Killer - %%player%% - %%kills%%" +bedwars.599="GAME OVER!" +bedwars.600="You earned %%coins%% Bed Wars Coins" +bedwars.601="Team Upgrades" +bedwars.602="%%option%%!" +bedwars.603="Hello ( ゚◡゚)/" +bedwars.604="You purchased %%item%%" +bedwars.605="Get back to base" +bedwars.606="I'm coming back to base" +bedwars.607="Click to send the message: "%%option%%"" +bedwars.608="%%option%%" +bedwars.609="BED DESTRUCTION > Your bed %%kill_message%% %%tc%%%%player%%!" +bedwars.610="Your bed %%kill_message%% %%tc%%%%player%%!" +bedwars.611="BED DESTRUCTION > %%team%% Bed %%kill_message%% %%tc%%%%player%%!" +bedwars.612=" FINAL KILL!" +bedwars.613="Could not use menu, because you are a spectator!" +bedwars.614="The Cosmetic Menu closed as you took damage!" +bedwars.615="The Cosmetic Menu closed as you attacked something!" +bedwars.616="TEAM ELIMINATED > %%tc%%%%tname%% Team %%kill_message%%!" +bedwars.617="R" +bedwars.618="B" +bedwars.619="G" +bedwars.620="Y" +bedwars.621="A" +bedwars.622="W" +bedwars.623="P" +bedwars.624="S" +bedwars.625="You will be able to select the %%type%%." +bedwars.626="I have %%resources%%" +bedwars.627="%%choice%%!" +bedwars.628="Lets attack %%option%%" +bedwars.629="We need %%resources%%" +bedwars.630="I'm attacking %%option%%" +bedwars.631="I'm collecting %%resources%%" +bedwars.632="Resource" +bedwars.633="Team" +bedwars.634="Fireball" +bedwars.635="%%choice%%" +bedwars.636="%%name%%" +bedwars.637="Click to send the message: "%%choice%%"" +bedwars.638="1st Killer" +bedwars.639="2nd Killer" +bedwars.640="3rd Killer" +bedwars.641="Kills: " +bedwars.642="Final Kills: " +bedwars.643="Beds Broken: " +bedwars.644="You can't use /shout as a spectator." +bedwars.645="You can't use /shout while muted." +bedwars.646="The game has finished, no need to shout!" +bedwars.647="SHOUT" +bedwars.648="%%player%% is on %%health%% HP!" +bedwars.649="You didn't pick up any more Iron because you have too much on you!" +bedwars.650="Food: %%val%%" +bedwars.651="%%entry%% - %%player%% - %%kills%%" +bedwars.652="Airshow" +bedwars.653="Aquarium" +bedwars.654="Archway" +bedwars.655="Ashore" +bedwars.656="Boletum" +bedwars.657="Chained" +bedwars.658="Crypt" +bedwars.659="Eastwood" +bedwars.660="Glacier" +bedwars.661="Hollow" +bedwars.662="Invasion" +bedwars.663="Lectus" +bedwars.664="Lighthouse" +bedwars.665="Lotus" +bedwars.666="Pernicious" +bedwars.667="Playground" +bedwars.668="Rooftop" +bedwars.669="Speedway" +bedwars.670="Stonekeep" +bedwars.671="Swashbuckle" +bedwars.672="Treenan" +bedwars.673="Waterfall" +bedwars.674="Doubles" +bedwars.675="4v4v4v4" +bedwars.676="Solo" +bedwars.677="3v3v3v3" +bedwars.678="CLICK TO OPEN" +bedwars.679="Hypixel" +bedwars.680="More Leaderboards" +bedwars.681="WEBSITE" +bedwars.682="LEADERBOARDS" +bedwars.683="On the website you can find even more leaderboards and other cool stuff!" +bedwars.tracking_player="Tracking: - Distance: " +bedwars.685="Please wait %%cooldown%% to use that again" +bedwars.686="%%mode%% Mode Statistics" +bedwars.687="Group Bonus" +bedwars.688="You earned %%exp%% Bed Wars Experience (First Join)" +bedwars.689="Let's attack!" +bedwars.690="[SPECTATOR]" +bedwars.691="You can't use /shout before the game has started." +bedwars.692="You can only use /shout in team modes." +bedwars.693="Quick Communications" +bedwars.694="You cannot use Quick Communications in Solo Mode!" +bedwars.695="You cannot use Quick Communications in Solo Mode!" +bedwars.696="You cannot do that right now!" +bedwars.697="I couldn't find a game for you!" +bedwars.698="You cannot open this Chest as the %%team%% has not been eliminated!" +bedwars.699="You took damage and lost your invisibility!" +bedwars.700="None Glyph" +bedwars.701="Killing an enemy will set their body on fire." +bedwars.702="Amazon" +bedwars.703="Wooden Pickaxe [Tier 1]" +bedwars.704="Stone Pickaxe [Tier 2]" +bedwars.705="Iron Pickaxe [Tier 3]" +bedwars.706="Diamond Pickaxe [Tier MAX]" +bedwars.707="Wooden Axe [Tier 1]" +bedwars.708="Stone Axe [Tier 2]" +bedwars.709="Iron Axe [Tier 3]" +bedwars.710="Diamond Axe [Tier MAX]" +bedwars.711="Your creature will fight for you for %%timer%% seconds." +bedwars.712="This is an upgradable item." +bedwars.713="If above tier 1, the item will" +bedwars.714="drop 1 tier upon death!" +bedwars.715="Your team gets Efficiency %%level%% on all tools!" +bedwars.716="Bedbug" +bedwars.717="Bedbug" +bedwars.718="Dream Defender" +bedwars.719="Frosty" +bedwars.720="As a stationary snowball sentry gun, this snowman will help defend your base." +bedwars.721="You don't have enough %%resource%%! Need %%amount%% more!" +bedwars.722="Quick Pick" +bedwars.723="Early Game" +bedwars.724="Mid Game" +bedwars.725="Late Game" +bedwars.726="The items on this line are recommended items for %%stage%%." +bedwars.727="%%stage%%" +bedwars.728="Saved item to slot %%slot%%!" +bedwars.729="Favourites" +bedwars.730="Favourites" +bedwars.731="Recommended Items" +bedwars.732="Recommended Items" +bedwars.733="Click to set your favourite item to this slot!" +bedwars.734="Click to %%choice%%!" +bedwars.735="replace" +bedwars.736="set" +bedwars.737="The Spray Can can be" +bedwars.738="used to display your Sprays" +bedwars.739="and Glyphs on the go!" +bedwars.740="Left Click: Change Selected" +bedwars.741="Right Click: Use Spray Can" +bedwars.742="Click to view some recommended items for early to late game!" +bedwars.743="Right-click to launch!" +bedwars.744="Moderately annoying. These" +bedwars.745="little critters can be thrown to" +bedwars.746="distract enemies." +bedwars.747="Moderately motivated." +bedwars.748="Sometimes they help defend your" +bedwars.749="base." +bedwars.750="Pretty useful for invading" +bedwars.751="enemy bases." +bedwars.752="This egg creates a bridge in" +bedwars.753="its trail after being thrown." +bedwars.754="Shift click an item in the shop to set it as a favourite item!" +bedwars.755="Click to view your favourite items. You can set a favourite item by shift clicking on any shop item!" +bedwars.756="Miner Fatigue Trap" +bedwars.757="The next enemy to enter your base will receive Mining Fatigue for 10 seconds!" +bedwars.758="Blast-Proof Glass" +bedwars.759="Immune to explosions" +bedwars.760="Bedbug (Unbreaking I)" +bedwars.761="Hypixel Spooky Halloween" +bedwars.762="Plays the %%title%% death cry when you die." +bedwars.763="Select %%clean%% as your Shopkeeper!" +bedwars.764="Acquired during Halloween!" +bedwars.765="The fear doesn't actually creep until you're alone in the dark and think of this victory dance." +bedwars.766="Press JUMP to Ghast Jump!" +bedwars.767="Unlocked through Special Quest!" +bedwars.768="Killing an enemy will make them *poof* out of the realm existence." +bedwars.769="Killing an enemy splits their soul into 7 Batcruxes." +bedwars.770="Pumpkinator's Pumpkin" +bedwars.771="You brought %%count%% pumpkins back to the shopkeeper!" +bedwars.772="You brought %%count%% pumpkin back to the shopkeeper!" +bedwars.773="Trade in at any shopkeeper to claim for the Pumpkinator quest!" +bedwars.774="%%who%%'s Batcrux #%%no%%" +bedwars.775="Spookeeper" +bedwars.776="Halloween Event" +bedwars.777="Click here to open the Bedwars shop" +bedwars.778="SPOOKY HALLOWEEN" +bedwars.779="Until Nov 7th" +bedwars.780="Featuring:" +bedwars.781="Select the %%name%% %%category%%. This change is cosmetic." +bedwars.782="Select %%name%% as your Shopkeeper!" +bedwars.783="Plays the %%name%% %%category%% when you die." +bedwars.784="Select the %%name%% %%category%% for in-game chat messages!" +bedwars.785="Batcrux" +bedwars.786="Black Mark" +bedwars.787="Doot Doot" +bedwars.788="Witch Bouillon" +bedwars.789="Groovy the Ghost" +bedwars.790="Defenestration" +bedwars.791="Disco Pumpkin" +bedwars.792="Starry Veggie" +bedwars.793="Sir von Mewrtimer" +bedwars.794="Evil Kitty" +bedwars.795="Eyeball" +bedwars.796="Ghostly Ghost" +bedwars.797="Hall-o-ween" +bedwars.798="Candle" +bedwars.799="Parchment the Skelly" +bedwars.800="Sinister Pot" +bedwars.801="Witch Hat" +bedwars.802="Toonywise" +bedwars.803="Select the %%name%% %%category%% to spawn above your island." +bedwars.804="Literally Spooky" +bedwars.805="Magic Toy Stick" +bedwars.806="Do not leave with an unsupervised magician" +bedwars.807="Last Candle" +bedwars.808="%%who%%'s Candle" +bedwars.809="for %%who%%" +bedwars.810="Killing an enemy will spawn a torch in their place." +bedwars.811="Killing an enemy will spawn a musical snow globe that will play 1 of 6 Christmas jingles." +bedwars.812="Snowplosion" +bedwars.813="Killing an enemy will make them explode into snowballs, splattering snow everywhere." +bedwars.814="Snowman" +bedwars.815="Santa" +bedwars.816="You!" +bedwars.817="Select yourself as your own Shopkeeper! Your own skin will be displayed." +bedwars.818="Gone" +bedwars.819="Miracle" +bedwars.820="Magic Wind" +bedwars.821="Candy Cane" +bedwars.822="Hype the Elf" +bedwars.823="Gift" +bedwars.824="Super Snow Golem" +bedwars.825="Reveillon" +bedwars.826="You must wait %%cooldown%% seconds between spray uses!" +bedwars.827="Sprays are now triggered from pre-defined slots on the map!" +bedwars.828="Glyphs will automatically appear when picking up resources!" +bedwars.829="The Spray Can will be" +bedwars.830="removed soon as Glyphs" +bedwars.831="and Sprays were changed." +bedwars.832="Old Spray Can" +bedwars.833="Select a Glyph image which will appear when picking up diamonds and emeralds!" +bedwars.834="Select a spray to show off all over the place! Spray slots can be found on every spawn island and some center islands." +bedwars.835="Bring this item back to whoever is looking for it." +bedwars.836="Can't open the gift while your inventory is full!" +bedwars.837="The milk refills as you drink it, you feel no effect..." +bedwars.838="I'm not looking for this kind of item!" +bedwars.839="Bring me: %%item%%!" +bedwars.840="You brought %%amount%% item back to %%name%%!" +bedwars.841="You brought %%amount%% items back to %%name%%!" +bedwars.842="Wants %%item%%" +bedwars.843="Lucas the Elf" +bedwars.844="Sammy the Cookie" +bedwars.845="Comet the Reindeer" +bedwars.846="Joe the Penguin" +bedwars.847="Compass - %%color%%Tracking %%name%% (Left Click)" +bedwars.848="The L" +bedwars.849="Humongous Christmas Tree" +bedwars.850="Fancy Santa Hat" +bedwars.851="Wingless Angel" +bedwars.852="Bunch of Presents" +bedwars.853="Magic Snowglobe" +bedwars.854="Hey what about you bring me buckets with some milk in them?" +bedwars.855="Did you... drink the milk?" +bedwars.856="L" +bedwars.857="Memed" +bedwars.858="Santa's Workshop" +bedwars.859="Unlock by purchasing Loot Boxes!" +bedwars.860="Ender Pulse" +bedwars.861="Shopkeeper Skin" +bedwars.862="Lifetime Final Kills" +bedwars.863="Weekly Final Kills" +bedwars.864="Lifetime Wins" +bedwars.865="Weekly Wins" +bedwars.866=" HAPPY HOLIDAYS" +bedwars.867="Right Click to open this present. Bring the gift inside to its recipient for experience and coins!" +bedwars.868="Wrapped Present (Right Click)" +bedwars.869="Gift Wishlist" +bedwars.870="Milk" +bedwars.871="Stocking" +bedwars.872="Fancy Frosty Hat" +bedwars.873="SUDDEN DEATH: +%%num%% %%team%% Dragon!" +bedwars.874="Bao" +bedwars.875="Chen" +bedwars.876="Li" +bedwars.877="Wei" +bedwars.878="Xiu" +bedwars.879="Zhao" +bedwars.880="Blossom" +bedwars.881="Dog" +bedwars.882="Yin and Yang" +bedwars.883="Cherry Blossom" +bedwars.884="Fountain Firework" +bedwars.885="Lunar Dragon" +bedwars.886="Mark of the Paw" +bedwars.887="Woof Woof" +bedwars.888="Lucky Cat" +bedwars.889="Cute Puppy" +bedwars.890="Bed Wars 4v4v4v4" +bedwars.891="Astronaut" +bedwars.892="You already unlocked this upgrade!" +bedwars.893="You need to unlock previous tiers before unlocking this one!" +bedwars.894="Can't use bridge egg over build height limit!" +bedwars.895="Quick Buy" +bedwars.896="Your team permanently gains Sharpness %%level%% on all swords and axes!" +bedwars.897="Mode: %%mode%%" +bedwars.898="v%%version%%" +bedwars.899="BETA %%version%%" +bedwars.900="Version: %%version%%" +bedwars.901="Diamond II" +bedwars.902="Diamond III" +bedwars.903="Emerald II" +bedwars.904="Emerald III" +bedwars.905="ITEM SHOP" +bedwars.906="SOLO" +bedwars.907="TEAM" +bedwars.908="UPGRADES" +bedwars.909="Upgrades & Traps" +bedwars.910="Your team permanently gains Protection on all armor pieces!" +bedwars.911="All players on your team permanently gain Haste." +bedwars.912="Upgrade resource spawning on your island." +bedwars.913="Buy a trap" +bedwars.914="Trap queue full!" +bedwars.915="Purchased traps will be queued on the right" +bedwars.916="Queue a trap" +bedwars.917="Traps Queue" +bedwars.918="Inflicts Blindness and Slowness for 5 seconds." +bedwars.919="Grants Speed I for 15 seconds to allied players near your base." +bedwars.920="Reveals invisible players as well as their name and team." +bedwars.921="Inflict Mining Fatigue for 10 seconds." +bedwars.922="Tier: %%tier%%" +bedwars.923="+%%percent%%% Resources" +bedwars.924="Protection %%tier%%" +bedwars.925="Haste %%tier%%" +bedwars.926="Items" +bedwars.927="Empty slot!" +bedwars.928="This is a Quick Buy Slot! Sneak Click any item in the shop to add it here." +bedwars.929="Sneak Click to remove from Quick Buy!" +bedwars.930="Sneak Click to add to Quick Buy" +bedwars.931="Hotbar Manager" +bedwars.932="Edit preferred slots for your items per category." +bedwars.933="Reset to Default" +bedwars.934="Reset your hotbar to the default" +bedwars.935="%%category%% items will prioritize this slot!" +bedwars.936="Click to remove!" +bedwars.937="Click to drag!" +bedwars.938="Drag this to the slot your compass will be set to on spawn." +bedwars.939="If no slot has a compass, you will not be given one." +bedwars.940="Drag this to a hotbar slot below to favor that slot when purchasing an item in this category or on spawn." +bedwars.item.compass="Compass (Right Click)" +bedwars.942="%%color%%Tier %%tier%%: %%upgrade%%, %%cost%%" +bedwars.943="No Trap!" +bedwars.944="Trap #%%number%%: %%trap%%" +bedwars.945="The %%nice%% enemy to walk into your base will trigger this trap!" +bedwars.946="first" +bedwars.947="second" +bedwars.948="third" +bedwars.949="Queued by: %%who%%" +bedwars.950="Purchasing a trap will queue it here. Its cost will scale based on the number of traps queued." +bedwars.951="Reinforced Armor I" +bedwars.952="Reinforced Armor II" +bedwars.953="Reinforced Armor III" +bedwars.954="Reinforced Armor IV" +bedwars.955="Maniac Miner I" +bedwars.956="Maniac Miner II" +bedwars.957="Counter-Offensive Trap" +bedwars.958="Alarm Trap" +bedwars.959="Next trap: %%cost%%" +bedwars.960="Purchasable" +bedwars.961="Instantly ignites, appropriate to explode things!" +bedwars.962="Great for bridging across islands. Turns into your team's color." +bedwars.963="Chainmail leggings and boots which you will always spawn with." +bedwars.964="Good block to defend your bed. Strong against pickaxes." +bedwars.965="Iron leggings and boots which you will always spawn with." +bedwars.966="Great to get rid of wool." +bedwars.967="Great to get rid of wool. You will always spawn with these shears." +bedwars.968="Complete Invisibility (0:30)" +bedwars.969="Speed II (0:45)" +bedwars.970="Great to slow down approaching enemies. Can also protect against TNT." +bedwars.971="Basic block to defend your bed." +bedwars.972="Immune to explosions." +bedwars.973="Solid block to defend your bed." +bedwars.974="Useful to save cats stuck in trees." +bedwars.975="Extreme protection for your bed." +bedwars.976="Diamond leggings and boots which you will always crush with." +bedwars.977="This is an upgradable item." +bedwars.978="It will lose 1 tier upon death!" +bedwars.979="You will permanently respawn with at least the lowest tier." +bedwars.980="Jump Boost V (0:45)" +bedwars.981="Well-rounded healing." +bedwars.982="Spawns silverfish where the snowball lands to distract your enemies. Lasts 15 seconds." +bedwars.983="Right-click to launch! Great to knock back enemies walking on thin bridges." +bedwars.984="The quickest way to invade enemy bases." +bedwars.985="This egg creates a bridge in its trail after being thrown." +bedwars.986="Avoid triggering traps for 60 seconds after consuming." +bedwars.987="Great for soaking up water." +bedwars.988="MAXED!" +bedwars.989="Wooden Pickaxe (Efficiency I)" +bedwars.990="Gold Pickaxe (Efficiency III, Sharpness II)" +bedwars.991="Wooden Axe (Efficiency I)" +bedwars.992="Stone Axe (Efficiency I)" +bedwars.993="Iron Axe (Efficiency II)" +bedwars.994="Diamond Axe (Efficiency III)" +bedwars.995="Iron Golem to help defend your base. Lasts 4 minutes." +bedwars.996="Adding to Quick Buy..." +bedwars.997="This is an empty Quick Buy slot!" +bedwars.998="Sneak Click on an item in the rest of the shop to fill it!" +bedwars.999="Adding item to Quick Slot!" +bedwars.1000="Your Magic Milk wore off!" +bedwars.1001="Magic Milk" +bedwars.1002="Click!" +bedwars.1003="Stick (Knockback I)" +bedwars.1004="Clicking too fast!" +bedwars.1005="Spawn emeralds" +bedwars.1006="Spawns silverfish where the snowball lands to distract your enemies." +bedwars.1007="Iron Golem to help defend your base." +bedwars.1008="Quack" +bedwars.1009="Bunny" +bedwars.1010="Bloom" +bedwars.1011="Hatching Egg" +bedwars.1012="Fat Chicken" +bedwars.1013="Chocolate" +bedwars.1014="Currently acquirable:" +bedwars.1015="Breaking a bed will wake up Thor." +bedwars.1016="Breaking a bed will summon a vortex!" +bedwars.1017="Breaking a bed will launch fireworks." +bedwars.1018="Breaking a bed will make it explode into lava." +bedwars.1019="Breaking a bed will spawn a fellow companion." +bedwars.1020="Breaking a bed will release the bugs within." +bedwars.1021="Bed Destroy" +bedwars.1022="Bed Destroys" +bedwars.1023="Select from various Bed Destroy effects, which will occur when you break a bed!" +bedwars.1024="Thief" +bedwars.1025="Plays the %%name%% %%category%% when you break a bed." +bedwars.1026="Lava Explosion" +bedwars.1027="Bed Bugs" +bedwars.1028="LIMITED TIME MODE!" +bedwars.1029="Win EXP is disabled in dream modes." +bedwars.1030="LIMITED TIME MODE: %%mode%%" +bedwars.1031="RUSH" +bedwars.1032="Rush Doubles" +bedwars.1033="Rush 4v4v4v4" +bedwars.1034="Overall stats, achievements and quests will NOT be earned in this mode!" +bedwars.1035="ULTIMATE" +bedwars.1036="Ultimate Doubles" +bedwars.1037="Ultimate 4v4v4v4" +bedwars.1038="Dreams" +bedwars.1039="Jumper" +bedwars.1040="Swordsman" +bedwars.1041="Healer" +bedwars.1042="Frozo" +bedwars.1043="Double Jump!" +bedwars.1044="Dash by holding right click with your sword and damage any enemies who get in the way!" +bedwars.1045="Heal allies for a short time in the dropped radius!" +bedwars.1046="Slow down enemies for a short time in the dropped radius!" +bedwars.1047="Easily build walls and bridges using wool! Passively generates wool." +bedwars.1048="Mode: %%mode%%" +bedwars.1049="Left click to change mode, place to activate!" +bedwars.1050="Builder Tool - %%mode%%" +bedwars.1051="Wall" +bedwars.1052="This ultimate is coming soon!" +bedwars.1053="Psst, try right clicking your bed with this!" +bedwars.1054="Cooldown: %%time%% Seconds" +bedwars.1055="Ultimates will be enabled in %%seconds%% seconds!" +bedwars.1056="Switched ultimate to %%ultimate%%!" +bedwars.1057="Select an ultimate in the store! They will be enabled in %%seconds%% seconds!" +bedwars.1058="Ultimates have been enabled!" +bedwars.1059="You had no ultimate selected so you've been set to %%ultimate%%!" +bedwars.1060="You have ran out of wool blocks!" +bedwars.1061="Dream Statistics" +bedwars.1062="View your statistics for Dream modes!" +bedwars.1063="No stats were tracked for Rush!" +bedwars.1064="Winstreak" +bedwars.1065="%%mode%% Statistics" +bedwars.1066="Overall Statistics" +bedwars.1067="DREAM %%version%%" +bedwars.1068="Bed Wars %%mode%%" +bedwars.1069="Rush" +bedwars.1070="Ultimate" +bedwars.1071="Ultimates" +bedwars.1072="Left click to switch mode, place to activate!" +bedwars.1073="Currently selected!" +bedwars.1074="Bed gone" +bedwars.1075="%%event%% in %%time%%" +bedwars.1076="Frozo Ultimate" +bedwars.1077="Healer Ultimate" +bedwars.1078="Magic Milk" +bedwars.1079="Dream Defender" +bedwars.1080="You cannot use Quick Communications in this Mode!" +bedwars.1081="LIMITED TIME DREAMS" +bedwars.1082="Castle" +bedwars.1083="Streak Points: " +bedwars.1084="BANKER" +bedwars.1085="STREAK POWERS" +bedwars.1086="Streak Powers" +bedwars.1087="Unleash your full potential with streak powers!" +bedwars.1088="Golden Knight" +bedwars.1089="Spawns you with a trusty horse and the Sword of Justice!" +bedwars.1090="Boots of Justice" +bedwars.1091="Pants of Justice" +bedwars.1092="Chestplate of Justice" +bedwars.1093="Soar through the sky on your majestic wither and obliterate your enemies by spitting feisty fireballs!" +bedwars.1094="Lone Wolf" +bedwars.1095="Spawns trusty wolves to help you in a battle by knocking players away from you!" +bedwars.1096="Another wolf has joined your heard!" +bedwars.1097=" %%color%%%%player%% unleashed the WITHER!" +bedwars.1098="%%color%%The Wither is on %%health%% HP!" +bedwars.1099="Team Limit: %%amount%% at the same time" +bedwars.1100="Cost: %%points%% Streak Points" +bedwars.1101="You're currently using a streak power!" +bedwars.1102="You've already activated this streak!" +bedwars.1103="You must be level %%level%% to use this streak!" +bedwars.1104="You need %%points%% more streak points!" +bedwars.1105="Your team has already hit the concurrent allowance for this streak. Check back later" +bedwars.1106="You must wait %%cooldown%% seconds before you can activate another streak power!" +bedwars.1107="Add resources by dragging them on this icon. The shops will automatically use resources from the Banker if you don't have enough." +bedwars.1108="Stored:" +bedwars.1109="%%color%%Add %%amount%%x %%resource%% to bank" +bedwars.1110="%%resource%% Team Resource" +bedwars.1111="Tier 1" +bedwars.1112="Tier 2" +bedwars.1113="You can't use your enemy's launch pads!" +bedwars.1114="+%%amount%% Streak Points (%%reason%%)" +bedwars.1115="You don't have enough %%resource%%!" +bedwars.1116="Your team's resource bank has reached the limit for %%resource%%!" +bedwars.1117="You added %%amount%%x %%type%% to your team's resource bank!" +bedwars.1118="Consider sharing some of your resources with your team mates by clicking the Banker NPC at your base." +bedwars.1119="Click to purchase with team resources!" +bedwars.1120="Please wait %%seconds%% seconds before using more team resources!" +bedwars.1121="You used %%amount%%x %%type%% from your team's resource bank for this purchase!" +bedwars.1122="You have available streak powers! Visit the Streak NPC at spawn or click anywhere with your compass to activate them!" +bedwars.1123="%%tc%%%%player%% activated their %%streak%% streak power!" +bedwars.1124="%%tc%%%%player%%'s streak power has worn off." +bedwars.1125="%%color%%%%player%% unleashed the WITHER!" +bedwars.1126="TIME IS UP! Your %%streak%% streak ran out." +bedwars.1127="Uses left: %%amount%%" +bedwars.1128="Ivory Castle" +bedwars.1129="%%player%% died." +bedwars.1130="You cannot build any further down!" +bedwars.1131="Rush Solo" +bedwars.1132="Ultimate Solo" +bedwars.1133="Rush V2" +bedwars.1134="Ultimate V2" +bedwars.1135="All generators are maxed! Your bed has two layers of protection! Left click while holding wool to activate bridge building!" +bedwars.1136="BRIDGE MODE DEACTIVATED" +bedwars.1137="BRIDGE MODE ACTIVATED" +bedwars.1138="You can activate bridge building by left clicking with wool in your hand!" +bedwars.1139="%%team%% Dragon" +bedwars.1140="∙ Double Jump!" +bedwars.1141="∙ Chance to keep resources on death!" +bedwars.1142="∙ Free milk on bed destroy!" +bedwars.1143="∙ Hold right click on a sword to dash forward!" +bedwars.1144="∙ Hold right click again to recall!" +bedwars.1145="∙ Cooldown reset on kill!" +bedwars.1146="∙ Hold right click on a sword to heal yourself!" +bedwars.1147="∙ Throw down potion to heal teammates in a radius!" +bedwars.1148="∙ Throw down potion to slow down enemies!" +bedwars.1149="∙ Snowball on kill! (16 max)" +bedwars.1150="∙ Build bridges!" +bedwars.1151="∙ Build walls!" +bedwars.1152="∙ Instantly protect your bed!" +bedwars.1153="Demolition" +bedwars.1154="∙ Burn wool in a radius!" +bedwars.1155="∙ Drops TNT on death!" +bedwars.1156="∙ Earns a creeper egg on bed destroy!" +bedwars.1157="∙ Chance to duplicate picked up diamonds/emeralds from generators!" +bedwars.1158="∙ Portable Ender Chest!" +bedwars.1159="∙ When own bed is destroyed, get a free team upgrade!" +bedwars.1160="Demolition Tool" +bedwars.1161="Portable Ender Chest (Right Click)" +bedwars.1162="%%name%% unlocked %%item%%" +bedwars.1163="Wizard Wand - Right-click to use" +bedwars.1164="Block Wizard" +bedwars.1165="Gives you a wand which can summon nearby blocks to help you in your battle!" +bedwars.1166="Please wait %%seconds%% seconds before using this again!" +bedwars.1167="Hot Floor" +bedwars.1168="Sets the floor by you on fire!" +bedwars.1169="40v40 Castle V2" +bedwars.1170="Would you like to see %%item%% added permanently to Bed Wars?" +bedwars.1171="YES" +bedwars.1172="NO" +bedwars.1173="Click here to vote YES" +bedwars.1174="Click here to vote NO" +bedwars.1175="You have already used this!" +bedwars.1176="Place a pop-up defence!" +bedwars.1177="Pop-up Tower" +bedwars.1178="Rotating Item" +bedwars.1179="LIMITED TIME" +bedwars.1180="This item is currently being tested in Bed Wars in order to collect feedback." +bedwars.1181="Purchase Failed! Exceeded purchase limit!" +bedwars.1182="Purchase Limit: %%limit%%" +bedwars.1183="Max Team Upgrades" +bedwars.1184="All teams will start with maxed out team upgrades." +bedwars.1185="Thanks for voting!" +bedwars.1186="Ice Bridge" +bedwars.1187="Spawn an ice bridge in the direction you're looking but beware, the bridge melts when you walk over it!" +bedwars.1188="You must be on the ground to use this!" +bedwars.1189="Spawn a snowball sentry gun!" +bedwars.1190="Sugar Cookie" +bedwars.1191="Block Shuffler" +bedwars.1192="Should %%item%% be added permanently to Bed Wars?" +bedwars.1193="Lucky Chest" +bedwars.1194="Spawns a lucky chest with random resource drops!" +bedwars.1195="Pig Missile" +bedwars.1196="Pigsplosion" +bedwars.1197="Pig Smash" +bedwars.1198="Click here to open the Bed Wars shop" +bedwars.1199="Breaking a bed will a bunch of baby pigs." +bedwars.1200="A pig will smash into the ground on your kills." +bedwars.1201="You didn't participate in a Bed Wars tournament, so your "Tournament Position" topper is just a bunch of air." +bedwars.1202="You needed to rank within the top 100,000 players in a Tournament for your "Tournament Position" topper to render while you only ranked #%%pos%%, sorry." +bedwars.1203="Merry Base" +bedwars.1204="Festive Harbinger" +bedwars.1205="Week Of The Pig" +bedwars.1206="Your Week Of The Pig ability is already active!" +bedwars.1207="You have activated your Week Of The Pig ability!" +bedwars.1208="Devastator Bow" +bedwars.1209="Place a compact pop-up defence!" +bedwars.1210="Compact Pop-up Tower" +bedwars.1211="4v4 Capture BETA" +bedwars.1212="BED WARS BETA" +bedwars.1213="Version: v%%version%%" +bedwars.1214="Beta is a way for you to shape the future of Bed Wars." +bedwars.1215="Play changes in upcoming updates now and share your feedback." +bedwars.1216="GIVE FEEDBACK" +bedwars.1217="What is Bed Wars BETA?" +bedwars.1218="Play Bed Wars Capture (BETA)" +bedwars.1219="Capture mode is a new mode of points capture and control." +bedwars.1220="Win EXP is disabled while Capture is in beta." +bedwars.1221="Capture" +bedwars.1222="DNA" +bedwars.1223="Soul Ripper" +bedwars.1224="Kill Counter" +bedwars.1225="Primal" +bedwars.1226="Glorious" +bedwars.1227="Dramatic" +bedwars.1228="Very Evil Pumpkin" +bedwars.1229="Evil Pumpkin" +bedwars.1230="Pumpkin Explosion" +bedwars.1231="Suspicious Tree" +bedwars.1232="Mini Herobrine's Mansion" +bedwars.1233="Gargoyle" +bedwars.1234="BED DESTRUCTION > " +bedwars.1235="Upgraded: Protection %%level%%" +bedwars.1236="Upgraded: Sharpness %%level%%" +bedwars.1237="You attacked someone and lost your invincibility!" +bedwars.1238="You have been given a tracker for the enemy team!" +bedwars.1239="Resource Info" +bedwars.1240="Add to bank" +bedwars.1241="Kill" +bedwars.1242="Completing Objective" +bedwars.1243="Collecting Resources" +bedwars.1244="Sharing Resources" +bedwars.1245="Destroying Bed" +bedwars.1246="Lucky Doubles" +bedwars.1247="Lucky 4v4v4v4" +bedwars.1248="All generators are maxed! Your bed has three layers of protection! Left click while holding wool to activate bridge building!" +bedwars.1249="Collect Lucky Blocks from resource generators to receive random loot! Break them to reveal their contents!" +bedwars.1250="Buy and place beds on capture points to drain the enemy team’s health or destroy all the enemy team’s beds then eliminate all players before they can place a new bed." +bedwars.1251="To win a game of Bed Wars Capture" +bedwars.1252="The portable enderchest you were using has disappeared!" +bedwars.1253="Breaking a bed will plant beautiful flowers in its memory." +bedwars.1254="Fishy" +bedwars.1255="Breaking a bed will summon dehydrated fish looking for a nearby lake." +bedwars.1256="Burp" +bedwars.1257="Rage" +bedwars.1258="Drama Queen" +bedwars.1259="Plotting Revenge" +bedwars.1260="Gapple" +bedwars.1261="Champion's Chalice" +bedwars.1262="Skullsword" +bedwars.1263="Noble" +bedwars.1264="was crushed by" +bedwars.1265="was dominated by" +bedwars.1266="was thrown off their high horse by" +bedwars.1267="was assassinated by" +bedwars.1268="was degraded by" +bedwars.1269="Ice Cold" +bedwars.1270="Golden" +bedwars.1271="Wave" +bedwars.1272="Covers the map in snow and spawns some snowman friends!" +bedwars.1273="Fanbase" +bedwars.1274="Your very own fanbase will spawn around you, and every single one of them wants your autograph on their forehead!" +bedwars.1275="Another Dimension" +bedwars.1276="Spawns a portal to a new dimension! Maybe it's the next game..?" +bedwars.1277="resources" +bedwars.1278="Let's attack %%option%%" +bedwars.1279="There are no teams left alive to target!" +bedwars.1280="No Teams to target!" +bedwars.1281="Wrapped Present" +bedwars.1282="Couldn't find anything to target on the compass!" +bedwars.1283="There are no teams to track!" +bedwars.1284="Normal Lucky Block" +bedwars.1285="Promising Lucky Block" +bedwars.1286="Fortunate Lucky Block" +bedwars.1287="Offensive Lucky Block" +bedwars.1288="Miracle Lucky Block" +bedwars.1289="Sharp Spoon" +bedwars.1290="Spicy Sword" +bedwars.1291="Fling Bow" +bedwars.1292="Battle Axe" +bedwars.1293="Scythe" +bedwars.1294="Chicken Bow" +bedwars.1295="DEVIL!" +bedwars.1296="Diamond Sheep" +bedwars.1297="Drops a diamond every 5 seconds for a total of 30s" +bedwars.1298="Diamond Sheep" +bedwars.1299="Disco Clay" +bedwars.1300="Place color-shifting hardened clay!" +bedwars.1301="Explosive Chicken" +bedwars.1302="Explosive Chicken" +bedwars.1303="Shoots explosive eggs at your opponents!" +bedwars.1304="Your trap queue is full!" +bedwars.1305="Filled your trap queue with %%traps%%!" +bedwars.1306="Instant Trap Queue" +bedwars.1307="Instantly fills your trap queue with random traps" +bedwars.1308="Instant Barrier" +bedwars.1309="Right click to place an instant obsidian barrier in the direction you're looking!" +bedwars.1310="You already have the best weapon!" +bedwars.1311="Upgraded your weapon to %%material%%!" +bedwars.1312="Instant Weapon Upgrade" +bedwars.1313="Instantly upgrades your weapon" +bedwars.1314="Knockback Slimeball" +bedwars.1315="Lava Rune" +bedwars.1316="Right-click a block to place temporary lava!" +bedwars.1317="You must use this on your bed!" +bedwars.1318="Protective Bed Cover" +bedwars.1319="Magically builds a 3-layer protective cover over your bed" +bedwars.1320="Rainbow Wool" +bedwars.1321="Places a random colored wool!" +bedwars.1322="You've already unlocked all available team upgrades!" +bedwars.1323="Random Team Upgrade" +bedwars.1324="Resource Trader" +bedwars.1325="Sleepinator" +bedwars.1326="Attack players to give them blindness!" +bedwars.1327="Unsafe TP location!" +bedwars.1328="Telebow" +bedwars.1329="Cute Pants" +bedwars.1330="So cuuuute! ❤" +bedwars.1331="Disco Armor" +bedwars.1332="Party like there's no tomorrow!" +bedwars.1333="Regen II (5s) on melee or arrow hit" +bedwars.1334="Frog Helmet" +bedwars.1335="Jump Boost while wearing" +bedwars.1336="Heat-Resistant Boots" +bedwars.1337="Hot Head" +bedwars.1338="Always on fire" +bedwars.1339="Things hitting you catch on fire" +bedwars.1340="Glorious Beacon" +bedwars.1341="You've been buffed by the Glorious Beacon!" +bedwars.1342="This beacon gives Strength!" +bedwars.1343="Your Blaze Rider power will expire in 10 seconds!" +bedwars.1344="Your Blaze Rider power has expired!" +bedwars.1345="The Blaze is on %%health%% HP!" +bedwars.1346="Gravity Gun" +bedwars.1347="Send your enemies flying!" +bedwars.1348="Super Star" +bedwars.1349="Immune to most damage for 15 seconds" +bedwars.1350="You can't activate your own trap!" +bedwars.1351="%%player%% set off your Mimic Trap!" +bedwars.1352="You set off %%player%%'s Mimic Trap!" +bedwars.1353="Mimic!" +bedwars.1354="Turns into a Zombie if someone tries to open it!" +bedwars.1355="Mystery Meat" +bedwars.1356="Can be eaten while satiated, gives 3 random potion effects for 15 seconds each" +bedwars.1357="Pig Launcher" +bedwars.1358="Shoot pigs at your enemies!" +bedwars.1359="Rush Pearl" +bedwars.1360="You will ride this pearl after you throw it" +bedwars.1361="Sword of Justice: %%remaining%%s" +bedwars.1362="Please wait for your Time Warp Pearl to expire!" +bedwars.1363="Your Time Warp Pearl has expired!" +bedwars.1364="You will be warped back in %%seconds%% seconds!" +bedwars.1365="Time Warp Pearl" +bedwars.1366="Magic Toy Stick" +bedwars.1367="Water Balloon" +bedwars.1368="Spawns water where it hits" +bedwars.1369="NEW! Lucky Blocks" +bedwars.1370="Play Bed Wars %%mode%%" +bedwars.1371="You can't use this yet! Please try again later." +bedwars.1372="Your Speed & Strength effects will expire in %%seconds%% seconds!" +bedwars.1373="Your Weakness effect will expire in %%seconds%% seconds!" +bedwars.1374="Gives you Speed and Strength, but also great Weakness! Lasts for %%seconds%% seconds." +bedwars.1375="Sleepyhead Coffee Beans" +bedwars.1376="Wicked Z-type" +bedwars.1377="Happy Pumpkin" +bedwars.1378="Avoid triggering traps for 30 seconds after consuming." +bedwars.1379="You respawned because you still have a bed!" +bedwars.1380="You respawned because your bed had not been destroyed at the time of you being killed!" +bedwars.1381="BED DESTRUCTION > %%team%% Bed %%kill_message%% %%tc%%%%player%%!" +bedwars.1382="You will be able to select the %%resource%%." +bedwars.1383="%%time%% %%type%% Armor" +bedwars.1384="No Emeralds" +bedwars.1385="Get rid of em hasty emeralds" +bedwars.1386="No Diamonds" +bedwars.1387="To hell with those shiny things" +bedwars.1388="Disable Block Protection" +bedwars.1389="Allows players to break any blocks, excluding blocks around generators and spawns." +bedwars.1390="Bed Instabreak" +bedwars.1391="Beds break with a single punch." +bedwars.1392="Event Times" +bedwars.1393="Modify the time for events." +bedwars.1394="0.5x - Slower" +bedwars.1395="1x - Normal" +bedwars.1396="2x - Faster" +bedwars.1397="4x - Fastest" +bedwars.1398="Respawn Time" +bedwars.1399="Modify player respawn time." +bedwars.1400="1 Second" +bedwars.1401="5 Seconds" +bedwars.1402="10 Seconds" +bedwars.1403="Alarm trap set off by %%team%% team!" +bedwars.1404="ALARM!!!" +bedwars.1405="Alarm trap set off by %%player%% from %%team%% team!" +bedwars.1406="There are %%count%% team members nearby." +bedwars.1407="%%bed%% Bed " +bedwars.1408="%%bed%% Bed: " +bedwars.1409="was stomped by" +bedwars.1410="was thrown down a pit by" +bedwars.1411="was thrown to the ground by" +bedwars.1412="was shot by" +bedwars.1413="was outclassed by" +bedwars.1414="was bed #%%bed%% destroyed by" +bedwars.1415="Sword of Justice" +bedwars.1416=" - Spawn Horse with right-click" +bedwars.1417="You have %%seconds%%s left to pick your companion!" +bedwars.1418="Your armor grew spikes!" +bedwars.1419="You have received another gauntlet upgrade! Your punches are now even more lethal!" +bedwars.1420="You have received a gauntlet upgrade! Your punches are now more lethal!" +bedwars.1421="You have been disguised as a %%team%% team player!" +bedwars.1422="Your %%tool%% has been upgraded!" +bedwars.1423="You already have the best available %%tool%%." +bedwars.1424="You have received a permanent axe!" +bedwars.1425="You have received a permanent pickaxe!" +bedwars.1426="APOCALYPSE BY %%player%%" +bedwars.1427="You copied %%player%%'s inventory!" +bedwars.1428="%%player%% copied your inventory!" +bedwars.1429="You activated a stasis effect on all players for %%duration%% seconds!" +bedwars.1430="seconds" +bedwars.1431="There are no players in front of you!" +bedwars.1432="You used the Force!" +bedwars.1433="Stasis by %%player%% for %%time%% %%plural%%!" +bedwars.1434="You've been violently pushed by %%player%%'s force!" +bedwars.1435="%%player%% HAS USED THE FORCE ON YOU" +bedwars.1436="You need to aim at a proper target!" +bedwars.1437="Invalid location soldier! Aim it somewhere else!" +bedwars.1438="... TRANSMISSION RECEIVED ... " +bedwars.1439="NUCLEAR PAYLOAD AIMED AT %%coords%%" +bedwars.1440="RECOMMENDING IMMEDIATE EVAC" +bedwars.1441="... TRANSMISSION ENDED ... " +bedwars.1442="☣ NUCLEAR LAUNCH DETECTED ☣" +bedwars.1443="BY %%player%%" +bedwars.1444="You exploded in %%player%%'s nuke!" +bedwars.1445="NUCLEAR PAYLOAD REPORT AT %%coords%%" +bedwars.1446="NO CASUALTIES. TRAIN HARDER, SOLDIER!" +bedwars.1447="SINGLE CASUALTY. TRY HARDER NEXT TIME, SOLDIER!" +bedwars.1448="DOUBLE CASUALTIES. GOOD JOB, SOLDIER!" +bedwars.1449="CONFIRMED MULTI-CASUALTIES. GREAT JOB, SOLDIER!" +bedwars.1450="CONFIRMED MASSIVE CASUALTIES. AWESOME WORK!" +bedwars.1451="You have been killed by %%player%%'s Roulette blitz!" +bedwars.1452="You have killed %%player%% with a Roulette blitz!" +bedwars.1453="Vampire Blood wore off!" +bedwars.1454="YOUR HEALTH IS BEING DRAINED BY %%player%%" +bedwars.1455="+%%size%% hp/s draining: %%players%%" +bedwars.1456="Get within 20 blocks of a player to drain their blood!" +bedwars.1457="Incredible!" +bedwars.1458="WATCH OUT! You can only pick one item! Choose carefully!" +bedwars.1459="ONLY %%time%% SECONDS REMAINING FOR YOUR INCREDIBLE CHEST!" +bedwars.1460="This is not yours!" +bedwars.1461="%%player%% cursed you!" +bedwars.1462="There aren't any enemy beds nearby!" +bedwars.1463="%%time%% %%tool%%" +bedwars.1464="Bunny in a Suit" +bedwars.1465="Oak Log" +bedwars.1466="Oak Plank" +bedwars.1467="Acacia Log" +bedwars.1468="Acacia Plank" +bedwars.1469="Birch Log" +bedwars.1470="Birch Plank" +bedwars.1471="Dark Oak Log" +bedwars.1472="Dark Oak Plank" +bedwars.1473="Jungle Log" +bedwars.1474="Jungle Plank" +bedwars.1475="Spruce Log" +bedwars.1476="Spruce Plank" +bedwars.1477="Wood Skin" +bedwars.1478="Change the Skin of Wood in game." +bedwars.1479="4v4 is the classic Bed Wars everyone knows and loves but with only 1 enemy!" +bedwars.1480="Daily Final Kills" +bedwars.1481="Final K/D Ratio" +bedwars.1482="Daily Wins" +bedwars.1483="Rush Statistics" +bedwars.1484="Ultimate Statistics" +bedwars.1485="Lucky Statistics" +bedwars.1486="Voidless Statistics" +bedwars.1487="Armed Statistics" +bedwars.1488="Team Selector (Right Click)" +bedwars.1489="Click to select your team!" +bedwars.1490="Click to be a Spectator" +bedwars.1491="Current spectators:" +bedwars.1492="Team Selector" +bedwars.1493="There can not be more than 4 spectators!" +bedwars.1494="You will be a spectator!" +bedwars.1495="That team is full!" +bedwars.1496="%%color%% TEAM" +bedwars.1497="Mummy" +bedwars.1498="Purchase Failed! Your inventory is full!" +bedwars.1499="Purchase guns at Shops or at the Weapons Chest!" +bedwars.1500="I couldn't find a team for you!" +bedwars.1501="Bed Broken by %%killer%%" +bedwars.1502="WIN STREAKS DISABLED" +bedwars.1503="This weapon is out of ammo!" +bedwars.1504="At this rate, a draw will happen in %%minutes%% minute!" +bedwars.1505="Your Bed" +bedwars.1506="[Tournament] High bracket games are played incognito!" +bedwars.1507="%%color%%+%%amount%% Diamond" +bedwars.1508="The trap queue is full! Wait for an enemy player to trigger a trap." +bedwars.1509="Activate a streak power to defend your team's base and attack the enemy team!" +bedwars.1510="No pass backs! Quickly find someone new to give the potato to!" +bedwars.1511="You can't use /shout in this mode." +bedwars.1512="You need to target a player! Spell wasted!" +bedwars.1513="%%killer%%'s Final Kill #%%num%%" +bedwars.1514="Click to visit the Banker" +bedwars.1515="BED WARS BANKER" +bedwars.1516="LEFT-CLICK to reload." +bedwars.1517="CAPTURED" +bedwars.1518="Cost: %%cost%% Emerald" +bedwars.1519="Use the Banker to store resources which will be accessible to your whole team." +bedwars.1520="ACTIVE TOURNAMENT!!!" +bedwars.1521="You can collect streak points through kills and collecting and sharing resources." +bedwars.1522="Read Full Changes" +bedwars.1523="XP Multiplier: %%mult%%" +bedwars.1524="%%team%% win in %%time%%" +bedwars.1525="I don't understand what world to put you on (Player)!" +bedwars.1526="Tournament" +bedwars.1527="You can't damage your own bed!" +bedwars.1528="Happy Holidays! Gifts dropped at %%type%% generators!" +bedwars.1529="Updated shops" +bedwars.1530="10s" +bedwars.1531="Stats, achievements and quests will NOT be earned in private games!" +bedwars.1532="Your Bed Wars Win Streak will not change during this game." +bedwars.1533="You can only use Streak Powers in Castle Mode!" +bedwars.1534="You triggered %%owner%%'s %%type%% trap!" +bedwars.1535="You have claimed the max amount of gifts this game!" +bedwars.1536=" Bed Wars v1.4" +bedwars.1537="Your pumpkins were automatically registered by winning!" +bedwars.1538="Can't place this! Bring it back to a shopkeeper!" +bedwars.1539="Tracking: " +bedwars.1540="Teleported you to %%name%%!" +bedwars.1541="You were sent to a lobby because someone in your party left!" +bedwars.1542="Capture a point to enable respawn!" +bedwars.1543="Mining Upgrade II" +bedwars.1544="%%reason%%There was an error while rewarding some of your Tributes!" +bedwars.1545="You can not apply this enchant!" +bedwars.1546="%%team%% set to win in %%minutes%% minute!" +bedwars.1547="Something went wrong! Report this to staff!" +bedwars.1548="Your invisibility was removed by an Alarm Trap!" +bedwars.1549="Draw in %%time%%" +bedwars.1550="%%player%% claimed some gifts!" +bedwars.1551="Contents of %%name%%'s Ender Chest have been dropped into their fountain." +bedwars.1552="Someone triggered your mining fatigue trap!" +bedwars.1553="It seems you've lost an item by throwing it in a place you can't re-obtain it! The item has been put back into your inventory!" +bedwars.1554="%%count%% Alive" +bedwars.1555="Creeper Army" +bedwars.1556="Poison Bolt" +bedwars.1557="Mines now produce emeralds!" +bedwars.1558="Halloween Event" +bedwars.1559="Warps nearby enemy players back to their base!" +bedwars.1560="Blocks" +bedwars.1561="That command is disabled while you are a player." +bedwars.1562="Final Kill by %%killer%%" +bedwars.1563="%%team%% team has lost a control point!" +bedwars.1564="There is not enough space here!" +bedwars.1565="Win Streaks are temporarily disabled due to an ongoing maintenance!" +bedwars.1566="Soul ripped" +bedwars.1567="You can only use the Banker in Castle Mode!" +bedwars.1568="Lost Final Control Point" +bedwars.1569="Bed Destroyed by %%killer%%" +bedwars.1570="Thanks!" +bedwars.1571="You are already on the %%color%%%%colorname%% team!" +bedwars.1572="This player already has an active Hot Potato! Find someone else!" +bedwars.1573="There are no dream modes available right now!" +bedwars.1574="That weapon is... what?" +bedwars.1575="by %%who%%" +bedwars.1576="You can't claim that yet!" +bedwars.1577="(Right click at target)" +bedwars.1578="Bring gifts back to any shopkeeper." +bedwars.1579="Your bed is under attack!" +bedwars.1580="%%player%% claimed a gift!" +bedwars.1581="XP Multiplier: %%mult%%" +bedwars.1582="Win via elimination of enemy teams health or players." +bedwars.1583="v1.4 Features:" +bedwars.1584="You have the hot potato! Quickly punch someone to pass it on!" +bedwars.1585="RE-VOTE!" +bedwars.1586="Chat is disabled during pregame in this bracket!" +bedwars.1587="I can't find a game in that world!" +bedwars.1588="Click to view all Streaks" +bedwars.1589="VIEW STREAKS" +bedwars.1590="Return to categories!" +bedwars.1591="Back" +bedwars.1592="You already have an extra bed!" +bedwars.1593="New traps" +bedwars.1594="Be careful of your teams health." +bedwars.1595="You were kicked for inactivity! " +bedwars.1596="You just landed a HEADSHOT!" +bedwars.1597="A %%trap%% trap has been placed for your team!" +bedwars.1598="You can't empty buckets here!" +bedwars.1599="Gifts claimed!" +bedwars.1600="Team: %%team%%" +bedwars.1601="Lucky Blocks" +bedwars.1602="Level: %%format%%" +bedwars.1603="Spectate" +bedwars.1604="I don't understand what world to put you on (World)!" +bedwars.1605="CAPTURING" +bedwars.1606="The %%color%%%%colorname%% team is full!" +bedwars.1607="Gun #%%number%%" +bedwars.1608="You have joined the %%color%%%%colorname%% team!" +bedwars.1609="Capture Mode Beta." +bedwars.1610="You have joined a game in-progress! Bed Wars Castle supports continuous join for the best experience!" +bedwars.1611="I can't find the world to send you to!" +bedwars.1612="Late initialization of tourney game..." +bedwars.1613="You were a player and a spectator, you are now a spectator." +bedwars.1614="Awww!" +bedwars.1615="Potions" +bedwars.1616="Bed Wars BETA (%%mode%%)" +bedwars.1617="Final Point Lost" +bedwars.1618="%%count%% hits! You poisoned %%players%%!" +bedwars.1619="Bed Wars Capture is currently closed!" +bedwars.1620="%%color%%+%%amount%% Bed" +bedwars.1621="Bracket: %%bracket%%" +bedwars.1622="You've poisoned %%player%%!" +bedwars.1623="To respawn you need one capture point." +bedwars.1624="(BETA)" +bedwars.1625="You are alerted when enemies enter your base, while the enemies receive 4 seconds of blindness!" +bedwars.1626="Hype: %%hype%%/%%maxHype%%" +bedwars.1627="Launch" +bedwars.1628="Thank you for taking part in v1.4 beta. The following features are now live on all modes:" +bedwars.1629="Heal self" +bedwars.1630="%%team%% team has captured a control point!" +bedwars.1631="Your team has fully upgraded this!" +bedwars.1632="➜ %%count%%x %%name%%: %%rewards%%" +bedwars.1633="Your Bed Wars Win Streak was not reset due to an ongoing maintenance!" +bedwars.1634="Buzzzz!" +bedwars.1635="You need %%cost%% %%resource%%! You have %%count%% %%resource%%!" +bedwars.1636="Current players:" +bedwars.1637="Mine productivity is doubled!" +bedwars.1638="You will respawn when your team captures a point!" +bedwars.1639="%%team%% team has captured a %%resource%% generator!" +bedwars.1640="Guns will deal more damage for your entire team" +bedwars.1641="Awaiting Respawn!" +bedwars.1642="Use beds to capture points and defend them." +bedwars.1643="The Hot Potato exploded!" +bedwars.1644="There you go!" +bedwars.1645="Right Click to join this team!" +bedwars.1646="Sharing resources will award you streak points (and make your team mates happy)" +bedwars.1647="%%team%% team has taken a %%resource%% generator from %%from%% team!" +bedwars.1648="Guns deal %%tier%%% more damage" +bedwars.1649="VIEW BANKER" +bedwars.1650="On Hypixel" +bedwars.1651="R.I.P. %%victim%%" +bedwars.1652="First Win of the Tournament" +bedwars.1653="You can track the enemy team by purchasing a tracker with the compass!" +bedwars.1654="Tools" +bedwars.1655="[Tournament] This game, you are known as: %%name%%" +bedwars.1656="You've been poisoned by %%player%%!" +bedwars.1657="Mining Upgrade I" +bedwars.1658="%%player%% has triggered your %%type%% trap!" +bedwars.1659="TNT Fountain" +bedwars.1660="%%team%% set to win in %%minutes%% minutes!" +bedwars.1661="That weapon doesn't exist" +bedwars.1662="You cannot build any further down!" +bedwars.1663="Wheee!" +bedwars.1664="Double XP during Tournament" +bedwars.1665="Place bed to capture!" +bedwars.1666="Your Bed Wars Win Streak did not increase due to an ongoing maintenance!" +bedwars.1667="UPCOMING TOURNAMENT!" +bedwars.1668="Play Bed Wars v%%version%%" +bedwars.1669="Border Shrinking..." +bedwars.1670="Banker" +bedwars.1671="Mine productivity is increased by 50%!" +bedwars.1672="New maps" +bedwars.1673="Grants Speed I and Jump Boost II for 10 seconds to allied players near your base." +bedwars.1674="You will be afk-ed in 10 seconds!" +bedwars.1675="You must wait %%seconds%% seconds between chat messages in Castle mode!" +bedwars.1676="%%color%%+%%amount%% Beds" +bedwars.1677="Could not find a game for you :(" +bedwars.1678="5% from perk" +bedwars.1679="You launched %%player%% in the air!" +bedwars.1680="◼ 40+ cosmetics" +bedwars.1681="You didn't hit any player! Spell wasted!" +bedwars.1682="You don't have enough Emerald!" +bedwars.1683="An %%trap%% trap has been placed for your team!" +bedwars.1684=" HAPPY EASTER" +bedwars.1685="ENEMY OWNS NO CONTROL POINTS" +bedwars.1686="That game is in pregame! /tpto -f %%name%% to ignore this warning!" +bedwars.1687="Max Upgrade!" +bedwars.1688="Someone triggered your mining fatigue trap!" +bedwars.1689="Enemy Bed" +bedwars.1690="You temporarily absorbed the giant's power!" +bedwars.1691="Gift claimed!" +bedwars.1692="You purchased %%ict%% %%name%% for %%cost%% %%resource%%! You have %%count%% %%resource%%!" +bedwars.1693="%%distance%%m" +bedwars.1694="Your wildcard saved you from death!" +bedwars.1695="Picked up a Holiday gift!" +bedwars.1696="Click to send the message: "%%option%%"" +bedwars.1697="You need %%ct%% %%resource%% to buy this!" +bedwars.1698="You don't have an item to support this enchant!" +bedwars.1699="Armor" +bedwars.1700="A spider's home!" +bedwars.1701="Mining Upgrade III" +bedwars.1702="Awaiting Respawn" +bedwars.1703="No players alive!" +bedwars.1704="You've been launched in the air by %%player%%!" +bedwars.1705="Double hit! You poisoned %%players%%!" +bedwars.1706="You can't fill buckets!" +bedwars.1707="by %%player%%" +bedwars.1708="Bed Wars beta is currently closed!" +bedwars.1709="Eliminate all players to win!" +bedwars.1710="%%tc%%%%name%% reconnected." +bedwars.1711="Inflicts Blindness and Slowness for 8 seconds." +bedwars.1712="%%name%% Scroll" +bedwars.1713="BED CREATION > An extra %%bed%% bed has been placed by %%player%%" +bedwars.1714="This lobby is currently closed." +bedwars.1715="%%name%% was kicked for being AFK!" +bedwars.1716="At this rate, a draw will happen in %%minutes%% minutes!" +bedwars.1717="Ooooww!" +bedwars.1718="Bows" +bedwars.1719="BED WARS STREAKS" +bedwars.1720="Not a number! We don't want blockX players. Tired of algebra." +bedwars.1721="Bed Wars 4v4 is currently closed!" +bedwars.1722="4v4" +bedwars.1723="You need to aim at something! Spell wasted!" +bedwars.1724="LAUNCHED!" +bedwars.1725="This block has not been placed by a player!" +bedwars.1726="Enemy Points Lost" +bedwars.1727="This item is already set as a favourite!" +bedwars.1728="An enemy has entered your base!" +bedwars.1729="%%color%%%%colorname%% Team" +bedwars.1730="Weapons" +bedwars.1731="Error! Cannot find BedGame. Please do /whereami and report the output to a staff member!" +bedwars.1732="Your team was split for balancing purposes." +bedwars.1733="Booom!" +bedwars.1734="Miscellaneous" +bedwars.1735="An Illusion Trap warped you back to your island!" +bedwars.1736="Build limit reached!" +bedwars.1737="Bed Wars Capture" +bedwars.1738="Something went wrong so you was removed from the game! Please report this to a member of staff! [PGS-SPEC]" +bedwars.1739="%%player%%'s Horse" +bedwars.1740="%%color%%+%%amount%% Emerald" +bedwars.1741="Click on a block to place the wither!" +bedwars.1742="Max players is now set at %%GameManager%%" +bedwars.1743="Bed Health: %%health%%" +bedwars.1744="An error has occurred in your session!" +bedwars.1745="You've healed yourself up to your maximum health!" +bedwars.1746="You can't drop gifts!" +bedwars.1747="Tadada!" +bedwars.1748="[Tournament] You can still /wdr on incognito players!" +bedwars.1749="RIGHT-CLICK to shoot." +bedwars.1750="Pistol" +bedwars.1751="Magnum" +bedwars.1752="Rifle" +bedwars.1753="Not-a-Flamethrower" +bedwars.1754="Shotgun" +bedwars.1755="Upside Down Snowman" +bedwars.1756="Present Man" +bedwars.1757="Error claiming gifts: No game!" +bedwars.1758="Error claiming gifts: No team!" +bedwars.1759="%%player%% was killed by %%killer%%'s %%mob%%." +bedwars.1760="Your %%bed%% was destroyed by %%killer%%!" +bedwars.1761="%%team%% %%bed%% was destroyed by %%killer%%!" +bedwars.1762="%%player%% was shot by %%killer%%." +bedwars.1763="%%player%% was knocked off a cliff by %%killer%%." +bedwars.1764="%%team%% has been eliminated!" +bedwars.1765="%%player%% was struck down by %%killer%%." +bedwars.1766="%%player%% was turned to dust by %%killer%%." +bedwars.1767="%%player%% was turned to ash by %%killer%%." +bedwars.1768="%%player%% was melted by %%killer%%." +bedwars.1769="%%player%% was fried by %%killer%%'s %%mob%%." +bedwars.1770="Your %%bed%% was incinerated by %%killer%%!" +bedwars.1771="%%team%% %%bed%% was incinerated by %%killer%%!" +bedwars.1772="%%player%% was filled full of lead by %%killer%%." +bedwars.1773="%%player%% met their end by %%killer%%." +bedwars.1774="%%player%% lost a drinking contest with %%killer%%." +bedwars.1775="%%player%% was killed with dynamite by %%killer%%." +bedwars.1776="%%player%% lost the draw to %%killer%%'s %%mob%%." +bedwars.1777="Your %%bed%% was iced by %%killer%%!" +bedwars.1778="%%team%% %%bed%% was iced by %%killer%%!" +bedwars.1779="%%player%% was given the cold shoulder by %%killer%%." +bedwars.1780="%%player%% was hit off by a love bomb from %%killer%%." +bedwars.1781="%%player%% was out of the league of %%killer%%." +bedwars.1782="%%player%% was struck with Cupid's arrow by %%killer%%." +bedwars.1783="%%player%% was no match for %%killer%%'s %%mob%%." +bedwars.1784="Your %%bed%% was dismantled by %%killer%%!" +bedwars.1785="%%team%% %%bed%% was dismantled by %%killer%%!" +bedwars.1786="%%player%% be sent to Davy Jones' locker by %%killer%%." +bedwars.1787="%%player%% be cannonballed to death by %%killer%%." +bedwars.1788="%%player%% be killed with magic by %%killer%%." +bedwars.1789="%%player%% be shot and killed by %%killer%%." +bedwars.1790="%%player%% be killed with metal by %%killer%%'s %%mob%%." +bedwars.1791="Your %%bed%% be shot with cannon by %%killer%%!" +bedwars.1792="%%team%% %%bed%% be shot with cannon by %%killer%%!" +bedwars.1793="%%player%% was glazed in BBQ sauce by %%killer%%." +bedwars.1794="%%player%% slipped in BBQ sauce off the edge spilled by %%killer%%." +bedwars.1795="%%player%% was not spicy enough for %%killer%%." +bedwars.1796="%%player%% was thrown chilli powder at by %%killer%%." +bedwars.1797="%%player%% was sliced up by %%killer%%'s %%mob%%." +bedwars.1798="Your %%bed%% was deep fried by %%killer%%!" +bedwars.1799="%%team%% %%bed%% was deep fried by %%killer%%!" +bedwars.1800="%%player%% was spooked by %%killer%%." +bedwars.1801="%%player%% was spooked off the map by %%killer%%." +bedwars.1802="%%player%% was totally spooked by %%killer%%." +bedwars.1803="%%player%% was remotely spooked by %%killer%%." +bedwars.1804="%%player%% was spooked by %%killer%%'s %%mob%%." +bedwars.1805="Your %%bed%% was spooked by %%killer%%!" +bedwars.1806="%%team%% %%bed%% was spooked by %%killer%%!" +bedwars.1807="%%player%% was wrapped into a gift by %%killer%%." +bedwars.1808="%%player%% hit the hard-wood floor because of %%killer%%." +bedwars.1809="%%player%% was pushed down a slope by %%killer%%." +bedwars.1810="%%player%% was put on the naughty list by %%killer%%." +bedwars.1811="%%player%% was turned to gingerbread by %%killer%%'s %%mob%%." +bedwars.1812="Your %%bed%% was traded in for milk and cookies by %%killer%%!" +bedwars.1813="%%team%% %%bed%% was traded in for milk and cookies by %%killer%%!" +bedwars.1814="%%player%% got rekt by %%killer%%." +bedwars.1815="%%player%% took the L to %%killer%%." +bedwars.1816="%%player%% got roasted by %%killer%%." +bedwars.1817="%%player%% got smacked by %%killer%%." +bedwars.1818="%%player%% got bamboozled by %%killer%%'s %%mob%%." +bedwars.1819="Your %%bed%% got memed by %%killer%%!" +bedwars.1820="%%team%% %%bed%% got memed by %%killer%%!" +bedwars.1821="%%player%% was bitten by %%killer%%." +bedwars.1822="%%player%% howled into the void for %%killer%%." +bedwars.1823="%%player%% was distracted by a puppy placed by %%killer%%." +bedwars.1824="%%player%% caught the ball thrown by %%killer%%." +bedwars.1825="%%player%% played too rough with %%killer%%'s %%mob%%." +bedwars.1826="Your %%bed%% was ripped apart by %%killer%%!" +bedwars.1827="%%team%% %%bed%% was ripped apart by %%killer%%!" +bedwars.1828="%%player%% died in close combat to %%killer%%." +bedwars.1829="%%player%% fought to the edge with %%killer%%." +bedwars.1830="%%player%% stumbled off a ledge with help by %%killer%%." +bedwars.1831="%%player%% tangoed with %%killer%%'s %%mob%%." +bedwars.1832="Your %%bed%% had to raise the white flag to %%killer%%!" +bedwars.1833="%%team%% %%bed%% had to raise the white flag to %%killer%%!" +bedwars.1834="%%player%% was hunted down by %%killer%%." +bedwars.1835="%%player%% stumbled on a trap set by %%killer%%." +bedwars.1836="%%player%% was thrown into a volcano by %%killer%%." +bedwars.1837="%%player%% got skewered by %%killer%%." +bedwars.1838="%%player%% was mauled by %%killer%%'s %%mob%%." +bedwars.1839="Your %%bed%% was sacrificed by %%killer%%!" +bedwars.1840="%%team%% %%bed%% was sacrificed by %%killer%%!" +bedwars.1841="%%player%% was tragically backstabbed by %%killer%%." +bedwars.1842="%%player%% was heartlessly let go by %%killer%%." +bedwars.1843="%%player%% was delivered into nothingness by %%killer%%." +bedwars.1844="%%player%% was dismembered by %%killer%%'s %%mob%%." +bedwars.1845="Your %%bed%% was dreadfully corrupted by %%killer%%!" +bedwars.1846="%%team%% %%bed%% was dreadfully corrupted by %%killer%%!" +bedwars.1847="%%player%% was locked outside during a snow storm by %%killer%%." +bedwars.1848="%%player%% was pushed into a snowbank by %%killer%%." +bedwars.1849="%%player%% was shoved down an icy slope by %%killer%%." +bedwars.1850="%%player%% was hit with a snowball from %%killer%%." +bedwars.1851="%%player%% got snowed in by %%killer%%'s %%mob%%." +bedwars.1852="Your %%bed%% was made into a snowman by %%killer%%!" +bedwars.1853="%%team%% %%bed%% was made into a snowman by %%killer%%!" +bedwars.1854="%%player%% was oinked by %%killer%%." +bedwars.1855="%%player%% slipped into void for %%killer%%." +bedwars.1856="%%player%% was distracted by a piglet from %%killer%%." +bedwars.1857="%%player%% got attacked by a carrot from %%killer%%." +bedwars.1858="%%player%% was oinked by %%killer%%'s %%mob%%." +bedwars.1859="Your %%bed%% was gulped by %%killer%%!" +bedwars.1860="%%team%% %%bed%% was gulped by %%killer%%!" +bedwars.1861="%%player%% was stomped by %%killer%%." +bedwars.1862="%%player%% was thrown down a pit by %%killer%%." +bedwars.1863="%%player%% was thrown to the ground by %%killer%%." +bedwars.1864="%%player%% was shot by %%killer%%." +bedwars.1865="%%player%% was outclassed by %%killer%%'s %%mob%%." +bedwars.1866="%%player%% was crushed by %%killer%%." +bedwars.1867="%%player%% was dominated by %%killer%%." +bedwars.1868="%%player%% was thrown off their high horse by %%killer%%." +bedwars.1869="%%player%% was assassinated by %%killer%%." +bedwars.1870="%%player%% was degraded by %%killer%%'s %%mob%%." +bedwars.1871="%%player%% was chewed up by %%killer%%." +bedwars.1872="%%player%% was scared into the void by %%killer%%." +bedwars.1873="%%player%% was distracted by a rat dragging pizza from %%killer%%." +bedwars.1874="%%player%% stepped in a mouse trap placed by %%killer%%." +bedwars.1875="%%player%% squeaked around with %%killer%%'s %%mob%%." +bedwars.1876="Your %%bed%% was squeaked apart by %%killer%%!" +bedwars.1877="%%team%% %%bed%% was squeaked apart by %%killer%%!" +bedwars.1878="%%player%% was painted pretty by %%killer%%." +bedwars.1879="%%player%% was deviled into the void by %%killer%%." +bedwars.1880="%%player%% was flipped off the edge by %%killer%%." +bedwars.1881="%%player%% slipped into a pan placed by %%killer%%." +bedwars.1882="%%player%% was made sunny side up by %%killer%%'s %%mob%%." +bedwars.1883="Your %%bed%% was scrambled by %%killer%%!" +bedwars.1884="%%team%% %%bed%% was scrambled by %%killer%%!" +bedwars.1885="%%player%% was buzzed to death by %%killer%%." +bedwars.1886="%%player%% was bzzz'd into the void by %%killer%%." +bedwars.1887="%%player%% was stung off the edge by %%killer%%." +bedwars.1888="%%player%% was startled by %%killer%%." +bedwars.1889="%%player%% was bee'd by %%killer%%'s %%mob%%." +bedwars.1890="Your %%bed%% was stung by %%killer%%!" +bedwars.1891="%%team%% %%bed%% was stung by %%killer%%!" +bedwars.1892="%%player%% was whacked with a party balloon by %%killer%%." +bedwars.1893="%%player%% was popped into the void by %%killer%%." +bedwars.1894="%%player%% was launched like a firework by %%killer%%." +bedwars.1895="%%player%% was shot with a roman candle by %%killer%%." +bedwars.1896="%%player%% was lit up by %%killer%%'s %%mob%%." +bedwars.1897="Your %%bed%% exploded from a firework by %%killer%%!" +bedwars.1898="%%team%% %%bed%% exploded from a firework by %%killer%%!" +bedwars.1899="%%player%% was wrapped up by %%killer%%." +bedwars.1900="%%player%% was tied into a bow by %%killer%%." +bedwars.1901="%%player%% tripped over a present placed by %%killer%%." +bedwars.1902="%%player%% was glued up by %%killer%%." +bedwars.1903="%%player%% was taped together by %%killer%%'s %%mob%%." +bedwars.1904="Your %%bed%% was stuffed with tissue paper by %%killer%%!" +bedwars.1905="%%team%% %%bed%% was stuffed with tissue paper by %%killer%%!" +bedwars.1906="%%colorName%% Team" +bedwars.1907="BED DESTRUCTION > %%killMessage%%" +bedwars.1908="TEAM ELIMINATED > %%killMessage%%" +bedwars.1909="number of final kills and bed" +bedwars.1910="destroys." +bedwars.1911="Your %%bed%% was bed #%%stat%% destroyed by %%killer%%!" +bedwars.1912="%%team%% %%bed%% was bed #%%stat%% destroyed by %%killer%%!" +bedwars.1913="%%player%% was %%killer%%'s final #%%stat%%." +bedwars.1914="%%player%% was bested by %%killer%%." +bedwars.1915="%%player%% was knocked into the void by %%killer%%." +bedwars.1916="%%player%% was knocked off an edge by %%killer%%." +bedwars.1917="%%player%% was shot by %%killer%%." +bedwars.1918="%%player%% was bested by %%killer%%'s %%mob%%." +bedwars.1919="Click to join the %%team%%." +bedwars.1920="Cross-teaming is not allowed! Report cross-teamers using /report." +bedwars.1921="Beds Status: %%beds%%" +bedwars.1922="Something went wrong when breaking the bed, please report this at https://hypixel.net/bugs! Please include the following error code in your report: BW_BED_CASH" +bedwars.1923="%%tc%%%%team%% won!" +bedwars.1924="%%bed%% Bed Alarm trap set off by %%team%% team!" +bedwars.1925="%%bed%% Bed: Alarm trap set off by %%player%% from %%team%% team!" +bedwars.1926=" Bed Wars XP" +bedwars.1927="Kangaroo" +bedwars.1928=" Armed" +bedwars.1929="Enemy Team" +bedwars.1930="1st Capture" +bedwars.1931="%%magic%%MN LEVEL UP! You are now %%prestige%%! %%magic%%NM" +bedwars.1932="You are already tracking that team!" +bedwars.1933="Voidless" +bedwars.1934="BED WARS COMP" +bedwars.1935="BED WARS CAPTURE" +bedwars.1936="Happy Holidays" +bedwars.1937="Player" +bedwars.1938="3rd Capture" +bedwars.1939="DRAW!" +bedwars.1940="Prestige" +bedwars.1941="Purchase tracking upgrade for your compass which will track the closest player on a specific team until you die." +bedwars.1942="2nd Capture" +bedwars.1943="CLOSED" +bedwars.1944="4v4" +bedwars.1945=" Lucky Blocks V2" +bedwars.1946="Your Team" +bedwars.1947="You will not lose this on death!" +bedwars.1948="It's a trap!" +bedwars.1949="Bridge Egg" +bedwars.1950="Red Team" +bedwars.1951="Blue Team" +bedwars.1952="Green Team" +bedwars.1953="Yellow Team" +bedwars.1954="Aqua Team" +bedwars.1955="White Team" +bedwars.1956="Pink Team" +bedwars.1957="Gray Team" +bedwars.1958="Firecracker" +bedwars.1959="Red Envelope" +bedwars.1960="%%player%% was crushed into moon dust by %%killer%%." +bedwars.1961="%%player%% was sent the wrong way by %%killer%%." +bedwars.1962="%%player%% was blasted to the moon by %%killer%%." +bedwars.1963="%%player%% was hit by an asteroid from %%killer%%." +bedwars.1964="%%player%% was blown up by %%killer%%'s %%mob%%." +bedwars.1965="Your %%bed%% was blasted to dust by %%killer%%!" +bedwars.1966="%%player%% was trampled by %%killer%%." +bedwars.1967="%%player%% was back kicked into the void by %%killer%%." +bedwars.1968="%%player%% was headbutted off a cliff by %%killer%%." +bedwars.1969="%%player%% was impaled from a distance by %%killer%%." +bedwars.1970="%%player%% was trampled by %%killer%%'s %%mob%%." +bedwars.1971="Your %%bed%% was impaled by %%killer%%!" +bedwars.1972="%%team%% %%bed%% was blasted to dust by %%killer%%!" +bedwars.1973="%%team%% %%bed%% was impaled by %%killer%%!" +bedwars.1974="Wood Skins" +bedwars.1975="Select the %%name%% %%category%% to be used when placing wood blocks." +bedwars.1976="Witch's Potion" +bedwars.1977="Bridge Egg" +bedwars.1978="Compact Pop-up Tower" +bedwars.1979="Egg with Bow" +bedwars.1980="Hot Cross Bun" +bedwars.1981="Easter Flower" +bedwars.1982="Chocolate Egg" +bedwars.1983="Blue Sheep Pajamas" +bedwars.1984="Purple Pig Pajamas" +bedwars.1985="Aqua Duck Pajamas" +bedwars.1986="Red Frog Pajamas" +bedwars.1987="Pink Bunny Pajamas" +bedwars.1988="Green Cow Pajamas" +bedwars.1989="Pink Rabbit" +bedwars.1990="Blue Rabbit" +bedwars.1991="Stormy Bed Destroy" +bedwars.1992="Couldn't put you on the %%team%% Team!" +bedwars.1993="Joined the %%team%% Team!" +bedwars.1994="You are already on the %%team%% Team!" +bedwars.1995="Practice" +bedwars.1996="Improve your gameplay by practicing different aspects of Bed Wars!" +bedwars.1997="Click to view modes!" +bedwars.1998="Core Modes" +bedwars.1999="4 Team Modes" +bedwars.2000="Infinite!" +bedwars.2001="Unable to get your team?!" +bedwars.2002="Stick of Second Chances" +bedwars.2003="Another wolf has joined your herd!" +bedwars.2004="Your Stick of Second Chances has saved you from certain death! You have %%time%% seconds of invulnerability!" +bedwars.2005="Keeping this stick in your inventory will allow you to evade death for a short moment when low on health!" +bedwars.2006="Practice mode is currently disabled, please try again later!" +bedwars.2007="Speed: " +bedwars.2008="Blocks Placed: " +bedwars.2009="Enable Wool" +bedwars.2010="Start with %%amount%% of the selected item." +bedwars.2011="%%prefix%%What do you want?" +bedwars.2012="Platform Position: %%position%%" +bedwars.2013="%%prefix%%Okay, you can stop." +bedwars.2014="Armed" +bedwars.2015="NEW PERSONAL BEST" +bedwars.2016="Something went wrong when breaking the bed, please report this at https://hypixel.net/bugs! Please include the following error code in your report: BW_BLANK_RAY" +bedwars.2017="You are in combat and can not recall!" +bedwars.2018="How do you have wool?!" +bedwars.2019="Castle BETA" +bedwars.2020="Teleports all teammates back to base after 5 seconds!" +bedwars.2021="You have that already selected." +bedwars.2022="You cannot go this far out!" +bedwars.2023="Reinstancing you to a new server due to an update!" +bedwars.2024="Platform Tallness: %%size%%" +bedwars.2025="You will start with 32 blocks of wool." +bedwars.2026="Practice" +bedwars.2027="Set the angle of the finishing island to %%angle%%." +bedwars.2028="Completed! Took %%time%% seconds, with a top speed of %%top%%" +bedwars.2029="Set the finishing island distance to be %%blocks%% blocks away." +bedwars.2030="Took %%time%% seconds, with %%placed%% blocks placed!" +bedwars.2031="Using this sword to damage players will provide a Trick or Treat!" +bedwars.2032="Lucky Blocks V2" +bedwars.2033="Trick or Treat Sword" +bedwars.2034="Platform Size: %%size%%" +bedwars.2035="%%prefix%%Why are you doing this?" +bedwars.2036="%%prefix%%Okay if I give you some souls will you stop?" +bedwars.2037="The landing platform will be placed random." +bedwars.2038="Set the elevation level of the finishing island to %%elevation%%." +bedwars.2039="No item shuffle." +bedwars.2040="4v4 stats no longer count to the Core Modes leaderboards." +bedwars.2041="Well well well, how the turn tables..." +bedwars.2042="Cost: %%cost%% Souls" +bedwars.2043="Receive %%count%% %%item%% in exchange for %%souls%% souls." +bedwars.2044="%%amount%% Items" +bedwars.2045="This item is currently on cooldown!" +bedwars.2046="%%blocks%% Blocks" +bedwars.2047="%%count%%x %%resource%%" +bedwars.2048="Recall Teammates" +bedwars.2049="Return to Lobby" +bedwars.2050="%%prefix%%STOP!" +bedwars.2051="%%prefix%%Are you... twerking?" +bedwars.2052="BED WARS PRACTICE" +bedwars.2053="Mode Selector" +bedwars.2054="Mode: " +bedwars.2055="Collect souls by killing players, mobs, and breaking beds." +bedwars.2056="You can only select a mode every 5 seconds!" +bedwars.2057="You cannot build this far out!" +bedwars.2058="Platform Height: %%height%%" +bedwars.2059="You cannot purchase this again just yet!" +bedwars.2060="You don't have any teammates to recall!" +bedwars.2061="You will respawn in %%seconds%% second!" +bedwars.2062="Chat is disabled in Bed Wars Practice!" +bedwars.2063="Bed Wars BETA" +bedwars.2064="Your Souls: %%count%%" +bedwars.2065="FIREBALL/TNT JUMPING" +bedwars.2066="Crafting is disabled!" +bedwars.2067="Wool cannot be placed more than 2 blocks from the platform edge." +bedwars.2068="You will start with %%item%%" +bedwars.2069="Use the items to jump as far as you can!" +bedwars.2070="Set the platform to be %%blocks%% blocks tall." +bedwars.2071="Have no finishing island and see how far you can go." +bedwars.2072="You can only switch your ultimate every 30 seconds!" +bedwars.2073="This shuffles the slot of the item after jumping down. This requires you to react quickly and change your slot before making use of the item." +bedwars.2074="%%prefix%%I said..." +bedwars.2075="RECALL! You will be teleported back to your base in %%time%% seconds!" +bedwars.2076="You already have that selected." +bedwars.2077="Disable Wool" +bedwars.2078="Personal Best: " +bedwars.2079="Updated your settings." +bedwars.2080="The landing platform will always be placed right in front of your island." +bedwars.2081="Useful for trying to clutch onto the side of the platform." +bedwars.2082="Get on the gold blocks without taking fall damage." +bedwars.2083="Cooldown: %%cooldown%% seconds" +bedwars.2084="%%prefix%%Fine, but you better stop!" +bedwars.2085="Become a Soul Collector and trade in your collected souls to the underworld for resources and special items in the Item Shop! Collect souls by killing players, mobs, and breaking beds." +bedwars.2086="Failed! Top speed of %%top%%" +bedwars.2087="%%prefix%%Don't make me angry." +bedwars.2088="+%%count%% Souls" +bedwars.2089="BAWK!" +bedwars.2090="Item: %%item%%" +bedwars.2091="Shuffle item after jumping." +bedwars.2092="Click to Activate!" +bedwars.2093="All beds can now be broken!" +bedwars.2094="You had a challenge activated, but we had to disable it since you joined a team game without a full party!" +bedwars.2095="You cannot attack using this item during the %%challenge%% challenge!" +bedwars.2096="WATCH OUT! Rain is toxic and drains items from your inventory" +bedwars.2097="Traps Queue" +bedwars.2098="Currently Active: %%challenge%%" +bedwars.2099="You have reached the max level for this upgrade in this mode!" +bedwars.2100="You cannot purchase this during the %%challenge%% challenge." +bedwars.2101="Swappage" +bedwars.2102="The center island has fallen, only side islands remain for resources! Generators spawn resources quicker!" +bedwars.2103="You do not have the authority to break this bed!" +bedwars.2104="New Target:" +bedwars.2105="Looking for a new way to play Bed Wars? Enhance your gameplay with exciting challenges!" +bedwars.2106="You cannot damage players with this item during the %%challenge%% challenge" +bedwars.2107="You cannot break this bed for another %%time%%" +bedwars.2108="Click to view challenges!" +bedwars.2109="%%time%%" +bedwars.2110="Activated Challenge: %%challenge%%" +bedwars.2111="You can't attack this player yet! Your target is: %%color%%%%target%%" +bedwars.swap_subtitle="New team: " +bedwars.2113="You failed the %%challenge%% challenge. Better luck next time!" +bedwars.2114="%%playerWhoFailed%% stepped on enemy blocks, so your team failed the %%challenge%% challenge" +bedwars.2115="Cost: ??" +bedwars.2116="Beds are unbreakable for the first %%minutes%% minutes. Fight for resources and prepare for battle!" +bedwars.2117="Challenge Locked!" +bedwars.2118="Purchasable" +bedwars.swap_team_changed="Your team swapped and you are now: " +bedwars.2120="RED LIGHT" +bedwars.2121="Challenges are a unique way to increase the difficulty of the game for you and your team. To unlock additional challenges, you must first complete currently unlocked challenges." +bedwars.2122="Your President is %%name%%. Protect your leader at all costs!" +bedwars.swap_title="bb SWAPPAGE bb" +bedwars.game_start.title="Bed Wars" +bedwars.game_start.swappage_title="Bed Wars Swappage" +bedwars.2124="CLOSED BETA" +bedwars.2125="Challenge active" +bedwars.2126="Locked Slot" +bedwars.2127="You collected %%color%%%%teamName%%Team's wool (%%size%%/%%need%%)" +bedwars.2128="You cannot drop anything during the %%challenge%% challenge" +bedwars.2129="Kills: %%kills%% Final Kills: %%finals%% Beds Broken: %%beds%%" +bedwars.2130="You cannot consume this item during the %%challenge%% challenge" +bedwars.2131=" - %%color%%%%reward%%" +bedwars.2132="%%name%% sprinted, so your team has failed the %%challenge%% challenge" +bedwars.2133="Challenge Rules:" +bedwars.2134="You successfully defused this bed!" +bedwars.2135="Rewards Claimed" +bedwars.2136="No Active Challenge" +bedwars.2137="You cannot use this item during the %%challenge%% challenge" +bedwars.2138="????" +bedwars.2139="So, you think you're pretty good, eh? Good luck not taking ANY damage" +bedwars.2140="Total Challenge Wins: %%completed%%" +bedwars.2141="Unlocked through Challenges" +bedwars.2142="You cannot open this Chest during the %%challenge%% challenge" +bedwars.2143="Grace" +bedwars.2144="Bed Wars Challenges" +bedwars.2145="You unlocked: %%name%%" +bedwars.2146="%%num%%. %%line%%" +bedwars.2147="Your team has collected all the required wool. Now win the game to complete the %%challenge%% challenge!" +bedwars.2148="You will respawn because you still have a bed!" +bedwars.2149="Click to Disable!" +bedwars.2150="Centerless" +bedwars.2151="Leaderboard re-sync completed!" +bedwars.2152="Your President has fallen, and your team has failed the %%challenge%% challenge" +bedwars.2153="Only your President may break enemy beds." +bedwars.2154="Grants Speed II and Jump Boost II for 15 seconds to allied players near your base." +bedwars.2155="%%whoMoved%% moved during a red light, so your team has failed the %%challenge%% challenge" +bedwars.2156="CHALLENGE ACTIVE!" +bedwars.2157="Active Challenge: %%challenge%%" +bedwars.2158="%%challenge%%" +bedwars.2159="That game is in pregame! /tpto -f name to ignore this warning!" +bedwars.2160="Click to Disable!" +bedwars.2161="You have not unlocked this challenge yet!" +bedwars.2162="Wins with Challenge: %%wins%%" +bedwars.2163="Challenge Information" +bedwars.2164="You have reached your challenge purchase limit for this item" +bedwars.2165="You can not purchase this any more this game!" +bedwars.game_start.swappage_description="Players swap teams at random intervals! Players also swap positions with the players of the team they are swapping to!" +bedwars.2167="Invisible Item Shop" +bedwars.2168="%%name%% took damage, so your team has failed the %%challenge%% challenge!" +bedwars.2169="[ADMIN DEBUG] That command would have been blocked because you are a spectator, but you are an admin!" +bedwars.2170="Disable Active Challenge" +bedwars.2171="Challenges" +bedwars.2172="WARNING! Beds can be broken in 1 minute" +bedwars.2173="Challenges Completed: %%completed%%/%%total%%" +bedwars.2174="You can move again!" +bedwars.2175="Target: %%color%%%%target%%" +bedwars.2176="You cannot use this item during the %%challenge%% challenge!" +bedwars.2177="You cannot use swords during the %%challenge%% challenge" +bedwars.2178="Remaining Purchases: %%remaining%%" +bedwars.2179="You failed the %%challenge%% challenge!" +bedwars.2180="C4 (Click REDSTONE)" +bedwars.2181="You must defuse this bed!" +bedwars.2182="You do not have enough Stamina to perform this action!" +bedwars.2183="RED LIGHT IN" +bedwars.2184="Your new target is: %%color%%%%target%%" +bedwars.2185="%%name%% the Elder Guardian" +bedwars.2186="You cannot purchase this item during this challenge" +bedwars.2187="You can't use this item during the %%challenge%% challenge" +bedwars.2188="GREEN LIGHT" +bedwars.2189="Deactivated Challenge: %%challenge%%" +bedwars.2190="Click to claim reward%%s%%!" +bedwars.2191="You can't break this bed yet! Your target is: %%color%%%%target%%" +bedwars.2192="You cannot place this block during the %%challenge%% challenge" +bedwars.2193="Disable Active Challenge" +bedwars.2194="You are the President. Now lead your team to victory!" +bedwars.2195="Don't Move!" +bedwars.2196="%%time%%" +bedwars.2197="%%color%%%%target%%" +bedwars.2198="You may now freely move for the rest of the game" +bedwars.2199="You failed the %%challenge%% challenge" +bedwars.2200="Good Luck!" +bedwars.2201="Remaining Purchases: %%remaining%%" +bedwars.2202="TEAM CHALLENGE ACTIVE!" +bedwars.2203="Reward%%s%%:" +bedwars.2204="This chest is locked during the %%challenge%% challenge" +bedwars.2205="Your Core Modes Lifetime stats have successfully been re-sync'd!" +bedwars.2206="%%name%%" +bedwars.2207="%%name%% crouched, so your team has failed the %%challenge%% challenge!" +bedwars.2208="Renegade" +bedwars.2209="Team upgrades and traps are disabled" +bedwars.2210="You cannot pick up diamonds" +bedwars.2211="Warmonger" +bedwars.2212="You cannot purchase nor use any utilities to aid you in battle" +bedwars.2213="Selfish" +bedwars.2214="You are too selfish to drop any items to other players" +bedwars.2215="Your team chest and Ender Chest are locked" +bedwars.2216="Minimum Wage" +bedwars.2217="Your island resource generator is 2x slower" +bedwars.2218="Assassin" +bedwars.2219="You can only break the bed of your assigned target" +bedwars.2220="No other beds can be broken until you eliminate your target's entire team" +bedwars.2221="After successfully eliminating your target team, a new target will be assigned" +bedwars.2222="Regular Shopper" +bedwars.2223="Any purchased armor upgrade will be removed upon death" +bedwars.2224="Any purchased tool upgrade will be reset upon death" +bedwars.2225="Invisible Shop" +bedwars.2226="Every item slot in the Item Shop and Team Upgrades is randomized and hidden" +bedwars.2227="The locations of each item will remain the same throughout the game" +bedwars.2228="Collector" +bedwars.2229="Collect all wool colors and return them to your shop keeper" +bedwars.2230="You must win the game after all team members return all wool colors" +bedwars.2231="Woodworker" +bedwars.2232="You can only purchase and pick up items made out of wood" +bedwars.2233="You cannot use your Ender Chest, it isn't made of wood!" +bedwars.2234="Bridging for Dummies" +bedwars.2235="You cannot purchase any blocks other than sponge" +bedwars.2236="You cannot pick up any blocks" +bedwars.2237="Toxic Rain" +bedwars.2238="There will be toxic rain throughout the game" +bedwars.2239="Standing in the rain drains items from your inventory" +bedwars.2240="The longer you are in the rain, the faster items drain" +bedwars.2241="Defuser" +bedwars.2242="Every enemy team's bed needs to be defused before being able to break it" +bedwars.2243="Once you defuse an enemy's bed defense, it will stay defused for 2 minutes" +bedwars.2244="Lazy Miner" +bedwars.2245="You gain permanent Mining Fatigue throughout the game" +bedwars.2246="If you activate a Mining Fatigue Trap, you receive a greater Mining Fatigue effect" +bedwars.2247="TNT and fireballs are disabled" +bedwars.2248="Ultimate UHC" +bedwars.2249="Natural health regeneration is disabled" +bedwars.2250="Golden Apples do not provide health" +bedwars.2251="Sleight of Hand" +bedwars.2252="You only have 1 available hotbar slot to use" +bedwars.2253="Weighted Items" +bedwars.2254="Each item has a unique weight to them" +bedwars.2255="Carrying heavy items will make you move slower" +bedwars.2256="Social Distancing" +bedwars.2257="You can only use Knockback Sticks and Punch Bows to attack players" +bedwars.2258="Swordless" +bedwars.2259="You cannot purchase any swords from the shop" +bedwars.2260="You cannot pick up any swords" +bedwars.2261="Using axes or pickaxes will only deal 1 damage to players" +bedwars.2262="Marksman" +bedwars.2263="You cannot hit any players with melee weapons, including your fist" +bedwars.2264="You can only attack players using a bow" +bedwars.2265="Patriot" +bedwars.2266="You can only walk on blocks your team has placed" +bedwars.2267="You cannot pick up any items from enemy players" +bedwars.2268="You do not receive any items from killing a player" +bedwars.2269="You can only pick up resources from your own generator" +bedwars.2270="If you walk on blocks placed by an enemy team, the challenge will be failed" +bedwars.2271="Stamina" +bedwars.2272="Any action in the game such as running or breaking blocks consumes stamina" +bedwars.2273="If you don't have enough stamina, you won't be able to sprint or break blocks" +bedwars.2274="Your stamina is represented by your hunger bar" +bedwars.2275="Golden Apples double your stamina recharge rate for 10 seconds" +bedwars.2276="Old Man" +bedwars.2277="You cannot sprint during the whole game" +bedwars.2278="If you sprint, the challenge will be failed" +bedwars.2279="Capped Resources" +bedwars.2280="All shop items have a limited purchase cap for your entire team" +bedwars.2281="Red Light, Green Light" +bedwars.2282="At random intervals the stop light will switch between red and green" +bedwars.2283="If you move when the light is red, you fail the challenge" +bedwars.2284="Slow Reflexes" +bedwars.2285="You can only hit enemies once every 2 seconds" +bedwars.2286="Pacifist" +bedwars.2287="You cannot use any bows to deal damage" +bedwars.2288="You can only use Utilities to deal damage" +bedwars.2289="Master Assassin" +bedwars.2290="You can only damage players of your target team" +bedwars.2291="Standing Tall" +bedwars.2292="You cannot sneak during the challenge" +bedwars.2293="If you crouch, the challenge will be failed" +bedwars.2294="Protect the President" +bedwars.2295="One player on the team is selected as the President" +bedwars.2296="Only the President has the authority to break enemy beds" +bedwars.2297="If the President dies, you fail the challenge" +bedwars.2298="Can't Touch This" +bedwars.2299="You must not take any damage for the whole game" +bedwars.2300="If you take any damage or fall into the void, the challenge will be failed" +bedwars.2301="Your team must break at least 1 bed to complete the challenge" +bedwars.2302="%%player%% was smothered in holiday cheer by %%killer%%." +bedwars.2303="%%player%% was banished into the ether by %%killer%%'s holiday spirit." +bedwars.2304="%%player%% was pushed by %%killer%%'s holiday spirit." +bedwars.2305="%%player%% was sniped by a missile of festivity by %%killer%%." +bedwars.2306="%%player%% was sung holiday tunes to by %%killer%%'s %%mob%%." +bedwars.2307="Your %%bed%% was melted by %%killer%%'s holiday spirit!" +bedwars.2308="%%team%% %%bed%% was melted by %%killer%%'s holiday spirit!" +bedwars.2309="Fai Chun" +bedwars.2310="Lunar Gold" +bedwars.2311="Penjing" +bedwars.2312="Ramen" +bedwars.2313="%%player%% was ripped to shreds by %%killer%%." +bedwars.2314="%%player%% was charged by %%killer%%." +bedwars.2315="%%player%% was ripped and thrown by %%killer%%." +bedwars.2316="%%player%% was pounced on by %%killer%%." +bedwars.2317="%%player%% was ripped to shreds by %%killer%%'s %%mob%%." +bedwars.2318="Your %%bed%% was ripped to shreds by %%killer%%." +bedwars.2319="%%team%% %%bed%% was ripped to shreds by %%killer%%." +bedwars.2320="Blast-Proof Glass" +bedwars.2321="Bridging" +bedwars.2322="Practice bridging across the void with wool." +bedwars.2323="MLG" +bedwars.2324="Practice preventing fall damage with water buckets and ladders." +bedwars.2325="Fireball/TNT Jumping" +bedwars.2326="Practice jumping over the void using Fireballs and TNT." +bedwars.2327="Place water before hitting the ground." +bedwars.2328="Place the ladder and land on its side." +bedwars.2329="Slime Boots" +bedwars.2330="Place to give your team an extra bed" +bedwars.2331="Placeable Bed" +bedwars.2332="HOT! HOT! HOT!" +bedwars.2333="Fastest Completion: %%time%% (#%%rank%%)" +bedwars.2334="%%tc%%%%name%% disconnected." +bedwars.2335="Wins with Challenge: %%wins%% (#%%rank%%)" +bedwars.2336="BOING!" +bedwars.2337="Place a block to start!" +bedwars.2338="Right-click to open the current mode settings. Changing mode settings allows for a wider variety of practice drills and different levels of difficulty." +bedwars.2339="Right-click to open the mode selector." +bedwars.2340="Successful!" +bedwars.2341="Failed!" +bedwars.2342="%%player%% had a small brain moment while fighting %%killer%%." +bedwars.2343="%%player%% was not able to block clutch against %%killer%%." +bedwars.2344="%%player%% forgot how many blocks they had left while fighting %%killer%%." +bedwars.2345="%%player%% got 360 no-scoped by %%killer%%." +bedwars.2346="%%player%% got absolutely destroyed by %%killer%%'s %%mob%%." +bedwars.2347="Your %%bed%% has left the game after seeing %%killer%%!" +bedwars.2348="%%team%% %%bed%% has left the game after seeing %%killer%%!" +bedwars.2349="Social Distance" +bedwars.2350="%%player%% was too shy to meet %%killer%%." +bedwars.2351="%%player%% didn't distance themselves properly from %%killer%%." +bedwars.2352="%%player%% tripped while trying to run away from %%killer%%." +bedwars.2353="%%player%% was coughed at by %%killer%%." +bedwars.2354="%%player%% got too close to %%killer%%'s %%mob%%." +bedwars.2355="Your %%bed%% was contaminated by %%killer%%!" +bedwars.2356="%%team%% %%bed%% was contaminated by %%killer%%!" +bedwars.2357="%%player%% was yelled at by %%killer%%." +bedwars.2358="%%player%% was thrown off the lawn by %%killer%%." +bedwars.2359="%%player%% slipped on the fake teeth of %%killer%%." +bedwars.2360="%%player%% was accidentally spit on by %%killer%%." +bedwars.2361="%%player%% was chased away by %%killer%%'s %%mob%%." +bedwars.2362="Your %%bed%% was sold in a garage sale by %%killer%%!" +bedwars.2363="%%team%% %%bed%% was sold in a garage sale by %%killer%%!" +bedwars.2364="%%player%% fell to the great marksmanship of %%killer%%." +bedwars.2365="Burned Up" +bedwars.2366="Turn those beds into a pile of ash!" +bedwars.2367="Lightning Strike Final Kill Effect" +bedwars.2368="You can't activate any more streaks of this tier!" +bedwars.2369="%%player%%'s heart was pierced by %%killer%%." +bedwars.2370="%%name%% was set off!" +bedwars.2371="Slight" +bedwars.2372="Staircase" +bedwars.2373="Reach For The Sky" +bedwars.2374="The landing platform will be 5x5 blocks." +bedwars.2375="The landing platform will be 3x3 blocks." +bedwars.2376="The landing platform will be a single block." +bedwars.2377="Lazy Bunnies" +bedwars.2378="Egg Decorations" +bedwars.2379="Easter Sweater" +bedwars.2380="Bunny Parkour" +bedwars.2381="Flower Bed" +bedwars.2382="Grow patches of beautiful flowers all around the map!" +bedwars.2383="Spread pumpkins wherever you walk!" +bedwars.2384="Plays a short festive tune after you win!" +bedwars.2385="Exploding Bunnies" +bedwars.2386="Core Mode Leaderboards" +bedwars.2387="Ride a flying chicken and shoot exploding eggs!" +bedwars.2388="Spawns villagers around you only for them all to be infected!" +bedwars.2389="Heat Wave" +bedwars.quick_communication.player_incoming="Player incoming!" +bedwars.2391="1st Border" +bedwars.2392="2nd Border" +bedwars.2393="3rd Border" +bedwars.2394="Your %%trap%% has been set off!" +bedwars.2395="Your %%bed%% Bed %%trap%% has been set off!" +bedwars.2396="Play a game of Bed Wars Solo.\n\nFight against 7 other players!\nDestroy enemy beds to stop them from respawning!\nProtect your bed from destruction!" +bedwars.2397="Play a game of Bed Wars Doubles.\n\nTeam up with 1 other player to defeat 7 enemy teams!\nDestroy enemy beds to stop them from respawning!\nProtect your bed from destruction!" +bedwars.2398="Play a game of Bed Wars 3v3v3v3.\n\nTeam up with 2 other players to defeat 3 other groups of players!\nDestroy enemy beds to stop them from respawning!\nProtect your bed from destruction!" +bedwars.2399="Play a game of Bed Wars 4v4v4v4.\n\nTeam up with 3 other players to defeat 3 other groups of players!\nDestroy enemy beds to stop them from respawning!\nProtect your bed from destruction!" +bedwars.2400="Play a game of Bed Wars 4v4.\n\n4v4 is the classic Bed Wars everyone knows and loves, but with only 1 enemy team!" +bedwars.2401="Play a game of Bed Wars %%mode%%." +bedwars.2402="Bed Wars Dreams is a variety of rotating game modes." +bedwars.2403="Everything is upgraded at the start! Fight to the death right away!" +bedwars.2404="Pick an Ultimate Ability to use any time during the battle!" +bedwars.2405="Gain Speed III and Jump IV for %%seconds%% seconds!" +bedwars.2406="Spawn an Enderman to shuffle most nearby player-placed blocks!" +bedwars.2407="Aggressive pigs will have a %%chance%%% chance to spawn with every hit after eating this porkchop! Lasts for %%duration%% seconds." +bedwars.2408="Deals up to %%damage%%% damage on hit! Max. %%maxdamage%% hearts" +bedwars.2409="This portable Ender Chest does not belong to your team!" +bedwars.2410="Take this Ender Chest everywhere you go! It will despawn %%seconds%% seconds after being placed." +bedwars.2411="Portable Ender Chest" +bedwars.2412="Cancelled teleport!" +bedwars.2413="You can not zap this block!" +bedwars.2414="Right Click on wool to break %%amount%% adjacent wool blocks." +bedwars.2415="Bridge Zapper" +bedwars.2416="Click a block to use this item!" +bedwars.2417="You spawned a %%name%%!" +bedwars.2418="Spawn an egg sentry gun! But watch out when it overheats!" +bedwars.2419="Chicken Turret" +bedwars.2420="Relive your assassin days by landing on the center of this Hay Bale to completely negate fall damage." +bedwars.2421="Hay Bale" +bedwars.2422="Your team is already using a %%name%%" +bedwars.2423="%%player%% used a %%name%%!" +bedwars.2424="You will be teleported to your base in %%delay%% seconds." +bedwars.2425="Click to cancel %%name%%!" +bedwars.2426="Click here to cancel" +bedwars.2427="Miracle of the Holidays" +bedwars.2428="Miracle of the Stars" +bedwars.2429="Just normal ice. Good way to make a speedway." +bedwars.2430="You can't place a %%name%% here!" +bedwars.2431="Easily access the Shopkeeper anywhere with this %%name%%." +bedwars.2432="Portable Shopkeeper" +bedwars.2433="You disarmed this Proximity Mine!" +bedwars.2434="Proximity IED. Can be disarmed by shooting them." +bedwars.2435="Festivity Mine" +bedwars.2436="Proximity Mine" +bedwars.2437="You set off %%player%%'s %%tnt%%!" +bedwars.2438="A ninja's best friend! Right Click to throw." +bedwars.2439="Sugarkens" +bedwars.2440="Shuriken" +bedwars.2441="Like normal TNT, but lighter so you can throw it!" +bedwars.2442="Throwable TNT" +bedwars.2443="After %%seconds%% seconds you will be teleported back to your original location." +bedwars.2444="You have activated your Week Of The Pig ability! It will last for %%duration%% seconds." +bedwars.2445="Healing Chicken" +bedwars.2446="Eat to heal 1 heart." +bedwars.2447="What are Rotating Items?" +bedwars.2448="Rotating Items are items that are only available for a limited amount of time. They may disappear and be replaced with another temporary item at any time." +bedwars.2449="Purchase limit reached!" +bedwars.2450="Purchases Remaining: %%limit%%" +bedwars.2451="Haunted Curse" +bedwars.2452="Rotating Items" +bedwars.2453="Easily access the Shopkeeper anywhere with this %%name%%. Despawns after %%seconds%% seconds" +bedwars.2454="PRIVATE GAMES ONLY" +bedwars.2455="Teleports you and your teammates back to your base after %%delay%% seconds. Disabled after Sudden Death." +bedwars.2456="You must be out of compat for another %%seconds%% second%%s%% before using this item." +bedwars.2457="Cobweb" +bedwars.2458="Unstable Teleportation Device" +bedwars.2459="1/3 Chance of the following:" +bedwars.2460="- Teleports you back to your base." +bedwars.2461="- Teleports you to the exact center of the map." +bedwars.2462="- Teleports you to any random location." +bedwars.2463="Disabled after Sudden Death." +bedwars.2464="Final Revive Beacon" +bedwars.2465="Can be used to revive fallen teammates after your bed is broken. Takes %%seconds%% seconds to power up. Limit 1 use per team. Disabled after Sudden Death." +bedwars.2466="Mega TNT" +bedwars.2467="This super-packed TNT has the explosive capability of blasting through even the toughest glass." +bedwars.2468="Rain Cloud" +bedwars.2469="Sprout" +bedwars.2470="Party Sloth" +bedwars.2471="Hypixel Knight" +bedwars.2472="You are too high up to use this!" +bedwars.2473="You can't place that here!" +bedwars.2474="You're too far out to spawn this!" +bedwars.2475="This is currently on cooldown! You can use this again in %%seconds%%s" +bedwars.2476="Click to spawn a 3x3 Wall." +bedwars.2477="Wall of Steel" +bedwars.2478="You are too high up to throw this!" +bedwars.2479="Headshot!" +bedwars.2480="Hit!" +bedwars.2481="Bullseye!" +bedwars.2482="Missed!" +bedwars.2483="Sets movement settings back to their default states." +bedwars.2484="Reset Movement Settings" +bedwars.2485="Reset Accuracy Stats" +bedwars.2486="Reset your total shots and accuracy stats." +bedwars.2487="Target Distance: %%distance%%" +bedwars.2488="Target Height: %%height%%" +bedwars.2489="Target Speed: %%speed%%" +bedwars.2490="Requires a movement type to be selected." +bedwars.2491="The target is very close to the spawn island." +bedwars.2492="The target is far from the spawn island." +bedwars.2493="The target is very far from the spawn island." +bedwars.2494="The target is 15 blocks above you." +bedwars.2495="The target is equal height to you." +bedwars.2496="The target is 15 blocks below you." +bedwars.2497="Moves the target up and down." +bedwars.2498="Moves the target right and left." +bedwars.2499="Moves the target forward and backward." +bedwars.2500="Makes the target jump up and down." +bedwars.2501="The target moves at a slow pace." +bedwars.2502="The target moves at a medium pace." +bedwars.2503="The target moves at a fast pace." +bedwars.2504="Movement: %%movement%%" +bedwars.2505="Click to toggle between target types." +bedwars.2506="Target Type" +bedwars.2507="Click start to be teleported, then try to clutch!" +bedwars.2508="Successful! Clutched from %%distance%% blocks!" +bedwars.2509="Start" +bedwars.2510="Click to be teleported into the air to start!" +bedwars.2511="Pearl Clutching Settings" +bedwars.2512="Always Face Platform" +bedwars.2513="Face Random Direction" +bedwars.2514="Face a random direction when you start." +bedwars.2515="Distance: %%distance%%" +bedwars.2516="This shuffles the slot of the pearl after starting. This requires you to react quickly and change your slot before making use of the pearl." +bedwars.2517="Shuffle Pearl" +bedwars.2518="Don't Shuffle Pearl" +bedwars.2519="Upgrade resource spawning and capacity on your island." +bedwars.2520="Bed Wars Menu & Shop (Right Click)" +bedwars.2521="This feature is currently disabled, please try again at another time!" +bedwars.2522="Could not find that player in your lobby!" +bedwars.2523="You cannot share your Quick Buy with yourself!" +bedwars.2524="Something went wrong trying to do that, please try again later!" +bedwars.2525="You cannot share your Quick Buy with this player." +bedwars.2526="Invalid UUID. Usage: /openquickbuyshare <uuid>" +bedwars.2527="BOW AIMING/PEARL CLUTCHING" +bedwars.2528="%%gametype%% Menu & Shop" +bedwars.2529="Current Item Rotation" +bedwars.2530="Empty slot!" +bedwars.2531="This is an upgradable item. It will lose 1 tier upon death!" +bedwars.2532="Great to get rid of wool. You will always spawn with these shears" +bedwars.2533="Edit Quick Buy" +bedwars.2534="Edit the layout of your Quick Buy menu in-game." +bedwars.2535="Nobody can share their Quick Buy with you." +bedwars.2536="Only friends can share their Quick Buy with you." +bedwars.2537="Only friends, guild members, and party members can share their Quick Buy with you." +bedwars.2538="Anyone can share their Quick Buy with you." +bedwars.2539="Edit Quick Buy" +bedwars.2540="This is a Quick Buy Slot!" +bedwars.2541="Left Click to set an item in this slot." +bedwars.2542="Left Click to replace the item in this slot." +bedwars.2543="Right Click to remove this item." +bedwars.2544="Click to add this item to your Quick Buy!" +bedwars.2545="Share Quick Buy Layout" +bedwars.2546="Click to share this layout with someone in your lobby!" +bedwars.2547="Something went wrong trying to open that menu, please try again later!" +bedwars.2548="This request has expired." +bedwars.2549="Please wait another %%cooldown%%s before sharing your Quick Buy with that player again." +bedwars.2550="%%color%%%%sender%% has shared their Quick Buy layout with you. Click to view!" +bedwars.2551="Click to view %%sender%%'s Quick Buy layout" +bedwars.2552="Sent your Quick Buy layout to %%color%%%%name%%!" +bedwars.2553="Share Quick Buy Layout" +bedwars.2554="No players!" +bedwars.2555="There are no players in this lobby to share with." +bedwars.2556="Click to share your Quick Buy layout with %%name%%" +bedwars.2557="Options: " +bedwars.2558="Click to change to %%color%%%%option%%!" +bedwars.2559="Quick Buy Share Privacy" +bedwars.2560="Please wait a bit before changing your settings again." +bedwars.2561="Quick Buy Sharing Privacy is now set to %%color%%%%name%%!" +bedwars.2562="%%name%%'s Layout" +bedwars.2563="Click to copy %%name%%'s Quick Buy layout." +bedwars.2564="CAUTION: This will override your current layout." +bedwars.2565="Copied %%name%%'s Quick Buy layout!" +bedwars.2566="Pearl Clutching" +bedwars.2567="Practice saving yourself from the void using Pearls." +bedwars.2568="Practice your aim with various bow and arrow challenges." +bedwars.2569="Spawns in %%seconds%% second" +bedwars.2570="The landing platform will be high up, so you fall very little." +bedwars.2571="The landing platform will be further down, so you fall longer." +bedwars.2572="The landing platform will be very far down, so you fall very long." +bedwars.2573="Change the Skin of Wood in-game." +bedwars.2574="Egg Popper" +bedwars.2575="Breaking a bed will summon hatching eggs!" +bedwars.2576="Shattering Ice" +bedwars.2577="Nothing is better than a nice cool bed." +bedwars.2578="Bite" +bedwars.2579="The End" +bedwars.2580="Aura" +bedwars.2581="Show off how strong your Aura is" +bedwars.2582="Cake Walk" +bedwars.2583="Its an all you can eat buffet, dig in!" +bedwars.2584="Elder Guardian" +bedwars.2585="Ride a flying elder guardian that destroys the map." +bedwars.2586="Anvil Smash" +bedwars.2587="An anvil will smash into the ground when you kill a player." +bedwars.2588="Guardian Rocket" +bedwars.2589="Killing an enemy will spawn some angry Guardians." +bedwars.2590="It's Raining Gold" +bedwars.2591="Killing an enemy will rain gold upon you." +bedwars.2592="Assassin's Blade" +bedwars.2593="Ballista" +bedwars.2594="Big Present" +bedwars.2595="Bluebird" +bedwars.2596="Chimney" +bedwars.2597="Chocolate Bar" +bedwars.2598="Collector's Chest" +bedwars.2599="Demon" +bedwars.2600="Devil" +bedwars.2601="Gingerbread House" +bedwars.2602="Heartbleed" +bedwars.2603="Invisible Villager" +bedwars.2604="Ladybug" +bedwars.2605="Large Rabbit" +bedwars.2606="Leaf" +bedwars.2607="Magic Bunny" +bedwars.2608="Parasol" +bedwars.2609="Presidential Goons" +bedwars.2610="Pudding" +bedwars.2611="Reaper" +bedwars.2612="Sapling" +bedwars.2613="Shopping Cart" +bedwars.2614="Small Rabbit" +bedwars.2615="Spooky Lantern" +bedwars.2616="Surfboard" +bedwars.2617="Tall Carrot" +bedwars.2618="Temple Hut" +bedwars.2619="Thunder" +bedwars.2620="Traffic Light" +bedwars.2621="Witch's House" +bedwars.2622="Zombie Hand" +bedwars.2623="Arcade" +bedwars.2624="Dark Portal" +bedwars.2625="Ghost's Cry" +bedwars.2626="Guardian" +bedwars.2627="Elf with Snow Globe" +bedwars.2628="Killer" +bedwars.2629="Lumberjack" +bedwars.2630="Merchant" +bedwars.2631="Patriotic Eagle" +bedwars.2632="President Sloth" +bedwars.2633="Rudolph" +bedwars.2634="Scarecrow" +bedwars.2635="Skeletor" +bedwars.2636="Warrior" +bedwars.2637="%%player%% was thrown chili powder at by %%killer%%." +bedwars.2638="Water Spout" +bedwars.2639="Crab" +bedwars.2640="Sand Castle" +bedwars.2641="Watermelon" +bedwars.2642="Spooky Hypixel" +bedwars.2643="Black Cat" +bedwars.2644="Grave" +bedwars.2645="Pinecone" +bedwars.2646="Bundled Snowman" +bedwars.2647="Snowy Cabin" +bedwars.2648="You can insert a Minion Skin here to change the appearance of your minion." +bedwars.2649="Explorer's Ornate Enchanted Iron Hammer" +bedwars.2650="What could this be used for? The Hotel Receptionist gives these out on rare occasion after helping enough people." +bedwars.2651="Give Jimmy %%amount%% Slumber Tickets" +bedwars.2652="Can you get me some Nether Stars? Their magical dreamlike attributes should help me remember this dream." +bedwars.2653="Get me %%iron%% %%item%%s and %%coins%% Silver Coins." +bedwars.2654="You must purchase Permanent Shears first!" +bedwars.2655="???" +bedwars.2656="QUEST STARTED" +bedwars.2657="Amount adjusted due to wallet size." +bedwars.2658="Doesn't matter. I need a bunch of %%item%% for my materials." +bedwars.2659="This multiplier only applies to tickets earned in-game." +bedwars.2660="Emerald Shard" +bedwars.2661="You cannot use this item anymore!" +bedwars.2662="%%current%%/%%max%% Slumber Tickets" +bedwars.2663="Talk to Confused Fellow" +bedwars.2664="• Bed Wars Experience - %%chance%%% Chance" +bedwars.2665="Help Inspector Maya find the fifth clue to the murder." +bedwars.2666="But first, take this %%name%%, and this Slumber Inventory." +bedwars.2667="A wool cable from a large block of wool. Seems like it can be attached to something. Breaking enemy wool blocks can yield wool cables." +bedwars.2668="Purchase a firework display" +bedwars.2669="You were given slowness by %%shooter%%'s Frost Bite Arrows!" +bedwars.2670="Doesn't work too well against humans. Too bad there aren't any werewolves around." +bedwars.2671="Ticket Machine now rolling..." +bedwars.2672="Save %%amount%% Iron Nuggets" +bedwars.2673="I made this Explorer's Wallet for you. It's bigger than the one you currently have." +bedwars.2674="A Blitz Star has fallen at %%vector%%!" +bedwars.2675="Sorry, Slumber quests have been temporarily disabled!" +bedwars.2676="Hello! I am the Doorman for the Slumber Hotel." +bedwars.2677="Ah yes here you are with the Diamond Fragments, take those tickets." +bedwars.2678="%%amount%% Figurines" +bedwars.2679="You found the stars!" +bedwars.2680="Mysterious Milkshake" +bedwars.2681="[NPC] Lester Brody: Brooooo" +bedwars.2682="We'll trap him in the sheets, then use the %%stars%% %%item%% to send him back to Solace." +bedwars.2683="You unlocked: +5% Bed Wars Experience Multiplier" +bedwars.2684=" %%line%%" +bedwars.2685="Click to View!" +bedwars.2686="Costs: 100 Slumber Ticket" +bedwars.2687="Apple Milkshake" +bedwars.2688="Click here to view your Slumber Items!" +bedwars.2689="%%cosmeticName%%" +bedwars.2690="Talk to the Confused Fellow" +bedwars.2691="Collect a Spark Plug" +bedwars.2692="Slumber Hotel Entrance" +bedwars.2693="[Nah not right now]" +bedwars.2694="This Milestone will be unlocked once enough players have met the Slumber Hotel owner." +bedwars.2695="You can trade %%emeralds%% Emeralds for %%tickets%% Slumber Tickets!" +bedwars.2696="Obtain Oasis Water" +bedwars.2697="What could be under the cover..." +bedwars.2698="Slumber Quest Log" +bedwars.2699="Find %%amount%% Emerald Shard for Jeremy" +bedwars.2700="That block can't be zapped!" +bedwars.2701="Please wait before using that again!" +bedwars.2702="Milkshakes are sooooo good." +bedwars.2703="Your Tickets: %%currentTickets%%/%%needed%%" +bedwars.2704="Tickets can be used in the Slumber Hotel to unlock quests, content, or cosmetics." +bedwars.2705="There is 1 team member nearby." +bedwars.2706="• Bed Wars Cosmetics - %%chance%%% Chance" +bedwars.2707="Hey, %%name%%, do you have time to have a milkshake together?" +bedwars.2708="This multiplier will increase over time as more players meet the Slumber Hotel owner." +bedwars.2709="One of the rare gems found throughout Bed Wars games. Every time you collect a diamond you have a 20% chance to obtain a Diamond Fragment." +bedwars.2710="You do not have enough Slumber Tickets for this!" +bedwars.2711="Play Bed Wars to obtain Slumber Tickets." +bedwars.2712="Your %%name%% has vanished." +bedwars.2713="[Teleport to the Hotel]" +bedwars.2714="A figurine in your showcase is not unlocked and has been removed!" +bedwars.2715="Continue your slumber adventure to unlock this quest." +bedwars.2716="[NPC] Lester Brody: Bruh" +bedwars.2717="Find %%amount%% Iron Nuggets for Jeremy" +bedwars.2718="Collected %%amount%% Ender Dust from your minion!" +bedwars.2719="You cannot afford this!" +bedwars.2720="Collect %%amount%% %%item%%s by winning any round of Bed Wars." +bedwars.2721="Tickets: %%tickets%%/%%limit%%" +bedwars.2722="Token of Ferocity" +bedwars.2723="Win the Quiz Show!" +bedwars.2724="Hammer Mold" +bedwars.2725="Headshots: " +bedwars.2726="Also bring them to me... %%amount%% %%item%%s should suffice." +bedwars.2727="The Slumber Hotel houses some of Bed Wars' most distinguished guests, who may have quests for you." +bedwars.2728="You can't collect any more Slumber Tickets right now because your wallet is full!" +bedwars.2729="You! %%player%%! Bring me a new %%item%%!" +bedwars.2730="Once you unlock a door and its given room, you will always have access to that room. To enter a room, click on the door after unlocking it." +bedwars.2731="Doesn't this belong to Ratman?" +bedwars.2732="You will no longer receive Slumber Ticket messages!" +bedwars.2733="Keep helping hotel guests until you obtain a %%wallet%%, then come see me again." +bedwars.2734="Collect Iron Nuggets" +bedwars.2735="You put %%name%% to sleep!" +bedwars.2736="Cost: %%count%% Slumber Tickets" +bedwars.2737="Have some tickets and this extra %%item%% I have." +bedwars.2738="Click to teleport to Doorman Dave" +bedwars.2739="PHASE ASCENSION" +bedwars.2740="Click to Exit!" +bedwars.2741="Find %%amount%% Wool Cables for Jeremy" +bedwars.2742="You died while carrying x%%amount%% %%name%%!" +bedwars.2743="You cannot pick up diamonds during the %%challenge%% challenge!" +bedwars.2744="You have activated your Week of the Pig ability! It will last for %%duration%% seconds." +bedwars.2745="+%%amount%% Slumber Tickets!" +bedwars.2746="Escape the temple and talk to John Indigos outside." +bedwars.2747="team" +bedwars.2748="Unlocking Doors" +bedwars.2749="Help John Indigos find an %%map%%, found by breaking dirt, grass, stone, glass, sand, or clay on maps." +bedwars.2750="REPEATABLE QUEST" +bedwars.2751="Click "Collect All" below to collect your items!" +bedwars.2752="Your Week of the Pig ability is already active!" +bedwars.2753="Obtain Ender Dust by teleporting around with Ender Pearls in Bed Wars Matches. Get one mg of Ender Dust of each block travelled." +bedwars.2754="Ideal Layout" +bedwars.2755="Get me %%stars%% %%itemOne%% and %%sheets%% %%itemTwo%%." +bedwars.2756="Straight from the Shopkeeper's personal stash." +bedwars.2757="You do not have enough Emeralds to trade right now!" +bedwars.2758="Silver Blade" +bedwars.2759="Oasis Water" +bedwars.2760="Disabled" +bedwars.2761="Find something that can be used to render the curse of the bridge inert." +bedwars.2762="An %%item%% for decoration..." +bedwars.2763="Speak to the Hotel Receptionist at the front desk." +bedwars.2764="Figurine" +bedwars.2765="Slumber Tickets" +bedwars.2766="Air Freshener" +bedwars.2767="Mythical dust found in Limbo that can render any curse inert." +bedwars.2768="Cannot place this block here!" +bedwars.2769="Leather of the highest possible quality. Only General Daku has been known to have leather of this quality." +bedwars.2770="FINAL REVIVE BEACON > %%color%%%%team%% Beacon was destroyed by %%colorplayer%%%%name%%!" +bedwars.2771="%%pillows%% Pillows! That's the right amount for a load." +bedwars.2772="Collect %%amount%% %%item%% by breaking any enemy wool blocks." +bedwars.2773="You unlocked: +20% Slumber Ticket Multiplier" +bedwars.2774="Tickets Collected: %%amount%%" +bedwars.2775="Hermes Timeworn Mystery Boxes" +bedwars.2776="Unable to purchase!" +bedwars.2777="Bed Wars Experience!" +bedwars.2778="%%name%%" +bedwars.2779="A Mystery chest from many decades ago. Obtained by completing a match of Bed Wars." +bedwars.2780="You currently have %%emeralds%% emeralds. Would you like to trade %%needed%% Emeralds for %%tickets%% Slumber Tickets?" +bedwars.2781="Help Inspector Maya find the fourth clue to the murder." +bedwars.2782="Lost Treasure" +bedwars.2783="%%iron%% %%itemOne%%s and %%emeralds%% %%itemTwo%%s for the frame, %%cables%% %%itemThree%%s for the electronics..." +bedwars.2784="You can now hold up to %%amount%% Slumber Tickets!" +bedwars.2785="%%line%%" +bedwars.2786="You did not find any treasure this time!" +bedwars.2787="A soul extracted from the body of an unknown Bed Wars player who was knocked into the void." +bedwars.2788="Obtain %%amount%% Iron Nuggets for the Blacksmith" +bedwars.2789="Blueberry Milkshake" +bedwars.2790="Collect %%amount%% Bed Sheets" +bedwars.2791="You now feel very refreshed!" +bedwars.2792="The list of possible rewards given out by the Ticket Machine." +bedwars.2793="Talk to Twitchy Joe" +bedwars.2794="Win %%amount%% Bed Wars games in a row." +bedwars.2795="Left Click to use this item!" +bedwars.2796="%%current%%/%%required%% Slumber Tickets" +bedwars.2797="Distressed Yellow Team Wither" +bedwars.2798="The most sought-after gem in every Bed Wars game. Every time you collect an emerald you have a 20% chance to obtain an Emerald Shard." +bedwars.2799="Slumber Items Gained" +bedwars.2800="Golden Ticket" +bedwars.2801="Minion Skin Slot" +bedwars.2802="This is on cooldown! You can use this again in %%time%%s!" +bedwars.2803="You can use this again in %%time%%!" +bedwars.2804="The Slumber Hotel" +bedwars.2805="Bring %%amount%% Bed Sheets to The Ratman. Bed Sheets are obtained by destroying beds." +bedwars.2806="Piece of Glowing Sandpaper" +bedwars.2807="You can't put your team to sleep!" +bedwars.2808="You must complete the following objectives to start this quest:" +bedwars.2809="Automated Shipping" +bedwars.2810="Rarely found throughout the Bed Wars universe, but when found they tend to have high value. To the right person, that is. Obtained from purchasing items in Bed Wars games." +bedwars.2811="Electrical Nightmare" +bedwars.2812="You do not have enough Slumber Tickets to unlock this door!" +bedwars.2813="Strawberry ice cream, whipped cream, white chocolate chips, and strawberry syrup drizzled on top. Our top seller!" +bedwars.2814="NEW QUEST" +bedwars.2815="Diamond Fragment my friend DIAMOND FRAGMENTS!" +bedwars.2816="Platinum Membership" +bedwars.2817="Resuming Automated Messaging System..." +bedwars.2818="You currently have %%emeralds%% emerald. You need %%needed%% Emeralds to trade for Slumber Tickets!" +bedwars.2819="Silver Blade Replay" +bedwars.2820="Limbo Dust" +bedwars.2821="Gizzy seems infatuated with his own ego, barely acknowledging your presence." +bedwars.2822="Click to Disable!" +bedwars.2823="This minion has reached the maximum tier." +bedwars.2824="You cannot unlock this door yet!" +bedwars.2825="Collect %%amount%% Wool Cables" +bedwars.2826="Bring %%count%%x %%item%%s to the shopkeeper, they will keep them safe for Jeremy." +bedwars.2827="You can't drop that!" +bedwars.2828="A rare, shiny, and exclusive version of a Slumber Ticket. People say the Laundry Guy gives these out." +bedwars.2829="Find %%amount%% Diamond Fragments for Jeremy" +bedwars.2830="<- Elevators ->" +bedwars.2831="Increase the speed of your minion by adding minion fuel items here." +bedwars.2832="Oh, I know, %%item%%! Two Hundred milligrams of it!" +bedwars.2833="Click to view!" +bedwars.2834="Can be obtained from finding one in Bed Wars matches." +bedwars.2835="Bring John Something Light and Clean" +bedwars.2836="Progress: %%current%%/%%required%%" +bedwars.2837="Right Click to break a single player-placed block." +bedwars.2838="Summons a wind current to knock back any nearby enemies." +bedwars.2839="Click to pay %%amount%% Slumber Tickets" +bedwars.2840="This intricate door requires a few more items before it can be opened. You will need to continue completing quests within the Slumber Hotel to find those items." +bedwars.2841="You must be out of combat for another %%seconds%% second%%s%% before using this item." +bedwars.2842="Total Ticket Multiplier: +%%amount%%%" +bedwars.2843="Feed Don Espresso %%amount%% Gold Ingots" +bedwars.2844="Completed: %%completed%%" +bedwars.2845="Wow, you're level %%level%%? Impressive!" +bedwars.2846="As you increase the Hotel's population, you may be noticed by the mysterious Hotel owner, who may one day reward you for your hard work!" +bedwars.2847="[I bet I can]" +bedwars.2848="Moonstone Nugget" +bedwars.2849="You have unlocked this door! Click on this door at any time to enter it." +bedwars.2850="With %%leaves%% %%itemOne%% and %%souls%% %%itemTwo%%, I can make more Soul Burgers." +bedwars.2851="Obtain a Hammer Mold" +bedwars.2852="Distressed Red Team Wither" +bedwars.2853="ANYTHING THAT GLITTERS" +bedwars.2854="Bring John Something that will Render the Bridge Inert" +bedwars.2855="I shall reward you with my %%item%%." +bedwars.2856="A murder clue that can be found on some Bed Wars maps after speaking to Inspector Mya Sterling." +bedwars.2857="Interact with a car to obtain a %%item%%." +bedwars.2858="This is on cooldown! You can use this again in %%time%%s" +bedwars.2859="Click to Unlock" +bedwars.2860="%%item%% x%%amount%%" +bedwars.2861="Click" +bedwars.2862="+5% from perk" +bedwars.2863="Obtain %%amount%% %%item%%s. Maybe purchasing items from the shopkeeper in game can help?" +bedwars.2864="Upgrade Slot" +bedwars.2865="Bring the Numbers Back Up" +bedwars.2866="Collect %%amount%% Dreamer's Soul Fragments" +bedwars.2867="Help Peter find his way back to The Pit." +bedwars.2868="Click to toggle wallet full notifications!" +bedwars.2869="Every time you collect an iron ingot you have a 20% chance to obtain an Iron Nugget." +bedwars.2870="Takes priority over regular arrows." +bedwars.2871="Collected %%amount%% Slumber Ticket from your minion!" +bedwars.2872="Help Hermes find %%amount%% Timeworn Mystery Boxes, by completing Bed Wars games." +bedwars.2873="Save %%amount%% Spare Cables" +bedwars.2874="An explorer wouldn't dare be caught without some trusty rope!" +bedwars.2875="Save %%amount%% Emerald Shards" +bedwars.2876="Iron Nugget" +bedwars.2877="Bill Starr will reward you with a Faded Blitz Star after helping him." +bedwars.2878="Opens menu displaying all the clues" +bedwars.2879="Ender Dust Minion X" +bedwars.2880="FINAL REVIVE BEACON > Your team used a %%item%%! Protect the Beacon for %%seconds%% seconds to revive your team!" +bedwars.2881="The wallet can hold up to %%amount%% Slumber Tickets. Quite an upgrade I would say!" +bedwars.2882="Gather %%amount%% %%item%% to feed to Don Espresso. Gold Bars are obtained by finishing a match with unspent gold ingots in your inventory." +bedwars.2883="Come speak to me again after reaching level %%level%%✫." +bedwars.2884="You can only use this item without a bed!" +bedwars.2885="[NPC] %%name%%: " +bedwars.2886="Small Tunnel..." +bedwars.2887="The perfect blend of frozen blueberries, vanilla almond milk, and ice cream." +bedwars.2888="When you break a bed you are rewarded with the sheet." +bedwars.2889="Obtain %%amount%% %%item%% for Combat Artist Sally. Wool Cables can be collected by breaking any enemy wool blocks." +bedwars.2890="You unlocked: Golden Sandman Figurine!" +bedwars.2891="You have not met the requirements for this cosmetic." +bedwars.2892="Who is The Owner?" +bedwars.2893="That player is in the Slumber Hotel and you cannot request to teleport to them right now." +bedwars.2894="Find something that can be used to help John Indigos blow up the Temple Door." +bedwars.2895="I'm sure you'll find something." +bedwars.2896="Click to to collect all items!" +bedwars.2897="A light and clean knife." +bedwars.2898="You will now receive Slumber Ticket messages!" +bedwars.2899="Peter needs to escape" +bedwars.2900="Bring %%amount%% %%item%% to the Laundry Guy. %%item%% are obtained by destroying beds." +bedwars.2901="%%amount%% should unlock it if there is" +bedwars.2902=" All Objectives Completed!" +bedwars.2903="Click to remove from showcase!" +bedwars.2904="Information on where to find each clue can be found in the quest log." +bedwars.2905="Give Jimmy %%amount%% Slumber Tickets." +bedwars.2906="You cannot put this player to sleep again for another %%time%%s!" +bedwars.2907="Give Slumber Tickets" +bedwars.2908="You would have triggered a nearby Sleeping Mine, but you recently slept!" +bedwars.2909="A sturdy, fancy-looking Hammer capable of breaking things, like doors. You'll need an experienced Blacksmith to craft one of these for you." +bedwars.2910="You will start with no wool." +bedwars.2911="Someone like Wally will surely have a spare Block of Mega Walls Obsidian." +bedwars.2912="Find King Flut's missing Amulet" +bedwars.2913="A %%item%%..." +bedwars.2914="Distressed Green Team Wither" +bedwars.2915="TICKET REWARD! %%display%%" +bedwars.2916="Obtained from Ticket Machine" +bedwars.2917="75 Slumber Tickets" +bedwars.2918="Locked Item" +bedwars.2919="Photo of Victim" +bedwars.2920="Obtain %%amount%% Souls for Oasis Spirit" +bedwars.2921="An Error occurred" +bedwars.2922="Owned" +bedwars.2923="The cleanest and clearest water you could ever see. Water this clear can only be obtained from the Oasis." +bedwars.2924="+5% from Slumber bonus" +bedwars.2925="You can improve your minion by adding a minion upgrade item here." +bedwars.2926="Something went wrong, please report this on the forums with error code REMOVE_TICKETS_NEGATIVE" +bedwars.2927="Bring me %%tokens%% Tokens of Ferocity, proof of your ability to fight." +bedwars.2928="Your Mystic Mirror has expired!" +bedwars.2929="You must pay %%tickets%% Tickets to unlock this room." +bedwars.2930="I must take my %%nap%% nap of the day." +bedwars.2931="The Receptionist has asked you not to do this for a while." +bedwars.2932="A rare stone from the moon, how it got to earth? Well that's a question for the astronaut. You can get one yourself by helping the Spaceman." +bedwars.2933="You cannot break your own %%item%%!" +bedwars.2934="Strawberry Milkshake" +bedwars.2935="SUCCESS! You brought back a %%item%%!" +bedwars.2936="Highest tier has been reached!" +bedwars.2937="Click to add to showcase!" +bedwars.2938="You cannot return items to another team's Shopkeeper!" +bedwars.2939="You need more Slumber Tickets to do this! They can be earned by playing Bed Wars games." +bedwars.2940="Slumber Milestones" +bedwars.2941="The key to a delicious Soul Burger is to perfectly cook the soul with the right mix of %%item%%, and, well, souls." +bedwars.2942="You cannot afford this display!" +bedwars.2943="Sneak to dismount - Time remaining: %%time%%s" +bedwars.2944="Unlocked through the Slumber Hotel!" +bedwars.2945="%%type%% - %%amount%% Slumber Ticket%%plural%%" +bedwars.2946="Continue Submission" +bedwars.2947="You used your %%name%%!" +bedwars.2948="SUCCESS! You collected a pair of %%item%%!" +bedwars.2949="Maybe you can convince Don Espresso to give up his if you help him." +bedwars.2950="%%name%% is Sleeping!" +bedwars.2951="Proof of Success" +bedwars.2952="I need %%amount%% %%item%%." +bedwars.2953="Collect a %%item%% from any Bed Wars game, they spawn randomly on the map 5 minutes into the game." +bedwars.2954="Here, take this - an explorer wouldn't dare be caught without some %%item%%!" +bedwars.2955="Please wait %%cooldown%% second%%s%% to use that again." +bedwars.2956="I can throw %%pillows%% Pillows in a load, just bring them to me." +bedwars.2957="Obtain a new Bed Sheet for Lady Saichi. A Bed Sheet can be obtained by breaking enemy team beds." +bedwars.2958="Help the hotel Blacksmith obtain 500 Iron Nuggets. Iron Nuggets have a chance to be obtained when picking up iron ingots." +bedwars.2959="Collect %%quartersAfter%% %%item%%. %%item%%s have a chance to be obtained when picking up iron ingots." +bedwars.2960="You cannot do this again right now!" +bedwars.2961="Sort the default layout" +bedwars.2962="+1 %%item%% collected! (%%current%%)" +bedwars.2963=" (Repeatable)" +bedwars.2964="Raspberry Milkshake" +bedwars.2965="Collect %%amount%% Iron Nuggets" +bedwars.2966="Shots: " +bedwars.2967="Collect %%amount%% Silver Coins. Maybe purchasing items from the shopkeeper in game can help?" +bedwars.2968="I think I've had %%number%% milkshakes so far today, is that a lot?" +bedwars.2969="Collect %%count%%x %%item%%s for Jeremy. Diamond Fragments have a chance to be obtained when picking up diamonds." +bedwars.2970="Obtain %%amount%% Wool Cables" +bedwars.2971="Click the Correct Answer!" +bedwars.2972="Get me a new %%item%%!" +bedwars.2973="You are now carrying x%%amount%% %%name%%, bring it back to your shop keeper!" +bedwars.2974="Bullseye: " +bedwars.2975="Blitz Star" +bedwars.2976="You can't use this while in combat! Try again in %%seconds%% seconds." +bedwars.2977="View the items required to upgrade this minion to the next tier." +bedwars.2978="Turns you invisible for %%time%%s." +bedwars.2979="Click to Trade!" +bedwars.2980="Opens the menu to select the murderer." +bedwars.2981="Faded Blitz Star" +bedwars.2982="[Select Murderer]" +bedwars.2983="Ender Dust" +bedwars.2984="Tokens of Ferocity are given by killing or assisting in killing a player." +bedwars.2985="Defeat a Player using the Silver Blade" +bedwars.2986="Find King Flut's Missing Comfy Pillows" +bedwars.2987="%%item%%..." +bedwars.2988="COMPLETED" +bedwars.2989="The Great Cave Adventure" +bedwars.2990="Speak to the Hotel Receptionist" +bedwars.2991="Unable to Trade!" +bedwars.2992="QUEST COMPLETE" +bedwars.2993="You disarmed this %%name%%!" +bedwars.2994="You will teleport to your base with your team!" +bedwars.2995="Please report this on the forums." +bedwars.2996="Timeworn Mystery Boxes, straight from 2015, have a chance to be obtained by completing any Bed Wars matches" +bedwars.2997="You would drive it around, but blocks don't make for very good wheels." +bedwars.2998="Block of Mega Walls Obsidian" +bedwars.2999="Obtain %%amount%% %%item%% for Electrician Russel. Gold Bars are obtained by finishing a match with unspent gold ingots in your inventory." +bedwars.3000="Talk to Twitchy Joe" +bedwars.3001="Slumber Inventory (Right Click)" +bedwars.3002="Ender Dust" +bedwars.3003="Limbo Dust" +bedwars.3004="You do not understand anything Gizzy is saying, but you go along with it." +bedwars.3005="Deciphering the Map" +bedwars.3006="Quest Log" +bedwars.3007="Slumber Hotel Exit" +bedwars.3008="Click to Enter!" +bedwars.3009="Thank you so much!" +bedwars.3010="Invalid UUID. Usage: /viewquickbuy <uuid>" +bedwars.3011="Not enough tickets!" +bedwars.3012="Ender Dust Minion X" +bedwars.3013="There's nothing in your minion to collect!" +bedwars.3014="After being hit a ghost will haunt you." +bedwars.3015="Collect %%amount%% Ender Dust" +bedwars.3016="Dreamer's Soul Fragment" +bedwars.3017="This multiplier applies to all players across Bed Wars, and increases the amount of Slumber Tickets earned in game." +bedwars.3018="Click to Pick Up!" +bedwars.3019="Collect %%amount%% %%item%% by killing or assisting in killing any players." +bedwars.3020="OBJECTIVE COMPLETE" +bedwars.3021="If you can get me %%amount%% Nether Stars, I can probably use their power to remember this dream." +bedwars.3022="Tier %%tier%% is a Rotating Item!" +bedwars.3023="The owner has taken notice of you, please speak with Hotel Reception." +bedwars.3024="Progress: %%current%%/%%required%%" +bedwars.3025="Amulet belonging to King Flut, the great pharaoh of... somewhere. It was forgotten after spending time at the Oasis, and should be brought back to him." +bedwars.3026="SUCCESS! You collected a used pair of %%item%%!" +bedwars.3027="Please wait another %%seconds%% seconds before your team uses this item again." +bedwars.3028="You have awoken and can now move again!" +bedwars.3029="Collect %%count%% Ender Dust for Chef Bucky. Ender Dust is obtained by using ender pearls." +bedwars.3030="Click to open!" +bedwars.3031="Add a Budget Hopper or Enchanted Hopper here to make your minion automatically sell generated items after its inventory is full." +bedwars.3032="Enter Portal to Exit" +bedwars.3033="Nether Star" +bedwars.3034="Teleporting to your base in %%delay%% second%%s%%. CLICK TO JOIN!" +bedwars.3035="Not unlocked!" +bedwars.3036="Speak to %%name%% to continue this quest." +bedwars.3037="Wow, you have %%tickets%% Slumber Tickets, you should buy some milkshakes!" +bedwars.3038="Throw at a player to put them to sleep! They will continue to sleep for up to %%duration%% seconds, or until woken up." +bedwars.3039="Collect %%count%% %%item%% for the SkyBlock Player. Ender Dust is obtained by using ender pearls." +bedwars.3040="Wallet Full Warning" +bedwars.3041="Slumber Tickets: %%tickets%%/%%limit%%" +bedwars.3042="You were the %%rank%% player to meet the Sandman!" +bedwars.3043="The Hotel Receptionist beckons to you. Perhaps you should talk to them?" +bedwars.3044="Figurines can also be unlocked in the Ticket Machine." +bedwars.3045="Angel of Death's Sword (One-time hit)" +bedwars.3046="Murder Clue #2" +bedwars.3047="Rarity: %%rarity%%" +bedwars.3048="Talk to the NPC who gave you this quest to complete it." +bedwars.3049="Murder Clue #1" +bedwars.3050="Murder Clue #4" +bedwars.3051="Murder Clue #3" +bedwars.3052="Collect %%amount%% %%item%% by winning any round of Bed Wars." +bedwars.3053="Place to spawn a wither." +bedwars.3054="Wither Gives Resistance 1, Speed 2 & Regeneration 2" +bedwars.3055="Click to cancel" +bedwars.3056="Teleporting to your base in %%delay%% seconds." +bedwars.3057="%%upgrade%% is a Rotating Item!" +bedwars.3058="Murder Clue #5" +bedwars.3059="Not enough room in showcase!" +bedwars.3060="+%%tickets%% Slumber Tickets!" +bedwars.3061="PHASE ASCENSION" +bedwars.3062="• Slumber Tickets - %%chance%%% Chance" +bedwars.3063="Ender Dust Collected: %%amount%%" +bedwars.3064="Sorry, this quest is temporarily disabled!" +bedwars.3065="Players hit will be given Slowness I for 3 seconds." +bedwars.3066="What?" +bedwars.3067="Right Click a block to use this item!" +bedwars.3068="QUEST COMPLETE" +bedwars.3069="FINAL REVIVE BEACON > %%color%%%%team%% has been revived!" +bedwars.3070="You traded %%emeralds%% Emeralds for %%tickets%% Slumber Tickets!" +bedwars.3071="+%%amount%% %%itemClean%%!" +bedwars.3072="Souls... %%amount%% %%item%%s should suffice. Knock them all into the void." +bedwars.3073="I'm leaving. Here %%player%%, take my Tickets and my suit, I'm done." +bedwars.3074="Prevents damage from players for 10 seconds, up to 3 hits. Disabled after Sudden Death." +bedwars.3075="You cannot open the shop while sleeping!" +bedwars.3076="Help the Blacksmith obtain a shiny Amulet. A certain adventurer may be able to help." +bedwars.3077="Slumber Tickets" +bedwars.3078="Old Treasure Map" +bedwars.3079="Obtain Slumber Tickets" +bedwars.3080="and %%stars%% %%item%%s for the engine! It needs all the power it can get." +bedwars.3081="SUCCESS! You collected a %%item%%!" +bedwars.3082="Say, can you grab the %%item%% next time you destroy some beds?" +bedwars.3083="Unlock the Owner's Office and introduce yourself to the Sandman." +bedwars.3084="+%%amount%%% %%purchaser%%'s Network Booster" +bedwars.3085="Talk to the Hotel Receptionist" +bedwars.3086="Speak to the Hotel Receptionist at the front desk." +bedwars.3087="Bed Sheet" +bedwars.3088="You cannot use that here!" +bedwars.3089="Here, have some of my %%item%%." +bedwars.3090="Diamond Fragment" +bedwars.3091="Sorry, this quest has been temporarily disabled!" +bedwars.3092="Collect %%amount%% Spare Cables" +bedwars.3093="To enter the Slumber Hotel, you need to give me %%required%% Slumber Tickets." +bedwars.3094="I am dead." +bedwars.3095="Oh there he goes!" +bedwars.3096="Feather Falling %%tier%%" +bedwars.3097="Find %%amount%% Gold Bars for Jeremy" +bedwars.3098="A-Z" +bedwars.3099="Complete quests to bring back life to the Slumber Hotel, increasing the amount of colorful characters staying the night." +bedwars.3100="Hey %%player%%, the Slumber Hotel is now accepting reservations!" +bedwars.3101="+0 Slumber Tickets! (Full) [Toggle Warning]" +bedwars.3102="Collect %%amount%% Iron Nuggets for the Apprentice Blacksmith. Iron Nuggets have a chance to be obtained when picking up iron ingots." +bedwars.3103="If you bring me %%wool%% Wool Cables, I can sew them into one Wool Block." +bedwars.3104="Don't tamper with evidence!" +bedwars.3105="There are 4 indentations on this door. Perhaps you could find these items by helping people around the hotel?" +bedwars.3106="Pay %%amount%% Tickets?" +bedwars.3107="Help Inspector Maya find the third clue to the murder." +bedwars.3108="Spare Wool Cable" +bedwars.3109="Win the Quiz Show" +bedwars.3110="About %%coins%% %%item%%s should do." +bedwars.3111="Always face towards the platform when you start." +bedwars.3112="Spark Plug" +bedwars.3113="This item is available in the Team Upgrades menu." +bedwars.3114="Characters met at the Hotel come from various points in all sorts of universes and timelines. They are not actually at the Hotel - they are dreaming!" +bedwars.3115="You currently have %%emeralds%% emeralds. You need %%needed%% Emeralds to trade for Slumber Tickets!" +bedwars.3116="Obtain a Golden Ticket" +bedwars.3117="Jets McTurbo may give you a spare Kart Wheel if you help him." +bedwars.3118="Accept bet" +bedwars.3119="OBJECTIVES COMPLETE" +bedwars.3120="To enter the Slumber Hotel, you must give the Doorman %%required%% Slumber Tickets." +bedwars.3121="Slumber Rank: #%%rank%%" +bedwars.3122="Banana pudding ice cream, peanut butter, chocolate, and a whole banana blended to perfection." +bedwars.3123="Comfy Pillow" +bedwars.3124="Save %%amount%% %%item%%s for Jets McTurbo. Emerald Shards have a chance to be obtained when picking up emeralds." +bedwars.3125="This is the car you won in the Hotel during that one quiz!" +bedwars.3126="Collected %%amount%% Slumber Tickets from your minion!" +bedwars.3127="Confirm Trade" +bedwars.3128="Decline bet" +bedwars.3129="Amulet of King Flut" +bedwars.3130="Your team can only purchase this trap %%number%% times!" +bedwars.3131="There they are! Hold on." +bedwars.3132="Help Inspector Maya find the second clue to the murder." +bedwars.3133="Total items: %%amount%%" +bedwars.3134="Bring me %%tickets%% Tickets for materials, 20 pieces of Wool Cables, and 50 Tokens of Ferocity to melt into checkers pieces, and I should be able to fix this." +bedwars.3135="You do not have enough space in your wallet to trade right now!" +bedwars.3136="Slumber Tickets can be obtained by doing the following:" +bedwars.3137="Your damage was blocked by %%name%%'s Mystic Mirror ability!" +bedwars.3138="color" +bedwars.3139="Silver Coin" +bedwars.3140="Find King Flut's missing Amulet. Maybe it's somewhere in the hotel?" +bedwars.3141="Note: You can't take fuel back out after you place it here!" +bedwars.3142="Open this door for %%tickets%% Slumber Tickets?" +bedwars.3143="Click to select %%name%% as the murderer." +bedwars.3144="You picked up: " +bedwars.3145="Welcome!" +bedwars.3146="Your team can only purchase this trap 1 time!" +bedwars.3147="[Click to view Slumber Items]" +bedwars.3148="Unlock Door" +bedwars.3149="Requirements:" +bedwars.3150="That'll do. Stand back!" +bedwars.3151="Successful! %%distance%% blocks!" +bedwars.3152="Banana Milkshake" +bedwars.3153="Can you bring me %%amount%% to give it a test?" +bedwars.3154="I need %%pillowsCount%% %%itemOne%%, %%sheetsCount%% sets of %%itemTwo%%, %%barsCounts%% %%itemThree%%, %%cablesCount%% sets of %%itemFour%% and a car %%itemFive%%." +bedwars.3155="Used Gloves" +bedwars.3156="Obtain %%amount%% Comfy Pillows. Found in enemy resource spawners." +bedwars.3157="Your %%name%% has been activated." +bedwars.3158="Unlocking doors will give you access to more rooms throughout the Hotel, which will allow you to meet more guests who will have quests for you to complete." +bedwars.3159="Pickup Minion" +bedwars.3160="Collect %%amount%% Iron Nuggets for the Apprentice Blacksmith" +bedwars.3161="Collect %%count%%x %%item%%s for Jeremy. Iron Nuggets have a chance to be obtained when picking up iron ingots." +bedwars.3162="Bring John Indigos a new Hammer for his expedition." +bedwars.3163="Quick-Upgrade Minion" +bedwars.3164="What? No! I'm not suspicious! %%playerName%% is suspicious!" +bedwars.3165="Talking to the Sandman is currently disabled, please try again at another time!" +bedwars.3166="You still do not understand anything Gizzy is saying, what a weird fellow." +bedwars.3167="Bring Something to Blow Up the Temple Door" +bedwars.3168="Used Murder Weapon" +bedwars.3169="Find something that can be used to help John Indigos breathe poisonous air. Maybe some sort of mask?" +bedwars.3170="FINAL REVIVE BEACON > %%color%%%%team%% used a %%item%%! Destroy the Beacon within %%seconds%% seconds to cancel the revive!" +bedwars.3171="Also, I have grown tired of this %%item%% already. Why don't you keep it?" +bedwars.3172="Your team has already used a %%name%%!" +bedwars.3173="You've done it, you brought me %%coins%% %%item%%s." +bedwars.3174="%%tickets%% Slumber Tickets" +bedwars.3175="%%tickets%% Slumber Tickets" +bedwars.3176="Help Chef Bucky obtain %%amount%% Dreamer's Soul Fragments. Try throwing players into the void." +bedwars.3177="Click to Wake Them Up!" +bedwars.3178="And so Gizzy played Guitar." +bedwars.3179="Next Tier" +bedwars.3180="Collect %%count%% Ender Dust for General Daku. Ender Dust is obtained by using ender pearls." +bedwars.3181="Bring %%count%%x %%item%% to Jeremy. Emerald Shards have a chance to be obtained when picking up emeralds." +bedwars.3182="Obtain %%amount%% %%item%%. Diamond Fragments have a chance to be obtained when picking up diamonds." +bedwars.3183="Get me %%iron%% %%itemOne%%s and %%coins%% %%itemTwo%%s." +bedwars.3184="%%count%%, so far." +bedwars.3185="Don't leave me to hang like some cat from some far away country." +bedwars.3186="Thank you for the %%required%% Slumber Tickets." +bedwars.3187="Click to view your Slumber Hotel progress & quest log" +bedwars.3188="Sorted By: %%type%%" +bedwars.3189="Can you get me %%stars%% %%itemOne%% and %%sheets%% %%itemTwo%%?" +bedwars.3190="Since you already had it, you received 500 coins." +bedwars.3191="Expensive Perfume" +bedwars.3192="Obtain %%amount%% %%item%% for The Ratman. Found in enemy resource spawners." +bedwars.3193="About as good as a wooden sword, really. Even looks like a wooden sword. It's pretty much blunt. Bad craftmanship if you ask me" +bedwars.3194="You cannot carry any more Comfy Pillows!" +bedwars.3195="Can you find the buried treasure? Break blocks around some maps to try and find some!" +bedwars.3196="Click to give %%amount%% Slumber Tickets" +bedwars.3197="Discarded Kart Wheel" +bedwars.3198="PHASE ASCENSION" +bedwars.3199="Obtain a new Bed Sheet for Lady Saichi" +bedwars.3200="Collect %%amount%% %%item%% by destroying beds." +bedwars.3201="Trusty Rope" +bedwars.3202="You cannot carry anymore!" +bedwars.3203="You must reach Phase %%phase%% by completing more quests." +bedwars.3204="Distressed Blue Team Wither" +bedwars.3205="You do not have enough Slumber Tickets to do this!" +bedwars.3206="Sorry, The Concierge has temporarily disabled entering the Slumber Hotel." +bedwars.3207="Obtain %%amount%% Tokens of Ferocity by killing or assisting in killing any players." +bedwars.3208="You purchased %%item%% (+1 Silver Coin [%%total%%])" +bedwars.3209="Click to Enable!" +bedwars.3210="Help the Blacksmith obtain a Hammer Mold. Speak to someone who knows a thing or two about HAMMERs." +bedwars.3211="bed" +bedwars.3212="Remember to stay hydrated and drink lots of water throughout the day." +bedwars.3213="Unused Bomb Materials" +bedwars.3214="Can be found in %%found%%" +bedwars.3215="You can't use this while in combat! Try again in %%seconds%% second." +bedwars.3216="%%current%%/%%required%% Slumber Tickets" +bedwars.3217="Please wait another %%seconds%% second before your team uses this item again." +bedwars.3218="Max Ender Dust Storage: %%amount%%" +bedwars.3219="INCOMPLETE OBJECTIVES:" +bedwars.3220="Invisible is removed after breaking 5 blocks." +bedwars.3221="Help the Laundry Guy" +bedwars.3222="Use the Silver Blade in a Bed Wars match to defeat a player." +bedwars.3223="LOCKED" +bedwars.3224="Collect %%amount%% %%item%% for The Ratman. Iron Nuggets have a chance to be obtained when picking up iron ingots." +bedwars.3225="The Slumber Ticket Machine presents you with some great rewards, including Slumber Tickets, cosmetics, Bed Wars experience, and more!" +bedwars.3226="Obtain a shiny Amulet" +bedwars.3227="This mold is centuries old and has forged some of the greatest weapons that warriors have ever wielded. A guy named Hammer should have one of these." +bedwars.3228="You must opt in to be teleported to your base." +bedwars.3229="Bring me %%diamonds%% Diamond Fragments, and I'll give you something back." +bedwars.3230="Water" +bedwars.3231="Hold-on, you are telling me you still do not have %%amount%% %%item%%?" +bedwars.3232="SUCCESS! You brought back a %%item%% for Bill Starr!" +bedwars.3233="Save %%amount%% %%item%%s for Jets McTurbo. Iron Nuggets have a chance to be obtained when picking up iron ingots." +bedwars.3234="Obtain %%amount%% Tokens of Ferocity" +bedwars.3235="Perfume fit for royalty. Lady Saichi believes she's royalty." +bedwars.3236="teamColor" +bedwars.3237="XP Multiplier:" +bedwars.3238="%%name%% are you ready?" +bedwars.3239="Every time you bring me %%sheets%% of them, I'll give you a reward." +bedwars.3240="Your %%name%% ability has worn off!" +bedwars.3241="Click here to upgrade your minion to the next tier." +bedwars.3242="Could not find that player!" +bedwars.3243="General Daku's Ender Dust" +bedwars.3244="Looks to be a very comfortable pillow from a bed. Team resource generators drop pillows once a game." +bedwars.3245="SkyBlock Collection" +bedwars.3246="Quests & Objectives" +bedwars.3247="Straight from down under. Also obtained by winning Bed Wars games." +bedwars.3248="Pay %%amount%% Slumber Tickets" +bedwars.3249="Costs: 75 Slumber Tickets" +bedwars.3250="I need %%amount%%! Just get %%barName%% in Bed Wars, that’ll net you some nuggets!" +bedwars.3251="Every Ender Pearl leaves a trail of dust" +bedwars.3252="Click to change the sorting type" +bedwars.3253="Sharpness %%tier%%" +bedwars.3254="Lump of Dwarven Mithril" +bedwars.3255="INCOMPLETE OBJECTIVES" +bedwars.3256="Help Inspector Maya find the first clue to the murder." +bedwars.3257="Play Bed Wars to increase your minion's resources." +bedwars.3258="You have been put into a deep sleep and cannot move!" +bedwars.3259="Click to opt in to %%name%%" +bedwars.3260="If you own a car you could take a spark plug from it." +bedwars.3261="Collect %%amount%% Silver Coins for the Apprentice Blacksmith" +bedwars.3262="You can disable Challenges through any NPC in the Bed Wars lobby using the redstone on the Challenges page." +bedwars.3263="Click Door to Exit" +bedwars.3264="%%amount%% %%item%%s..." +bedwars.3265="Cancel Submission" +bedwars.3266="Sneak Click to add to Quick Buy" +bedwars.3267="You selected %%name%%!" +bedwars.3268="A classic raspberry flavored milkshake topped with a generous scoop of vanilla ice cream." +bedwars.3269="Pay %%amount%% Tickets?" +bedwars.3270="Don Espresso is currently stuffing his face with all sorts of minerals. That's why he's not yelling at this time, thankfully." +bedwars.3271="Explore the Slumber Hotel to unlock all sorts of quests to help you obtain more Tickets." +bedwars.3272="You cannot talk to the Sandman yet! Please continue helping guests throughout the hotel." +bedwars.3273="Timeworn Mystery Box" +bedwars.3274="You have no more arrows in your inventory!" +bedwars.3275="%%color%%%%player%% used a %%name%%!" +bedwars.3276="End of messages" +bedwars.3277="Obtain %%item%% by teleporting around with Ender Pearls in Bed Wars Matches. Get one mg of Ender Dust of each block travelled." +bedwars.3278="%%rarity%% Figurine Display" +bedwars.3279="Sorry, this objective has been temporarily disabled!" +bedwars.3280="Couldn't find your game!" +bedwars.3281="Help Laundry Guy get some %%item%%." +bedwars.3282="Get me %%amount%% %%itemOne%%s and my %%itemTwo%%, and I'll reward you handsomely." +bedwars.3283="FINAL REVIVE BEACON > Your team has been revived!" +bedwars.3284="Play the Ticket Machine!" +bedwars.3285="FINAL REVIVE BEACON > Your Beacon was destroyed by %%color%%%%name%%!" +bedwars.3286="Your collection of %%rarity%% Figurines." +bedwars.3287="Progress: %%current%%/%%required%%" +bedwars.3288="Bed Wars Experience" +bedwars.3289="IN PROGRESS" +bedwars.3290="Unused bomb materials, what a shame these didn't get put to use." +bedwars.3291="Gold Bar" +bedwars.3292="Requires Permanent Shears" +bedwars.3293="There is already a firework show in progress!" +bedwars.3294="I'll reward you if you can bring me %%sheets%%." +bedwars.3295="Click to Enter" +bedwars.3296="Max Tickets Storage: %%amount%%" +bedwars.3297="Collect All" +bedwars.3298="It's time for me to wake up, and I know just the way." +bedwars.3299="Click to view Team Upgrades!" +bedwars.3300="You can't put that player to sleep over the void!" +bedwars.3301="Collect %%amount%% %%item%%s for Jimmy. Wool Cables can be collected by breaking any enemy wool blocks." +bedwars.3302="You are the %%rank%% person to reach this room." +bedwars.3303="And that's %%sheets%% sets of sheets." +bedwars.3304="Find Bill Starr a Blitz Star" +bedwars.3305="Help Oasis Spirit obtain %%amount%% Dreamer's Soul Fragments. Try throwing players into the void." +bedwars.3306="Toggle whether to send a message in-game when trying to earn Slumber Tickets with a full wallet." +bedwars.3307="Collect %%amount%% %%item%%s by breaking any enemy wool blocks." +bedwars.3308="This player is no longer online! Please try again." +bedwars.3309="With %%bars%% Gold Bars, I should be able to make some repairs here." +bedwars.3310="A proximity mine that puts everybody within range to sleep for %%duration%% seconds, or until woken up." +bedwars.3311="You are one of the first %%unique%% to meet me." +bedwars.3312="Error claiming gifts: Non BedGame!" +bedwars.3313="Slumber Items" +bedwars.3314="Collect %%amount%% Comfy Pillows" +bedwars.3315="A refreshing mix of sweet apples, cinnamon, and oat milk." +bedwars.3316="bring me %%stars%% Nether Stars as proof that you're a winner" +bedwars.3317="You currently own %%emeralds%% Emeralds." +bedwars.3318="Meet the Sandman" +bedwars.3319="You cannot enter the Slumber Hotel yet! Please speak to the Doorman." +bedwars.3320="You already have an active Vampire Blood effect." +bedwars.3321="Obtained %%amount%% Experience" +bedwars.3322="Amulet belonging to King Flut, the great pharaoh of... somewhere. He gave it to you after helping him fluff up his throne." +bedwars.3323="Your Frost Bite Arrows hit %%victim%%!" +bedwars.3324="Emeralds" +bedwars.3325="[NPC] %%name%%: " +bedwars.3326="Cleaned up Murder Knife" +bedwars.3327="Obtain %%amount%% Comfy Pillows" +bedwars.3328="Bring the CEO %%amount%% %%item%%, obtained by winning Bed Wars games." +bedwars.3329="The Slumber Hotel exists within a unique Dimension between the waking world and the dream world." +bedwars.3330="Win the Bet" +bedwars.3331="Introduce yourself to the Slumber Hotel Receptionist. They may have a new gift for you." +bedwars.3332="Collect %%amount%% Nether Stars" +bedwars.3333="+1 Oasis Boon collected! (Slumber Ticket Multiplier)" +bedwars.3334="Teleporting to your base in %%delay%% second." +bedwars.3335="Oasis Boon" +bedwars.3336="QUEST" +bedwars.3337="Proof that you have successfully won a match of Bed Wars." +bedwars.3338="Ratman Mask" +bedwars.3339="Help the Blacksmith obtain a bottle of Oasis Water. Speak to someone who knows a thing or two about Oasis Water." +bedwars.3340="You purchased %%name%%!" +bedwars.3341="Imperial Leather" +bedwars.3342="UNLOCKED!" +bedwars.3343="Click to pickup!" +bedwars.3344="You earned %%amount%% Slumber Tickets" +bedwars.3345="Can't decide what to order? Try a Mysterious Milkshake and let us make the decision for you!" +bedwars.3346="Your Mystic Mirror has smashed!" +bedwars.3347="Slumber Tickets can be obtained by: " +bedwars.3348="Next sorting type: %%type%%" +bedwars.3349="Obtain %%amount%% %%item%% for the Laundry Gal. Found in enemy resource spawners." +bedwars.3350="Your team permanently gains Feather Falling on your boots!" +bedwars.3351="Enabled Slumber Hotel music." +bedwars.3352="If %%name%% answers the questions correctly, the car is theirs! Forever!" +bedwars.3353="Help John Indigos" +bedwars.3354="Bring John Something that'll Help Breathe Poisonous Air" +bedwars.3355="Collect %%amount%% Nether Stars by winning any round of Bed Wars." +bedwars.3356="Disabled Slumber Hotel music." +bedwars.3357="Your team has already used a %%item%%, and you cannot purchase another!" +bedwars.3358="Accuracy: " +bedwars.3359="[View Clues]" +bedwars.3360="Find something that can be used to replace the figurine." +bedwars.3361="Collect %%item%%s for the Arcade Player. Iron Nuggets have a chance to be obtained when picking up iron ingots." +bedwars.3362="%%name%% %%category%%" +bedwars.3363="You approached the door with the correct items!" +bedwars.3364="You do not have enough tickets to open this door." +bedwars.3365="A %%item%%... for payment - I really want the exclusive member's breakfast buffet!" +bedwars.3366="You currently own %%emeralds%% Emerald." +bedwars.3367="Obtained from killing a player using a Silver Blade." +bedwars.3368="You unlocked: %%name%%" +bedwars.3369="You must pay the required amount of Slumber Tickets to unlock doors in the Slumber Hotel." +bedwars.3370="Dirty Boots" +bedwars.3371="You unlocked: Sandman Figurine!" +bedwars.3372="Hammer's Silver Coins" +bedwars.3373="I could use %%amount%%, if you can." +bedwars.3374="Let me get back to that now." +bedwars.3375="Bring me %%coins%% %%item%%s, I need to go hunt!" +bedwars.3376="Having this minion will start generating and harvesting Ender Dust! Every match adds %%leaves%% dust to the minion's inventory, up to a maximum of 2 stacks of 64. Every 2 matches adds 1 Slumber Ticket to the minion's inventory, up to a maximum of 64." +bedwars.3377="This Oasis Boon, granted to you by the Oasis Spirit, permanently increases your Slumber Ticket gain by 50%." +bedwars.3378="Fuel" +bedwars.3379="Iron" +bedwars.3380="Gold" +bedwars.3381="Diamond" +bedwars.3382="Emerald" +bedwars.3383="Sapphire" +bedwars.3384="Ruby" +bedwars.3385="Crystal" +bedwars.3386="Opal" +bedwars.3387="Amethyst" +bedwars.3388="Rainbow" +bedwars.3389="Iron Prime" +bedwars.3390="Gold Prime" +bedwars.3391="Diamond Prime" +bedwars.3392="Emerald Prime" +bedwars.3393="Sapphire Prime" +bedwars.3394="Ruby Prime" +bedwars.3395="Crystal Prime" +bedwars.3396="Opal Prime" +bedwars.3397="Amethyst Prime" +bedwars.3398="Mirror" +bedwars.3399="Light" +bedwars.3400="Dawn" +bedwars.3401="Dusk" +bedwars.3402="Air" +bedwars.3403="Wind" +bedwars.3404="Nebula" +bedwars.3405="Earth" +bedwars.3406="Water" +bedwars.3407="Fire" +bedwars.3408="Sunrise" +bedwars.3409="Eclipse" +bedwars.3410="Gamma" +bedwars.3411="Majestic" +bedwars.3412="Andesine" +bedwars.3413="Marine" +bedwars.3414="Element" +bedwars.3415="Galaxy" +bedwars.3416="Atomic" +bedwars.3417="Sunset" +bedwars.3418="Time" +bedwars.3419="Winter" +bedwars.3420="Obsidian" +bedwars.3421="Spring" +bedwars.3422="Ice" +bedwars.3423="Summer" +bedwars.3424="Spinel" +bedwars.3425="Autumn" +bedwars.3426="Mystic" +bedwars.3427="Eternal" +bedwars.3428="Emeralds" +bedwars.3429="Diamonds" +bedwars.3430="Figurine Displays" +bedwars.3431="Isn't that nice? Look at that figurine display." +bedwars.3432="Just look at it." +bedwars.3433="If only I had any figurines... I really like them but I can never get enough tickets." +bedwars.3434="Hey, you have a figurine! How wonderful." +bedwars.3435="I can help you set them up here. Come talk to me whenever you want to manage the displays!" +bedwars.3436="Come back when you have a figurine to show me!" +bedwars.3437="Figurine Enthusiast" +bedwars.3438="You must not perform such violence within the hotel." +bedwars.3439="Punching your friends is forbidden here." +bedwars.3440="Only The Concierge is worthy of punching in the hotel." +bedwars.3441="Punching within this sacred hotel is forbidden." +bedwars.3442="No. Leave the punching for the games." +bedwars.3443="Well well well what do we have here? Someone who thinks they can punch their friends!" +bedwars.3444="The Concierge is not happy with that action." +bedwars.3445="Hey! Stop that." +bedwars.3446="Please respect all players in the hotel." +bedwars.3447="Okay, that's just mean." +bedwars.3448="Milkshake Mike" +bedwars.3449="Lover of Milkshakes" +bedwars.3450="Throne Door" +bedwars.3451="Hotel Door" +bedwars.3452="Desert Door" +bedwars.3453="Electronic Door" +bedwars.3454="Door from the Sky" +bedwars.3455="Door as seen on TV" +bedwars.3456="Skyscraper Door" +bedwars.3457="Arcade Door" +bedwars.3458="Intricate Door" +bedwars.3459="Space Door" +bedwars.3460="D o 0 r" +bedwars.3461="Garage Door" +bedwars.3462="Owner's Office" +bedwars.3463="You don't need to press it so many times I'm here!" +bedwars.3464="Hold your horses I'm coming!" +bedwars.3465="WHERE'S THE FIRE?!" +bedwars.3466="Oh, it's just you." +bedwars.3467="Can you stop?!?!" +bedwars.3468="I'm gonna remove that bell." +bedwars.3469="Haahaa guess bridging really isn't your strong suit?" +bedwars.3470="Don't worry, I'll help you up." +bedwars.3471="Murder Clues" +bedwars.3472="A bloody and well worn knife." +bedwars.3473="Could be the possible murder weapon." +bedwars.3474="An air freshener found near the body." +bedwars.3475="Could've been used to hide the smell." +bedwars.3476="A pair of used gloves with blood on them." +bedwars.3477="Who wore these? They're very used." +bedwars.3478="A pair of bloody work boots." +bedwars.3479="Someone really should've washed these." +bedwars.3480="A photo of the dead body." +bedwars.3481="Of course, the Doctor!" +bedwars.3482="That knife is a scalpel, hence why it doesn't poke so well." +bedwars.3483="The doctor clearly had motive, and money to exact his plot." +bedwars.3484="Ah yes, a disgruntled employee. Sibling of the victim." +bedwars.3485="It makes sense - Robert treated him rudely, per the killer's own admission." +bedwars.3486="He worked at the site, so he got the gear there." +bedwars.3487="I'll take him in, Good work!" +bedwars.3488="Obviously I figured it out too." +bedwars.3489="The evidence was planted in an attempt to frame Felix" +bedwars.3490="If you scare the masses into thinking even your family can hurt you" +bedwars.3491="everyone will start hiring bodyguards." +bedwars.3492="Unlock Door" +bedwars.3493="Slumber Cosmetics" +bedwars.3494="Slumber Quest Log" +bedwars.3495="Slumber Milkshakes" +bedwars.3496="Purchase a firework display" +bedwars.3497="Slumber Inventory" +bedwars.3498="Item Submission" +bedwars.3499="Give Slumber Tickets" +bedwars.3500="Slumber Locations" +bedwars.3501="Receptionist Menu" +bedwars.3502="Slumber Milestones" +bedwars.3503="Ender Dust Minion X" +bedwars.3504="View the most efficient spot for this minion to be placed in." +bedwars.3505="The Concierge" +bedwars.3506="Come talk to me at the entrance of the Hotel, behind the Shopkeeper." +bedwars.3507="You can now enter the Slumber Hotel whenever you like!" +bedwars.3508="Hello! I am the Doorman for.. Oh it's just you, you're free to walk right in!" +bedwars.3509="Need some help? Try talking to the Hotel Receptionist behind the counter inside the Hotel." +bedwars.3510="Did you know that Frederic Fernton has something different to say about every painting hung above them?" +bedwars.3511="The Hotel Pianist is willing to take music requests, at a small cost." +bedwars.3512="Some people struggle to sleep, but me? I'm so good at sleeping, I can do it with my eyes closed!" +bedwars.3513="I would love to be paid to sleep. It would be my dream job." +bedwars.3514="Scientists say working out first thing in the morning is good for your health." +bedwars.3515="So, I've started doing sit-ups every morning. I get up, hit snooze, and go back to sleep. Then repeat the cycle." +bedwars.3516="Did you know the animal that sleeps the most is the koala? They can sleep for 20-22 hours each day!" +bedwars.3517="On average, humans spend about a third of their life sleeping. Do something cool with the other two thirds!" +bedwars.3518="Most people take about 10-15 minutes to fall asleep at night." +bedwars.3519="You can start Quests by talking to NPCs you find inside the Hotel." +bedwars.3520="I read once that humans are the only mammal that deliberately puts off sleeping, weird." +bedwars.3521="What do you call a sleeping pizza? A pizzzzzzzzzzza!" +bedwars.3522="Doorman Dave" +bedwars.3523="I love fireworks!" +bedwars.3524="Want to see a firework display?" +bedwars.3525="I can make a firework display for you!" +bedwars.3526="For the right price I can make the skies pretty." +bedwars.3527="I love milkshakes!" +bedwars.3528="Have you tried the milkshakes here? They're amazing!" +bedwars.3529="BUUUURRRRRPPPPP" +bedwars.3530="What flavor milkshake is your favorite?" +bedwars.3531="I wish I had more Slumber Tickets to buy more milkshakes." +bedwars.3532="I could drink milkshakes all day long." +bedwars.3533="What time is it? I've been ordering milkshakes all day!" +bedwars.3534="Hi! Welcome to the Slumber Hotel!" +bedwars.3535="Wow, you are actually here! You are not dreaming!" +bedwars.3536="Wonderful!" +bedwars.3537="I am responsible for selling you unique items unlocked by talking to the Hotel Customers. Make sure you help everyone!" +bedwars.3538="A customer... no, you are actually here! You are not dreaming!" +bedwars.3539="Welcome to the Slumber Hotel!" +bedwars.3540="I am the Hotel Receptionist! I have no name otherwise." +bedwars.3541="You can ask me any questions you have about this place." +bedwars.3542="Very impressive, you are doing great!" +bedwars.3543="It's time for you to take things up a notch." +bedwars.3544="What's this you have?" +bedwars.3545="Imperial leather..." +bedwars.3546="A reinforcing tincture... or perfume?" +bedwars.3547="Rope of the Highest Quality..." +bedwars.3548="Yes, with this, I can upgrade your wallet." +bedwars.3549="With this wallet, you should be able to save up enough tickets to access some of the Hotel doors." +bedwars.3550="For now... why don't you take a nap." +bedwars.3551="You have done well helping the guests so far." +bedwars.3552="... It's time to go deeper." +bedwars.3553="You have done well helping the customers of this Hotel." +bedwars.3554="The owner has decided to reward you with this new wallet." +bedwars.3555="He will soon meet you." +bedwars.3556="In the meantime, please also take this Piece of Glowing Sandpaper." +bedwars.3557="I'm sure you can figure out a way to use it." +bedwars.3558="Isn't it marvellous?" +bedwars.3559="The Hotel is teeming with life." +bedwars.3560="All thanks to you, among others." +bedwars.3561="The owner has taken notice of your actions." +bedwars.3562="Will you meet him? You will need to fill up this wallet." +bedwars.3563="His door is quite expensive, you see." +bedwars.3564="I'm the hotel pianist, I play music for the guests." +bedwars.3565="I have a set-list, so no requests." +bedwars.3566="I hope you enjoy your stay here." +bedwars.3567="Hotel Pianist" +bedwars.3568="Firework Frank" +bedwars.3569="Hostess Katrina" +bedwars.3570="Hotel Receptionist" +bedwars.3571="Move along, citizen." +bedwars.3572="Safe Guard" +bedwars.3573="Woah there it looks like you're still drinking one!" +bedwars.3574="Wait a few minutes before drinking another one." +bedwars.3575="Don't want you getting a sugar rush!" +bedwars.3576="Milkshake Barman" +bedwars.3577="Where can I take you to today?" +bedwars.3578="Top o' te mornin te ya." +bedwars.3579="Where to?" +bedwars.3580="Tips are appreciated!" +bedwars.3581="Slumber Tour Guide" +bedwars.3582="Ticket Machine" +bedwars.3583="Welcome. I have been expecting you." +bedwars.3584="You have done well helping the many residents of my Hotel." +bedwars.3585="I am The Sandman." +bedwars.3586="I help people sleep at night, using magical sand." +bedwars.3587="I'm sure you've heard of me, if not, look it up." +bedwars.3588="You are the very first person I meet." +bedwars.3589="Congratulations. Your name shall forever be kept in my books." +bedwars.3590="For meeting with me, I shall offer you an important boon." +bedwars.3591="Once a certain amount of people reach this room, I will bestow boons to the entirety of the population." +bedwars.3592="This deserves an honorable mention." +bedwars.3593="Here, for your troubles." +bedwars.3594="The Sandman" +bedwars.3595="Curious about how many people I have met?" +bedwars.3596="Its very impressive." +bedwars.3597="I hope my powers are being put to good use." +bedwars.3598="Frederic Fernton" +bedwars.3599="I painted this one during a dark time in my life where I felt like I could not trust anyone, not even my own friends." +bedwars.3600="This one is called: The Frog." +bedwars.3601="Just a wonderful portrait of a distinguished gentleman." +bedwars.3602="I just felt like a mischievous young man." +bedwars.3603="I've never worried about life's big questions." +bedwars.3604=":o" +bedwars.3605="Familiar, isn't it?" +bedwars.3606="This one reflects my biggest fear." +bedwars.3607="The most nightmarish of creatures." +bedwars.3608="You may not like it, but this is what peak performance looks like." +bedwars.3609="Inspiration strikes at the oddest of times." +bedwars.3610="I guess I was just a bit sleepy for this one." +bedwars.3611="A familiar building in a dark landscape. Chilling!" +bedwars.3612="A victory should always be rewarded, no matter the size." +bedwars.3613="An empty bottle represents endless possibilities." +bedwars.3614="Oh, what's this? I don't remember drawing this one." +bedwars.3615="These fell on my head one morning after I told my previous employer I was quitting. They inspired me." +bedwars.3616="A nice warm summer on the beach. What else anyone could dream of?" +bedwars.3617="A bunny frolicking in the spring. How wonderful!" +bedwars.3618="Autumn is my favorite season. I really think I captured the spooky feeling of falling leaves." +bedwars.3619="There is nothing more cozy than a nice winter night." +bedwars.3620="A vision of splendor this one is. The most refined of gentlemen." +bedwars.3621="The glorious sun, if it could look at us." +bedwars.3622="The cliffside by the ocean. Majestic yet Dangerous." +bedwars.3623="The dark forest beckons only the most courageous of us all." +bedwars.3624="The snowy mountains only accepts the most hardy adventurers." +bedwars.3625="The heart - the most important aspect of one's soul." +bedwars.3626="Its a skull. I just think they're neat." +bedwars.3627="It is dangerous yet extremely exciting to witness an erupting volcano in person. Quite exhilarating indeed!" +bedwars.3628="A pyramid I visited once." +bedwars.3629="I painted a hazy encounter I had with an unidentified object in the sky. Was it a dream? I don't actually know." +bedwars.3630="Hello Adventurer." +bedwars.3631="I am General Daku of the Fifth Imperial Legion." +bedwars.3632="Or at least, I was a General. The war was 25 years ago." +bedwars.3633="Today, all I do is sit here in this lobby and sip sand tea." +bedwars.3634="It's not very good tea." +bedwars.3635="Can you get me a better ingredient for some better tea?" +bedwars.3636="You would not last very long under my command." +bedwars.3637="Go on then!" +bedwars.3638="Go get the dust! Teleport around like an Ender Man would himself." +bedwars.3639="Thank you my friend." +bedwars.3640="You have made this old man happy again." +bedwars.3641="They make good wallets out of those, but you may need to collect some other materials before upgrading yours." +bedwars.3642="I do not need anything else, thank you my friend. Carry on." +bedwars.3643="Yes, this will definitely get me recognition at the Museum!" +bedwars.3644="Oh, hey, isn't it %%player%%!" +bedwars.3645="I just stumbled upon this magnificent hotel... I think?" +bedwars.3646="All I remember is taking a nap..." +bedwars.3647="Anyway, I want to meet the owner, but no one is letting me." +bedwars.3648="Maybe if I was richer?" +bedwars.3649="Some really rare artifacts would definitely help fund this venture." +bedwars.3650="Where could we find riches..." +bedwars.3651="Maybe by digging some blocks on the floating islands?" +bedwars.3652="Wow, that map looks expensive!" +bedwars.3653="I'll begin the search immediately." +bedwars.3654="I'll let you know if I need your help." +bedwars.3655="Maybe you can use it to upgrade your wallet, but you may need some other materials first." +bedwars.3656="Come talk to me later, I might need your help again." +bedwars.3657="The beds in this hotel are an insult!" +bedwars.3658="I tried to speak to the manager, but the Receptionist has denied my many requests." +bedwars.3659="I shan't take this any longer." +bedwars.3660="What kind of Hotel Employee are yo" +bedwars.3661="Do I have to repeat myself?" +bedwars.3662="... you are not very good at this. Is this even your passion?" +bedwars.3663="Ah, yes, this bed sheet will do." +bedwars.3664="If you don't like the smell, maybe it can be used to upgrade your wallet, if you gather enough materials first." +bedwars.3665="I did not call you over for anything, please leave me be. I have had a terrible day." +bedwars.3666="You cheated! After everything we've been through together, you are cheating!" +bedwars.3667="How could you do this to your own roommate?" +bedwars.3668="I'm not cheating, how am I cheating?" +bedwars.3669="You moved a piece when I looked away! I'm done with you!" +bedwars.3670="What a sore loser." +bedwars.3671="I didn't think he would notice that I moved his king a bit tho..." +bedwars.3672="I'd like to fix this board so others can play again, can you help me?" +bedwars.3673="Then anyone can play!" +bedwars.3674="Ah, you brought me the stuff!" +bedwars.3675="That's what I'm talking about. Now let me fix this table." +bedwars.3676="There it is! All fixed! Now we can play checkers again!" +bedwars.3677="Numbers are down!" +bedwars.3678="Lumbers are done!" +bedwars.3679="Let's bring the numbers back up then shall we?" +bedwars.3680="Bring the numbers back up!" +bedwars.3681="Ring the Rafters Very Much!" +bedwars.3682="You there! Can you bring us some numbers?" +bedwars.3683="Bring us the numbers!" +bedwars.3684="Bribe the plumbers!" +bedwars.3685="10 of them should suffice!" +bedwars.3686="Brew the Dumpster propped up!" +bedwars.3687="Bring us 10 proof that you have succeeded in bringing the numbers back up!" +bedwars.3688="The numbers are back up!" +bedwars.3689="You know what, I was not going to say anything, but this is starting to" +bedwars.3690="I mean look at you guys, repeating the same words as the CEO is saying!" +bedwars.3691="Are you guys not seeing it?" +bedwars.3692="I don't think I can stay here and do this anymore." +bedwars.3693="Number 2, you didn't even come to my wedding last Tuesday!" +bedwars.3694="I know you were here the whole time, spouting number nonsense!" +bedwars.3695="This is not healthy, absolutely not healthy. I can't stand it anymore." +bedwars.3696="Help the war effort, wool you?" +bedwars.3697="I know what I said." +bedwars.3698="My name's Sally." +bedwars.3699="I'm a combat artist - I fight with art." +bedwars.3700="Blocks are my weapon." +bedwars.3701="I was a soldier in the Great Build Battle of 2043" +bedwars.3702="I heard the tension was pretty bad lately, and we might be going to war again." +bedwars.3703="I need to stock up on Wool. Can you help me out?" +bedwars.3704="Wool Cables would do, I can sew them up together into blocks." +bedwars.3705="I'll give you some tickets, if you can help." +bedwars.3706="That's enough cable for a block!" +bedwars.3707="That's great, but I can't create art with just one block." +bedwars.3708="Bring me more!" +bedwars.3709="Here's your payment, for now." +bedwars.3710="I'M HUNGRY, WHERE IS THE DINNER STAFF" +bedwars.3711="SOMEONE FEED ME" +bedwars.3712="IS THERE EVEN ANYONE AROUND HERE" +bedwars.3713="I'LL HAVE THE CHEF'S HEAD IF I DON'T GET SERVICE SOON" +bedwars.3714="YOU, DO YOU WORK HERE" +bedwars.3715="I AM HUNGRY, I REQUIRE SUSTENANCE" +bedwars.3716="FEED ME SOMETHING" +bedwars.3717="ARE YOU DEAF" +bedwars.3718="I SAID SOMETHING THAT GLITTERS" +bedwars.3719="I LIKE METALS" +bedwars.3720="GOLD IS INDEED A METAL" +bedwars.3721="I GOOGLED IT" +bedwars.3722="THAT I WHAT I WANTED" +bedwars.3723="HERE HAVE SOMETHING" +bedwars.3724="This place is a mess. Whoever did the cables here didn't know what they were doing." +bedwars.3725="The fuse is blown, who built the wiring for this place?" +bedwars.3726="Its a complete mess, and the cables are low quality." +bedwars.3727="Dream Electricity only flows through gold cables, who would use bronze for this?" +bedwars.3728="What a mess. Amateurish design." +bedwars.3729="Can you get me some Gold Bars so I can have the blacksmith around here make me golden cables?" +bedwars.3730="Bring them to me and I'll give you some tickets for saving me time." +bedwars.3731="I don't want to have to go back to the shop and get some more cables you know." +bedwars.3732="There we go, with those I can get some repairs done." +bedwars.3733="Thank you, here's some tickets." +bedwars.3734="Come back later, there's always more repairs needed around here." +bedwars.3735="Boy, can I play guitar." +bedwars.3736="I come from Jupiter." +bedwars.3737="Where I learned to play Guitar." +bedwars.3738="With the Ants from Jupiter." +bedwars.3739="I would like my god-given Guitar to be improved." +bedwars.3740="Diamond Fragment all over it. The dogs are after my diamonds, and they keep stealing them." +bedwars.3741="I have to sing and play Guitar." +bedwars.3742="There you are, Hammer!" +bedwars.3743="I heard you've been looking for me." +bedwars.3744="HEEAATWAAAAAAVVVEEEEEEEE" +bedwars.3745="Hey it's you." +bedwars.3746="I think I'm somewhat ready to fight Heatwave, the werewolf." +bedwars.3747="I've made a Silver Blade to fight him, but I don't know how to use blades." +bedwars.3748="I've used hammers all my life." +bedwars.3749="Can you save a Replay of you using the sword to defeat an enemy?" +bedwars.3750="You haven't defeated anything with the Silver Blade yet." +bedwars.3751="I need to watch footage of someone using it." +bedwars.3752="I don't know blades too well." +bedwars.3753="Ah, I got the footage from you a minute ago." +bedwars.3754="Let's watch it." +bedwars.3755="Wow you really gave him a good one." +bedwars.3756="I think I got it. Here's something for your efforts" +bedwars.3757="Right when I was about to land my final blow, Heatwave escaped." +bedwars.3758="Thanks again for your help anyway." +bedwars.3759="You see this big safe?" +bedwars.3760="I bet they hide all their tickets in there." +bedwars.3761="Probably coins too." +bedwars.3762="You want to get in? I want to get in." +bedwars.3763="Let's work together!" +bedwars.3764="I'm going to need quite a few materials to make a bomb and a distraction." +bedwars.3765="Trust me. It's going to be worth it... I hope." +bedwars.3766="I really wanna know what's in there!" +bedwars.3767="That's for our bomb and a distraction." +bedwars.3768="Alright stand back and watch the pro." +bedwars.3769="Look guard, emeralds!" +bedwars.3770="That's it, you've been acting suspicious for a while now." +bedwars.3771="You're coming with me." +bedwars.3772="I could have never caught this man if you hadn't talked to him before." +bedwars.3773="Here's a reward, citizen." +bedwars.3774="The heist of the century!" +bedwars.3775="Eeeeyyyyyy I'm the Laundry Gal." +bedwars.3776="... I used to have a name but I can't remember it now." +bedwars.3777="This place does weird things to the mind when you work in it." +bedwars.3778="I'm responsible for cleaning Pillows! Bring me your excess pillows." +bedwars.3779="I'll clean em good, I'm really good at it. At least the machine is." +bedwars.3780="I'll give you tickets when you do. I ain't got any use for them." +bedwars.3781="I'll put them right in. Thank you so much!" +bedwars.3782="You're making my job easy, really." +bedwars.3783="brooooooooooooooooo" +bedwars.3784="how long u been playing bed wars?" +bedwars.3785="dude, DUDE" +bedwars.3786="u gotta win to make it Where even are u on the leaderboard" +bedwars.3787="if u prove to me that ur winning ill give u tickets" +bedwars.3788="bruhhhh" +bedwars.3789="are u even winning" +bedwars.3790="only winners get tickets" +bedwars.3791="climb that leaderboard" +bedwars.3792="I think i saw u on the leaderboard" +bedwars.3793="nice" +bedwars.3794="hey take those tickets and keep at it" +bedwars.3795="maybe you'll be first someday idk just keep playing lol" +bedwars.3796="The Art of Combat is the most pure form of expression." +bedwars.3797="There are many ways to fight, between weapons and, well, pushing people around." +bedwars.3798="Go, my student. Fight, and bring me back proof of your mettle." +bedwars.3799="Through battle, one can reach Enlightenment." +bedwars.3800="You shall be rewarded." +bedwars.3801="You are one with the battlefield." +bedwars.3802="I can see that." +bedwars.3803="You have done well, and shall be rewarded for it." +bedwars.3804="You are looking kinda... sus." +bedwars.3805="Are you the murderer?" +bedwars.3806="No, you wouldn't be, or I would already be dead!" +bedwars.3807="I need clues as to who killed this innocent man." +bedwars.3808="Can you look for some around here? Or on the Floating Isles?" +bedwars.3809="Use this" +bedwars.3810="I think I might have a few suspects." +bedwars.3811="You gather the clues, and I'll gather the suspects." +bedwars.3812="These are the suspects we found near the murder area." +bedwars.3813="Talk to them and see if you can figure out who the murderer is." +bedwars.3814="Feel free to review the clues in your inventory." +bedwars.3815="The Murderer is now in custody, thank you for your help." +bedwars.3816="Inspector Mya Sterling" +bedwars.3817="Bill Starr" +bedwars.3818="The name's Bill Starr." +bedwars.3819="I've survived them all." +bedwars.3820="Pixelville, Thorin, Caelum, I've seen it all." +bedwars.3821="Somehow, the one thing that eludes me, is the Blitz Star." +bedwars.3822="Years of Blitz and I still don't have one. What are the odds?" +bedwars.3823="I'm thinking of quitting Blitz." +bedwars.3824="Years of Blitz and I still don't have a star." +bedwars.3825="Maybe I should have given up a long time ago?" +bedwars.3826="A Blitz Star?" +bedwars.3827="You found one!" +bedwars.3828="And you somehow took it out of the game and brought it here... what." +bedwars.3829="Are you giving it to me? That's awesome. Maybe I'll keep playing Blitz." +bedwars.3830="Seeing this star really makes me think I'll eventually get one." +bedwars.3831="This star is beautiful..." +bedwars.3832="Cheerful Chap" +bedwars.3833="I keep hearing about this mysterious owner, WHO IS HE?" +bedwars.3834="I wish I could meet him. Maybe we'd be good friends." +bedwars.3835="I don't tend to sleep very well at night, so I don't tend to stay here long." +bedwars.3836="I wish I could get more sleep." +bedwars.3837="If only I had a *blip*" +bedwars.3838="Fatigued Fella" +bedwars.3839="We absolutely did it, wow. I saw you running, that was pretty cool." +bedwars.3840="Me? I took the easy path, I'm surprised you didn't just follow me." +bedwars.3841="You went straight to the hard mode path. I knew you had it in you." +bedwars.3842="Now that should get the owner's attention!" +bedwars.3843="Thanks again for helping me. Feel free to check out the temple any time." +bedwars.3844="Looks like you're going to need a bigger wallet to enter this temple." +bedwars.3845="Oh hey, its you!" +bedwars.3846="How did you... no matter." +bedwars.3847="I need to open this door, but I need to blow it up. Can you help me?" +bedwars.3848="Bring me some explosives or something." +bedwars.3849="Go help the people at the Hotel - someone's bound to give you something you need." +bedwars.3850="You got this from Jeremy Jagger, didn't you?" +bedwars.3851="I can recognize his handiwork instantly. Its really bad." +bedwars.3852="... it looks like we made a small tunnel in the corner there." +bedwars.3853="Let's go in." +bedwars.3854="The air is poisoned here. We'll need some sort of mask to breathe through." +bedwars.3855="Isn't that Ratman's mask?" +bedwars.3856="That could help us breathe through this." +bedwars.3857="... are you a cosplayer? I read all of Ratman's comics when I was a young lad." +bedwars.3858="This one is super high quality - you could fool me if you told me it was the real thing." +bedwars.3859="Hold on, don't step on the bridge just yet." +bedwars.3860="Its cursed. It'll throw you off instantly." +bedwars.3861="We need something to render it inert." +bedwars.3862="We need something that would cancel out the curse to render the bridge inert" +bedwars.3863="That'll do. See you on the other side." +bedwars.3864="There it is - the golden figurine of the Sandman." +bedwars.3865="Have you heard of him? He's well known in all sorts of folklore stories." +bedwars.3866="This is what we're looking for, my friend!" +bedwars.3867="But to avoid traps, I need something to swap it with..." +bedwars.3868="Something light, but also clean." +bedwars.3869="I need to replace the figurine with something light." +bedwars.3870="Small, and clean, so its shiny like the figurine." +bedwars.3871="Maybe someone at the hotel has something that could help?" +bedwars.3872="A... murder knife?" +bedwars.3873="You could have just told me its a knife, no need to mention murder." +bedwars.3874="That's a bit of a stretch... but it'll do." +bedwars.3875="Talk to me when you're ready, things might be wild." +bedwars.3876="Did that say Escape Sequence?" +bedwars.3877="Oh boy, well, here goes nothing!" +bedwars.3878="See you on the outside!" +bedwars.3879="That's the exit? I was hoping for somewhere to jump in." +bedwars.3880="Find me the real exit, dummy" +bedwars.3881="Hey there's a pit I can get behind!" +bedwars.3882="See ya!" +bedwars.3883="I gotta go back to the pit man..." +bedwars.3884="This place is giving me the creeps.." +bedwars.3885="It smells like... Bed Wars." +bedwars.3886="I don't like Bed Wars, I only play the pit." +bedwars.3887="Can you show me the exit?" +bedwars.3888="Take me to the exit man, I gotta get out of here." +bedwars.3889="I can't stop playing Bed Wars but I'm not very good at it." +bedwars.3890="At this point I'm close to giving up, but the game keeps pulling me back." +bedwars.3891="Maybe I'll look at some YouTubers playing for a while." +bedwars.3892="Terrible Tony" +bedwars.3893="Peter" +bedwars.3894="Explorer John Indigos" +bedwars.3895="Wally" +bedwars.3896="You seeing this right?" +bedwars.3897="I ain't crazy." +bedwars.3898="There's a wither up there." +bedwars.3899="It's creepy, it keeps looking at us." +bedwars.3900="If we don't take it down, the enemy team won't stop respawning." +bedwars.3901="What am I talking about? That's common knowledge isn't it?" +bedwars.3902="Anyway, I need your help sending it back where it came from." +bedwars.3903="We're gonna trap him and use the nether stars to teleport him back to Solace." +bedwars.3904="There's a team out there that's winning because no one can kill their wither." +bedwars.3905="It's our responsibility to send it back, really." +bedwars.3906="Ah there we go, watch this!" +bedwars.3907="I hope we never see one of those pesky withers again!" +bedwars.3908="I was taking a quick nap between reforges." +bedwars.3909="This guy made me reforge his Hyperion like 300 times!" +bedwars.3910="Made good money tho." +bedwars.3911="I feel like making a hammer. Do you want one? I don't make hammers often enough." +bedwars.3912="There conveniently is a forge right next to me." +bedwars.3913="I can make you one, if you bring me the materials." +bedwars.3914="I need quite a few things." +bedwars.3915="Bring me all of that, and I'll make you the hammer." +bedwars.3916="That's all I need! You got it all!" +bedwars.3917="That's very impressive, I'll get to work!" +bedwars.3918="There you go! One fancy-looking Explorer's Ornate Enchanted Iron Hammer." +bedwars.3919="Better wake up soon, I got reforges to apply and coin to make." +bedwars.3920="And I'll pay you back with Slumber Tickets." +bedwars.3921="Turns out I'll be needing to make 5,000 more iron swords and 5,000 more silver daggers." +bedwars.3922="After that, I should be a master blacksmith. Right?" +bedwars.3923="Apprentice Blacksmith Roberto" +bedwars.3924="Someday, I'll be the village blacksmith!" +bedwars.3925="I'm training to be, at least." +bedwars.3926="Can you get me some stuff to practice with?" +bedwars.3927="I need Silver and Iron, really." +bedwars.3928="I'm thinking of making 3,000 iron swords and 3,000 silver daggers." +bedwars.3929="That should skill me up nicely." +bedwars.3930="Yes! That should get me a few more crafts in." +bedwars.3931="Here's your tickets!" +bedwars.3932="Chef Bucky" +bedwars.3933="I keep messing up. I'm trying to make Soul Burgers for Chef Grant." +bedwars.3934="We always need more - I can pay you these Slumber Tickets if you want?" +bedwars.3935="Bring those to me anytime you have extra, and I'll pay you with Slumber Tickets." +bedwars.3936="Ah, yes, there we go. With this I can make more Soul Burgers." +bedwars.3937="Here's your tickets." +bedwars.3938="I'm trying to run a Kitchen here!" +bedwars.3939="My co-chef is a complete moron." +bedwars.3940="I can't keep him in check." +bedwars.3941="I can't keep him focused." +bedwars.3942="Everything he makes comes back OVERCOOKED!" +bedwars.3943="And now we've run out of ingredients!" +bedwars.3944="What are you Chef Bucky? WHAT ARE YOU?" +bedwars.3945="A dummy burger..." +bedwars.3946="That's right you are. Get back to work." +bedwars.3947="I hope I fed my dog before going to bed, I don't remember!" +bedwars.3948="I wonder if I got a room here if I could sleep within my sleep..." +bedwars.3949="Oh man I may have forgotten to set my alarm clock..." +bedwars.3950="I wonder who the owner of this place is?" +bedwars.3951="The Receptionist is a bit cold, aren't they..." +bedwars.3952="The hostess is always so nice to me... I wonder if she's dreaming too." +bedwars.3953="Do these people constantly clean all the Sheets in Bed Wars matches?" +bedwars.3954="I saw a door open earlier, I swear I saw sand behind it!" +bedwars.3955="One of the doors smells like the ocean... it's eerie!" +bedwars.3956="Maybe I'll just browse cool videos on my phone while I wait..." +bedwars.3957="I'm hungry." +bedwars.3958="This place is always so clean, yet I never see anyone cleaning it!" +bedwars.3959="When's the breakfast bar opening? Oh, in the morning when I wake up..." +bedwars.3960="A quest? What? I don't have anything of the sort!" +bedwars.3961="I went to bed like a minute ago." +bedwars.3962="I woke up here, this is the third time this month!" +bedwars.3963="I guess I didn't quite wake up..." +bedwars.3964="Confused Fellow" +bedwars.3965="Hammer" +bedwars.3966="My name is Hammer." +bedwars.3967="I am half werewolf... and I hunt werewolves." +bedwars.3968="You know what works well against werewolves?" +bedwars.3969="That's right, Silver." +bedwars.3970="Shopkeepers on the floating islands should have some silver coins." +bedwars.3971="Ill pay you back, I promise!" +bedwars.3972="You don't have the coins yet?" +bedwars.3973="Are you out of your dang mind?!" +bedwars.3974="That's great. I'll use the furnace downstairs to melt it all and make a weapon." +bedwars.3975="I'm not sure which one yet. A blade sounds nice, but my name's Hammer..." +bedwars.3976="I can't decide..." +bedwars.3977="Heatwave... I promise you.... You'll be dead by the dawn..." +bedwars.3978="Hermes" +bedwars.3979="Hold on, I haven't even started building my house!" +bedwars.3980="Wait, you don't look like a guest, who are you?" +bedwars.3981="Slumber... Bed Wars? This is Housing lol." +bedwars.3982="Can you help me unlock my materials? What year is this?" +bedwars.3983="It's 2015, Housing just came out. Who are you again?" +bedwars.3984="I could check the delivery man again..." +bedwars.3985="Do you have any Mystery Boxes for me yet?" +bedwars.3986="Ah, sweet. I'll head to the Main Lobby in a bit to open these." +bedwars.3987="Hopefully I get some neat materials." +bedwars.3988="Here, I found these on the ground when you came in." +bedwars.3989="With these Mystery Boxes I can finally build my house!" +bedwars.3990="I believe I have deciphered the map my friend!" +bedwars.3991="I shall mount an expedition, post haste!" +bedwars.3992="I've already gathered some new tools, but I need a special kind of hammer." +bedwars.3993="You know, to break doors, something sturdy." +bedwars.3994="I don't know where to begin!" +bedwars.3995="Look around the Hotel to see if anyone can help you." +bedwars.3996="Maybe the people in this Hotel can help?" +bedwars.3997="Look around, talk to people, help them." +bedwars.3998="Try opening doors!" +bedwars.3999="Well done!" +bedwars.4000="This will definitely do." +bedwars.4001="I'm leaving for the expedition soon." +bedwars.4002="Go speak to the Hotel Receptionist, they'll have something for you." +bedwars.4003="Anyway, I'll be back in a jiffy!" +bedwars.4004="You sand before King Flut!" +bedwars.4005="Sorry, I meant stand not sand. There's a lot of sand in here." +bedwars.4006="I can reward you with Sand, but before you first must execute these simple tasks for me." +bedwars.4007="You see, I lost an Amulet from the Kingdom I come from somewhere in this hotel." +bedwars.4008="I shouldn't have wandered off." +bedwars.4009="It's somewhere wet. Can you find it for me?" +bedwars.4010="I believe it was behind one of those hotel room doors." +bedwars.4011="While you're at it, do you know the staff?" +bedwars.4012="I need a lot of pillows, because comfort, you see." +bedwars.4013="Enemy resource spawners will contain Comfy Pillows once a game." +bedwars.4014="Find the Amulet somewhere... in the hotel!" +bedwars.4015="King Flut" +bedwars.4016="You sand before... Oh it's you!" +bedwars.4017="Enemy resource spawners will contain Comfy Pillows once a game." +bedwars.4018="Find the amulet somewhere... in the hotel!" +bedwars.4019="I found some Slumber Tickets while wandering around." +bedwars.4020="My face's on it, Neat, isn't it?" +bedwars.4021="Thank you, this is all I need for now." +bedwars.4022="Laundry Guy" +bedwars.4023="Eeeeyyyyyy I'm the Laundry Guy." +bedwars.4024="... I wish I had more of an identity but that's really who I am." +bedwars.4025="I clean the sheets that come in after Bed Wars matches are over." +bedwars.4026="At least those that don't get destroyed..." +bedwars.4027="I got a quota to reach my friend." +bedwars.4028="Bring me dirty sheets from broken beds, and I might reach it." +bedwars.4029="Where were you keeping those?" +bedwars.4030="Doesn't matter, time to get cleaning." +bedwars.4031="Here, have some Slumber Tickets on the house." +bedwars.4032="But, don't tell the house." +bedwars.4033="So many sheets to clean..." +bedwars.4034="Oasis Spirit" +bedwars.4035="Hello Traveler." +bedwars.4036="I am the spirit of this oasis." +bedwars.4037="I can grant you a boon." +bedwars.4038="But first, you need to bring me something." +bedwars.4039="Take this Dreamer Soul Collector." +bedwars.4040="Defeat enemies by knocking them into the void to collect Dreamer's Soul Fragments." +bedwars.4041="You have performed well." +bedwars.4042="HE should take notice..." +bedwars.4043="I shall grant you this important boon and some Enchanted Oasis Water..." +bedwars.4044="Do not waste it..." +bedwars.4045="Thank you, that is all I need for now." +bedwars.4046="Have you heard of the myth of the Sand Man?" +bedwars.4047="In ancient times, the Sand Man would sprinkle magical sand on people's eyes." +bedwars.4048="This would help them go to sleep more easily, and inspire beautiful dreams." +bedwars.4049="I'd say that sounds fun, but that's never happened to me!" +bedwars.4050="I play a lot of Bed Wars! I could 1v1 you ezpz." +bedwars.4051="I know sick tricks but I'm not gonna tell you about any of them." +bedwars.4052="Gonna post a compilation of my best kills soon, look me up." +bedwars.4053="Introduce Yourself to the Receptionist" +bedwars.4054="The General's Tea" +bedwars.4055="Obtain a Bed Sheet" +bedwars.4056="Ready for a Nap" +bedwars.4057="King Flut's Missing Artifacts" +bedwars.4058="Hermes Needs Chests" +bedwars.4059="Oasis Spirit Souls" +bedwars.4060="Blacksmith's Iron Nuggets" +bedwars.4061="The Newbie" +bedwars.4062="Laundry Manager's Quota" +bedwars.4063="John Indigos Hammer" +bedwars.4064="The Best Soul Burger in the City" +bedwars.4065="Help The Ratman" +bedwars.4066="The Moon" +bedwars.4067="Jimmy and Bimmy" +bedwars.4068="Feed Don Espresso" +bedwars.4069="Peter the Pit Player" +bedwars.4070="A Murder has Happened" +bedwars.4071="Help Wally" +bedwars.4072="Steal with Jeremy" +bedwars.4073="The Executives Meeting" +bedwars.4074="Repair Jets McTurbo's Kart" +bedwars.4075="The Laundry Gal" +bedwars.4076="Wool for the War Effort" +bedwars.4077="The Art of Fight" +bedwars.4078="bro u gotta win" +bedwars.4079="Hello!" +bedwars.4080="This slot machine contains prizes!" +bedwars.4081="Experience, tickets, figurines!" +bedwars.4082="Spend your extra tickets here!" +bedwars.4083="Comfy Pillows" +bedwars.4084="Used Murder Weapon" +bedwars.4085="Air Freshener" +bedwars.4086="Used Gloves" +bedwars.4087="Dirty Boots" +bedwars.4088="Photo of victim" +bedwars.4089="Blitz Star" +bedwars.4090="Default" +bedwars.4091="Mini Slumber Wallet" +bedwars.4092="Light Slumber Wallet" +bedwars.4093="Light Imperial Wallet" +bedwars.4094="Explorer's Wallet" +bedwars.4095="Hotel Staff Wallet" +bedwars.4096="Platinum Membership Wallet" +bedwars.4097="Stats, achievements, quests, and currency will NOT be earned in this mode!" +bedwars.4098="Completing quests may unlock access to unique cosmetics, which can then be purchased using Bed Wars Tokens." +bedwars.4099="• Bed Wars Tokens - %%chance%%% Chance" +bedwars.4100="Nest of Chicks" +bedwars.4101="Chocolate Bunny" +bedwars.4102="Mister Egg" +bedwars.4103="Coconut Drink" +bedwars.4104="Bungalow" +bedwars.4105="Fishing Rod" +bedwars.4106="Strawberry" +bedwars.4107="Palm Tree" +bedwars.4108="Coconut" +bedwars.4109="Flame" +bedwars.4110="Frog Man" +bedwars.4111="Dark Dragon" +bedwars.4112="Cyclops" +bedwars.4113="Owl" +bedwars.4114="MORE DRAGONS HAVE SPAWNED!" +bedwars.4115="You can only remove traps you have purchased!" +bedwars.4116="Remove %%name%%?" +bedwars.4117="Removed %%name%% from the queue!" +bedwars.4118="PUNCH TO DEPOSIT" +bedwars.4119="Cushioned Boots" +bedwars.4120="Your invisibility was removed by an Reveal Trap!" +bedwars.4121="%%bed%% Bed Reveal trap set off by %%team%% team!" +bedwars.4122="%%bed%% Bed: Reveal trap set off by %%player%% from %%team%% team!" +bedwars.4123="Reveal trap set off by %%team%% team!" +bedwars.4124="Reveal trap set off by %%player%% from %%team%% team!" +bedwars.4125="Bed Wars Settings" +bedwars.4126="Adjust game settings for Bed Wars." +bedwars.4127="Punch To Deposit" +bedwars.4128="When enabled allows you to punch a chest to deposit a stack of items." +bedwars.4129="Left Clicking a chest with items in your hand will attempt to deposit said items." +bedwars.4130="The deposit feature is still active, but any holograms above chests are hidden." +bedwars.4131="Deposit feature is disabled." +bedwars.4132="Slumber Item Notification" +bedwars.4133="When enabled, receive notifications every time you pickup a Slumber Item." +bedwars.4134="Full Wallet Notifications" +bedwars.4135="When enabled warns you when your Slumber Wallet is full of tickets." +bedwars.4136="Trap Removal Confirmation" +bedwars.4137="When enabled, requires you to confirm that you want to remove a trap" +bedwars.4138="Birdhouse" +bedwars.4139="Picnic Basket" +bedwars.4140="Watering Can" +bedwars.4141="Hermit Crab" +bedwars.4142="Sailboat" +bedwars.4143="HOT" +bedwars.4144="Shell" +bedwars.4145="Umbrella" +bedwars.4146="Massive 40 versus 40 all out war on a unique Castle map!" +bedwars.4147="No longer can you be a victim of the Void!" +bedwars.4148="Use the Swap to change ownership between beds! Chaos ensues." +bedwars.4149="Find the Lucky Blocks to earn a variety of events and effects, leading to total mayhem!" +bedwars.4150="Set the starting distance you spawn at to %%distance%%" +bedwars.4151="Potential Rewards" +bedwars.4152="%%color%%%%amount%% Bed Wars %%currency%%!" +bedwars.4153="%%amount%% Slumber Tickets!" +bedwars.4154="Deposited %%color%%x%%amount%% %%item%% into Ender Chest! (%%total%% Total)" +bedwars.4155="Deposited %%color%%x%%amount%% %%item%% into Team Chest! (%%total%% Total)" +bedwars.new_item_in_4="You will now get a new item every 4 seconds!" +bedwars.new_item_in_3="You will now get a new item every 3 seconds!" +bedwars.new_item_in_1="You will now get a new item every 1 seconds!" +bedwars.4159="Mace" +bedwars.4160="On hit, deals an additional +0.25 Bonus Damage for each block you’ve fallen and prevents fall damage." +bedwars.4161="Wind Charge" +bedwars.4162="Short range projectile that launches you when landing. Does NOT push other players." +bedwars.4163="Your TNT can't break blocks here!" +bedwars.4164="Height: %%distance%%" +bedwars.4165="Set the starting height you spawn at to %%distance%%" +bedwars.4166="Next Item: %%time%%" +bedwars.4167="%%event%%: %%time%%" +bedwars.4168="You can't purchase any more traps once your bed is destroyed!" +bedwars.4169="Can't be purchased without a bed!" +bedwars.4170="Dream Calendar" +bedwars.4171="See what Dream Modes will enter rotation next!" +bedwars.4172="This mode is currently not featured." +bedwars.4173="This mode is currently featured." +bedwars.4174="Dream Rotation" +bedwars.4175="This mode will be featured in %%days%% days." +bedwars.4176="This mode will be featured in 1 day." +bedwars.4177="This mode will be featured in %%hours%% hours." +bedwars.4178="This mode will be featured in 1 hour." +bedwars.4179="This mode will be featured in %%minutes%% minutes." +bedwars.4180="This mode will be featured shortly." +bedwars.4181="Changes in %%days%% days!" +bedwars.4182="Changes in 1 day!" +bedwars.4183="Changes in %%hours%% hours!" +bedwars.4184="Changes in 1 hour!" +bedwars.4185="Changes in %%minutes%% minutes!" +bedwars.4186="Changes shortly!" +bedwars.4187="One Block" +bedwars.4188="Swappage" +bedwars.4189="Utilize a new arsenal of ranged weapons to win the game!" +bedwars.4190="Collect Souls from killing players and breaking beds to trade for new items!\n\nThis is a Halloween exclusive mode!" +bedwars.4191="Every few seconds brings a new surprise! Use these items to defend your bed or destroy enemy beds." +bedwars.4192="Monthly Wins" +bedwars.4193="Monthly Final Kills" +bedwars.4194="Monthly Beds Broken" +bedwars.4195="Pickaxe" +bedwars.4196="Axe" +bedwars.4197="Shears" +bedwars.4198="%%amount%% Tickets" +bedwars.4199="%%amount%% XP Doublers" +bedwars.4200="%%color%%%%amount%% Bed Wars %%currency%%" +bedwars.4201="TICKET REWARD! You've obtained %%amount%% rewards! [HOVER TO VIEW]" +bedwars.4202="TICKET REWARD!" +bedwars.4203="!! You have max XP Doublers and will not find any in the Ticket Machine" +bedwars.4204="Bed Wars Tokens ➜ %%chance%%%%%dark_gray%%" +bedwars.4205="Random Cosmetic ➜ %%chance%%%%%dark_gray%%" +bedwars.4206="Slumber Tickets ➜ %%chance%%%%%dark_gray%%" +bedwars.4207="XP Doublers ➜ %%chance%%%%%dark_gray%%" +bedwars.4208="Not Enough Tickets" +bedwars.4209="Come back with at least 75 Tickets!" +bedwars.4210="Each roll costs 75 Tickets." +bedwars.4211="Click to roll once!" +bedwars.4212="Click to roll once! (75 Tickets)" +bedwars.4213="Right-Click to roll 10! (750 Tickets)" +bedwars.4214="Shift Right-Click to roll 100! (7,500 Tickets)" +bedwars.4215="Roll Ticket Machine?" +bedwars.4216="You're already running the Slumber Ticket Machine!" +bedwars.4217="Something went wrong running the animation!" +bedwars.4218="XP Doublers" +bedwars.4219="Whenever you earn Bed Wars XP in-game, XP Doublers are consumed to double it!" +bedwars.4220="Your Doublers: %%amount%%/%%max%%" +bedwars.4221="Obtained %%amount%% %%display%%" +bedwars.4222="XP Doublers!" +bedwars.4223="+%%amount%% Slumber Tickets! (%%reason%%)" +bedwars.4224="+1 Slumber Ticket! (%%reason%%)" +bedwars.4225="Dropped in various amounts from the Ticket Machine." +bedwars.4226="!! Playtime XP is not doubled!" +bedwars.4227="+2 Pumpkins (Final Kill)" +bedwars.4228="+2 Pumpkins (Bed Destroy)" +bedwars.4229="+1 Pumpkin (Kill) (%%have%%/%%limit%%)" +bedwars.4230="BOO! You reached Pumpkin Milestone %%milestone%%! Your rewards have been auto claimed." +bedwars.4231="+%%amount%% Bed Wars XP (Pumpkin Milestone Bonus)" +bedwars.4232="+%%amount%% Bed Wars XP (Pumpkin Milestone Reward)" +bedwars.4233="[NPC] Patches: Boo! Happy Halloween!" +bedwars.4234="[NPC] Patches: This month you’ll find δ Pumpkins while playing in-game!" +bedwars.4235="[NPC] Patches: If you turn enough of them in to Shopkeepers, you'll get rewards!" +bedwars.4236="[NPC] Patches: δ Pumpkins can be obtained by getting kills and breaking beds in Bed Wars!" +bedwars.4237="HALLOWEEN EVENT" +bedwars.4238="CLICK" +bedwars.4239="Pumpkin Milestone %%milestone%%" +bedwars.4240="Deliver %%pumpkins%% Pumpkins to Shopkeepers." +bedwars.4241="Progress: %%current%%/%%required%%" +bedwars.4242=" +%%reward%% %%type%%" +bedwars.4243=" +%%reward%% Bed Wars Tokens" +bedwars.4244=" +%%reward%% Bed Wars Experience" +bedwars.4245="Unlocked by reaching Pumpkin Milestone %%milestone%%" +bedwars.4246="Gather δ Pumpkins from kills and breaking beds in-game and take them to a Shopkeeper to claim them!" +bedwars.4247="The more δ Pumpkins you gather, the more rewards you'll get!" +bedwars.4248="Pumpkin Milestones" +bedwars.4249="You'll earn +25 Bed Wars Experience for every 50 Pumpkins you collect" +bedwars.4250="Progress: %%current%%/50 Pumpkins" +bedwars.4251="!! Reach Milestone V first!" +bedwars.4252="Halloween Maps have joined the rotation this month!" +bedwars.4253="There are also some new maps:" +bedwars.4254=" 1. Hollow Hills (Solos, Doubles)" +bedwars.4255=" 2. Sanctuary (3v3v3v3, 4v4v4v4)" +bedwars.4256="New Maps" +bedwars.4257="The Underworld Dream Mode is back in rotation for a limited time this month!" +bedwars.4258="Get Souls by killing players and spend them in the shop for new items!" +bedwars.4259="Click to go to the NPC!" +bedwars.4260="Underworld Mode" +bedwars.4261="The Event Shop features new and returning Halloween cosmetics." +bedwars.4262="New Bed Wars Cosmetics:" +bedwars.4263=" 1. Coffin Island Topper" +bedwars.4264=" 2. Crystal Ball Island Topper" +bedwars.4265=" 3. Halloween Spray/Kill Note Pack #3" +bedwars.4266="Click to open the Event Shop!" +bedwars.4267="New Cosmetics" +bedwars.4268="Bonus Pumpkins" +bedwars.4269="Bed Wars Halloween" +bedwars.4270="Broken Pumpkin" +bedwars.4271="Crystal Ball" +bedwars.4272="Coffin" +bedwars.4273="Stack O' Lantern" diff --git a/configuration/i18n/en_US/official/bungee.properties b/configuration/i18n/en_US/official/bungee.properties new file mode 100644 index 000000000..ad759f8f0 --- /dev/null +++ b/configuration/i18n/en_US/official/bungee.properties @@ -0,0 +1,70 @@ +bungee_miscellaneous.0="Outdated Client!" +bungee_miscellaneous.1="We're down for maintenance, try again in a bit!" +bungee_miscellaneous.2="The name you sent was invalid!" +bungee_miscellaneous.3="You're already connected to this server!" +bungee_miscellaneous.4="Failed to authenticate your connection!" +bungee_miscellaneous.5="You logged in from another location!" +bungee_miscellaneous.6="An error occurred in your connection! Try logging in again!" +bungee_miscellaneous.7="You were spawned in Limbo because the connection failed: %%kickMessage%%" +bungee_miscellaneous.8="The server you were on is rebooting! Please rejoin!" +bungee_miscellaneous.9="Hypixel Network\n\nThere was an issue attempting to connect to the server! :(\nTry reconnecting, if this issue persists, contact a\nstaff member with the information listed below!\n\n%%debug%%" +bungee_miscellaneous.10="An internal error occurred when running this command, please inform a staff member!" +bungee_miscellaneous.11="You don't have permission to run that command!" +bungee_miscellaneous.12="You haven't logged into Hypixel before and we're in offline mode!" +bungee_miscellaneous.13="Your username is inappropriate. Change it at minecraft.net before returning.\nIf this is an error, visit https://hypixel.net" +bungee_miscellaneous.14="This server is currently full and has VIP-bypass disabled! Try again later!" +bungee_miscellaneous.15="This server is currently full! Try again later!" +bungee_miscellaneous.16="This server is currently full! Buy VIP at http://store.hypixel.net to be able to join." +bungee_miscellaneous.17="Huh, we can't seem to find that server in the listing! Probably something on our end. Please contact a staff member." +bungee_miscellaneous.18="This server is running BungeeCord version %%version%% by md_5" +bungee_miscellaneous.19="Couldn't connect you to your previous server, %%serverName%%" +bungee_miscellaneous.20="Enabled debug connect" +bungee_miscellaneous.21="Disabled debug connect" +bungee_miscellaneous.22="You are currently in limbo" +bungee_miscellaneous.23="You are currently connected to server %%serverName%%" +bungee_miscellaneous.24="A disconnect occurred in your connection, so you were put in the %%gameType%% Lobby!" +bungee_miscellaneous.25="A disconnect occurred in your connection, so you have been routed to limbo!" +bungee_miscellaneous.26="An exception occurred in your connection, so you were put in the %%gameType%% Lobby!" +bungee_miscellaneous.27="An exception occurred in your connection, so you have been routed to limbo!" +bungee_miscellaneous.28="You were kicked from that server for flying! Do you have a laggy connection?" +bungee_miscellaneous.29="A kick occurred in your connection, so you were put in the %%gameType%% lobby!" +bungee_miscellaneous.30="A kick occurred in your connection, so you have been routed to limbo!" +bungee_miscellaneous.31="You're already in this channel!" +bungee_miscellaneous.32="You aren't allowed to join the staff channel!" +bungee_miscellaneous.33="Invalid usage! Correct usage: /chat channel" +bungee_miscellaneous.34="§cYou are already connected to this server" +bungee_miscellaneous.35="A kick occurred while connecting you, so you have been routed to the main lobby!" +bungee_miscellaneous.36="You must choose a class before joining that server!" +bungee_miscellaneous.37="You were kicked while joining that server!" +bungee_miscellaneous.38="Couldn't connect you to that server, so you were put in the %%gameType%% lobby!" +bungee_miscellaneous.39="This game has already started! Please try again!" +bungee_miscellaneous.40="The correct syntax is /ochat <message>." +bungee_miscellaneous.41="ochat" +bungee_miscellaneous.42="OFFICER" +bungee_miscellaneous.43="This proxy is restarting soon." +bungee_miscellaneous.44="Please re-connect to mc.hypixel.net!" +bungee_miscellaneous.45="WARNING" +bungee_miscellaneous.46="Something went wrong trying to send you to that server! If this keeps happening please report it!" +bungee_miscellaneous.47="Could not connect you to that server, so routing to Limbo!" +bungee_miscellaneous.48="Could not connect you to that server!" +bungee_miscellaneous.49="You are currently playing on %%host%% with ID %%instance%% (%%prefix%%)" +bungee_miscellaneous.50="Click to put in chat!" +bungee_miscellaneous.51="Click to put server in chat!" +bungee_miscellaneous.52="The lobby you attempted to join was full or offline." +bungee_miscellaneous.53="Because of this, you were routed to Limbo, a subset of your own imagination." +bungee_miscellaneous.54="This place doesn't exist anywhere, and you can stay here as long as you'd like." +bungee_miscellaneous.55="To return to "reality", use /lobby GAME." +bungee_miscellaneous.56="Examples: /lobby, /lobby skywars, /lobby arcade" +bungee_miscellaneous.57="Watch out, though, as there are things that live in Limbo." +bungee_miscellaneous.58="You are AFK" +bungee_miscellaneous.59="Move around to return to the lobby." +bungee_miscellaneous.60="Your version (%%version%%) of Minecraft is disabled on Hypixel due to compatibility issues. Please use 1.8 or 1.21 to play on Hypixel.\n\nRead more at https://hypixel.net/versionnotice" +bungee_miscellaneous.61="Valid channels: all, party, guild, officer, skyblock-coop" +bungee_miscellaneous.62="Valid channels: all, party, guild, officer, skyblock-coop, staff" +bungee_miscellaneous.63="Invalid channel! Valid channels: all, party, guild, officer, skyblock-coop" +bungee_miscellaneous.64="Invalid channel! Valid channels: all, party, guild, officer, skyblock-coop, staff" +bungee_miscellaneous.65="You have no SkyBlock data. Please join SkyBlock on mc.hypixel.net first!" +bungee_miscellaneous.66="Your SkyBlock data was not migrated yet. Please join SkyBlock on mc.hypixel.net first!" +bungee_miscellaneous.67="Encountered an issue trying to process your SkyBlock data." +bungee_miscellaneous.68="Failed cloning your SkyBlock data: An unexpected internal error occured." +bungee_miscellaneous.69="Failed cloning your SkyBlock data: %%message%%" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/challenges.properties b/configuration/i18n/en_US/official/challenges.properties new file mode 100644 index 000000000..1c38962d4 --- /dev/null +++ b/configuration/i18n/en_US/official/challenges.properties @@ -0,0 +1,211 @@ +challenges.0="Win a game of Build Battle." +challenges.1="Kill a Hunter in Farm Hunt." +challenges.2="Kill %%amount%% Zombies in Blocking Dead." +challenges.3="Obtain at least %%amount%% score in Bounty Hunter." +challenges.4="Reach wave %%amount%% in Creeper Attack." +challenges.5="Kill a player while riding the Dragon." +challenges.6="Have both BIGSHOT and TRIPLESHOT powerups at the same time." +challenges.7="Get a kill with a beam sword." +challenges.8="Get a kill while you have at least 100 personal knockback." +challenges.9="Reach the Finals during a game of Hole in the Wall." +challenges.10="Obtain at least %%amount%% points during a Hypixel Says game." +challenges.11="Reach the Final during a game of Pixel Painters." +challenges.12="Win at least %%amount%% rounds during a Party game." +challenges.13="Score %%amount%% goals during a Football game." +challenges.14="Get a Final Kill using an arrow in a game of Mini Walls." +challenges.15="Grab a Magical Key during a game." +challenges.16="Kill at least %%amount%% enemies during a 4v4 game." +challenges.17="Win a game without using your Ultimate Skill." +challenges.18="Use the Blitz Star." +challenges.19="Wear a full set of Iron Armor." +challenges.20="Win a game before Deathmatch." +challenges.21="Kill a player before the 1 minute mark." +challenges.22="Kill %%amount%% enemies before the Red Walls fall." +challenges.23="Purchase one of each different lucky block during a game." +challenges.24="Obtain %%amount%% bow kills during a game." +challenges.25="Activate the Super Lucky block %%amount%% times during a game." +challenges.26="Get %%amount%% pistol kills in a single match." +challenges.27="Get a knife kill." +challenges.28="Get a grenade kill." +challenges.29="Use %%amount%% killstreaks in a single match." +challenges.30="Get at least %%amount%% kills with a Nuke." +challenges.31="Get the last kill in a match." +challenges.32="Obtain both Rapid Fire and Speed Boost powerups in a single game." +challenges.33="Obtain %%amount%% different killstreaks in a single match." +challenges.34="Shut down an enemy player during his streak." +challenges.35="Get a double kill." +challenges.36="Kill %%amount%% players by knocking them into the Void in a single match." +challenges.37="Be the first player to open a middle chest." +challenges.38="Kill %%amount%% players in a single Ranked Mode match." +challenges.39="Have a total of %%amount%% Enderpearls inside your inventory." +challenges.40="Kill all enemies at least once in a game." +challenges.41="Obtain the Smash Crystal %%amount%% times in a single game." +challenges.42="Be the first player to activate your Smash during a game." +challenges.43="Win a game without dying." +challenges.44="Obtain a potion in a speed UHC Game." +challenges.45="Enchant a Diamond Item in a Speed UHC Game." +challenges.46="Get %%amount%% bow kills in a single Speed UHC Game." +challenges.47="Get %%amount%% kill in the Nether during a Speed UHC Game." +challenges.48="Pickup at least %%amount%% coins during a single game." +challenges.49="Get hit by a Blue Torpedo." +challenges.50="Hit a player with a Banana." +challenges.51="Finish the game in the top 3 players." +challenges.52="Manage to stay in a game for at least %%amount%% minutes." +challenges.53="Win a game without using a single powerup." +challenges.54="Get tagged at least %%amount%% different rounds and still win the game." +challenges.55="Hit an enemy from at least %%amount%% blocks away with an arrow." +challenges.56="Don't take any damage during the Grace Period." +challenges.57="Obtain at least %%amount%% kills before the start of Deathmatch." +challenges.58="Deal at least %%amount%% damage to enemy players during a game." +challenges.59="Obtain %%amount%% kills with the Original Fang in a single game." +challenges.60="Win a game as a survivor without buying more than %%amount%% gold." +challenges.61="Kill a Vampire with Holy Water." +challenges.62="Be the last Survivor remaining in your game." +challenges.63="Deal at least %%amount%% damage to a Wither during a game." +challenges.64="Obtain a top 3 Final Kill place at the end of your game." +challenges.65="Win a game while your Wither was not the last to fall." +challenges.66="Wear a fully enchanted set of armor." +challenges.67="Open a secret chest during a match." +challenges.68="Heal at least %%amount%% HP on your teammates during a game." +challenges.69="Reach the top damage leaderboard at the end of the game." +challenges.70="Capture a flag." +challenges.71="End a game with at least %%amount%% times more kills than deaths in TDM." +challenges.72="Get %%amount%% kills in a row." +challenges.73="Get %%amount%% kills within %%time%%." +challenges.74="Get a kill." +challenges.75="Get %%amount%% kills." +challenges.76="Be the first player to get a kill during a match." +challenges.77="Be the first player to reach %%amount%% kills." +challenges.78="Win a team game with all members of your team alive." +challenges.79="Get at least %%amount%% Takedowns defending your Wither." +challenges.80="Support Challenge" +challenges.81="Brute Challenge" +challenges.82="Capture Challenge" +challenges.83="Carry Challenge" +challenges.84="Enderchest Challenge" +challenges.85="Open an Enderchest." +challenges.86="Teamwork Challenge" +challenges.87="Fighter Challenge" +challenges.88="Kill 2 players in a single game." +challenges.89="Monster Killer Challenge" +challenges.90="Kill 2 mobs in a single game." +challenges.91="WHERE IS IT Challenge" +challenges.92="Triple Kill Challenge" +challenges.93="No Ultimate Challenge" +challenges.94="Cooperation Challenge" +challenges.95="Feeding the Void Challenge" +challenges.96="Rush Challenge" +challenges.97="Ranked Challenge" +challenges.98="Enderman Challenge" +challenges.99="TNT Run Challenge" +challenges.100="Manage to stay in a game for at least 3 minutes." +challenges.101="PVP Run Challenge" +challenges.102="Kill a player without knocking them into the void." +challenges.103="Bow Spleef Challenge" +challenges.104="Use all of your perks." +challenges.105="TNT Tag Challenge" +challenges.106="Tag 5 people." +challenges.107="Wither Challenge" +challenges.108="Protector Challenge" +challenges.109="Get at least 10 kills/assists defending your Wither." +challenges.110="Berserk Challenge" +challenges.111="Comeback Challenge" +challenges.112="Rampage Challenge" +challenges.113="Samples Challenge" +challenges.114="Archer Challenge" +challenges.115="Super Lucky Challenge" +challenges.116="Build Battle Challenge" +challenges.117="Farm Hunt Challenge" +challenges.118="Blocking Dead Challenge" +challenges.119="Bounty Hunter Challenge" +challenges.120="Creeper Attack Challenge" +challenges.121="Dragon Wars Challenge" +challenges.122="Ender Spleef Challenge" +challenges.123="Galaxy Wars Challenge" +challenges.124="Throw Out Challenge" +challenges.125="Hole in the Wall Challenge" +challenges.126="Hypixel Says Challenge" +challenges.127="Pixel Painters Challenge" +challenges.128="Party Games Challenge" +challenges.129="Football Challenge" +challenges.130="Mini Walls Challenge" +challenges.131="Pistol Challenge" +challenges.132="Knife Challenge" +challenges.133="Grenade Challenge" +challenges.134="Killing Spree Challenge" +challenges.135="Fang Challenge" +challenges.136="Gold Challenge" +challenges.137="Purifying Challenge" +challenges.138="Last Stand Challenge" +challenges.139="Longshot Challenge" +challenges.140="Perfect Start Challenge" +challenges.141="Hunter Challenge" +challenges.142="Threat Challenge" +challenges.143="Kill Streak Challenge" +challenges.144="Nuke Challenge" +challenges.145="Finish Challenge" +challenges.146="Coin Challenge" +challenges.147="First Place Challenge" +challenges.148="Banana Challenge" +challenges.149="Leaderboard Challenge" +challenges.150="Alchemist Challenge" +challenges.151="Wizard Challenge" +challenges.152="Marksman Challenge" +challenges.153="Nether Challenge" +challenges.154="Crystal Challenge" +challenges.155="Smash Challenge" +challenges.156="Flawless Challenge" +challenges.157="Star Challenge" +challenges.158="Iron Man Challenge" +challenges.159="Blitz Challenge" +challenges.160="Resistance Challenge" +challenges.161="Defensive" +challenges.162="Defend your bed against 5 attackers in a single game." +challenges.163="Support" +challenges.164="Collect 10 diamonds in a single game." +challenges.165="Offensive" +challenges.166="Destroy 2 beds in a single game." +challenges.167="Powerup Challenge" +challenges.168="Killing Streak Challenge" +challenges.169="Don't Blink Challenge" +challenges.170="Combo Challenge" +challenges.171="First Blood Challenge" +challenges.172="Powerhouse Challenge" +challenges.173="Looting Challenge" +challenges.174="Double Kill Challenge" +challenges.175="Defend your bed against %%amount%% attackers in a single game." +challenges.176="Collect %%amount%% diamonds in a single game." +challenges.177="Destroy %%amount%% beds in a single game." +challenges.178="Get at least %%amount%% kills/assists defending your Wither." +challenges.179="Murder Spree" +challenges.180="Sherlock" +challenges.181="Hero" +challenges.182="Kill %%amount%% players as the murderer in a single game." +challenges.183="Kill the murderer in under 2 minutes as the detective." +challenges.184="Become the hero by killing the murderer as innocent." +challenges.185="Serial Killer" +challenges.186="Become the hero by killing the murderer as an innocent or the detective." +challenges.187="Collect %%amount%% diamonds from generators in a single game." +challenges.188="Feed The Void Challenge" +challenges.189="Hit 20 successful bow shots." +challenges.190="Kill 2 players." +challenges.191="Kill a player by knocking them into the void." +challenges.192="Target Practice Challenge" +challenges.193="Teams Challenge" +challenges.194="TNT Wizards Challenge" +challenges.195="Capture 4 points in a single game." +challenges.196="Zombies Challenge" +challenges.197="Kill %%amount%% enemies in Zombies." +challenges.198="Hide and Seek Challenge" +challenges.199="Win a game of Party Pooper as a seeker with at least 1 kill and without hitting an NPC." +challenges.200="Kill %%amount%% players in a single game." +challenges.201="Kill %%amount%% mobs in a single game." +challenges.202="Capture the Wool Challenge" +challenges.203="Kill an enemy by fishing them and making them fall into the void." +challenges.204="Builder Challenge" +challenges.205="Place %%amount%% blocks in one round." +challenges.206="Merciless Killer Challenge" +challenges.207="Kill %%amount%% players in one round." +challenges.208="Win %%amount%% rounds in a row." +challenges.209="Pixel Party Challenge" +challenges.210="Reach Round 20 in Pixel Party" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/chat_filter.properties b/configuration/i18n/en_US/official/chat_filter.properties new file mode 100644 index 000000000..4dc319cc5 --- /dev/null +++ b/configuration/i18n/en_US/official/chat_filter.properties @@ -0,0 +1,6 @@ +chat_filter.speed_limit="You can only chat once every %%expiry%% seconds! Ranked users bypass this restriction!" +chat_filter.discord_username="Your message was blocked because it looks like you're trying to share your Discord username. Try adding it under your social media information by using /profile" +chat_filter.disallowed="This message is not allowed!" +chat_filter.hatred="We blocked your comment \"%%in%%\" as it is breaking our rules because it involves encouraging violence or hatred towards other players. https://www.hypixel.net/rules/" +chat_filter.adult_theme="We blocked your comment \"%%in%%\" as it is breaking our rules because it contains inappropriate content with adult themes. https://www.hypixel.net/rules/" +chat_filter.advertising="Advertising is against the rules. You will receive a punishment on the server if you attempt to advertise." \ No newline at end of file diff --git a/configuration/i18n/en_US/official/collectibles.properties b/configuration/i18n/en_US/official/collectibles.properties new file mode 100644 index 000000000..e0d11122a --- /dev/null +++ b/configuration/i18n/en_US/official/collectibles.properties @@ -0,0 +1,2286 @@ +collectibles.0="Favorite Collectibles" +collectibles.1="Favoriting items allows you to activate them easily. Right click on an item in your Collectibles menu to favorite it!" +collectibles.2="Reset Favorites" +collectibles.3="Click here to reset your Favorites." +collectibles.4="Collectibles" +collectibles.5="Search" +collectibles.6="That feature is currently disabled in this lobby, should be back soon!" +collectibles.7="Unlocked:" +collectibles.8="Removed %%type%% from your Favorites." +collectibles.9="Reset your Favorites." +collectibles.10="You've exceeded the number of cosmetics you can favorite. Right click an item you have favorited to remove it and make space." +collectibles.11="Added %%type%% to your Favorites. You can now select it straight from your inventory!" +collectibles.12="You can't favorite an item you don't own." +collectibles.13="Collectibles" +collectibles.14="Collectibles (Right Click)" +collectibles.15="You must wait another %%seconds%%s before using this!" +collectibles.16="Reset your Morph" +collectibles.17="Sorry, this item is currently unavailable - check back in the future to find out how to unlock!" +collectibles.18="This item can only be unlocked at store.hypixel.net!" +collectibles.19="You must be %%rank%% or higher to use that! Purchase ranks at https//store.hypixel.net" +collectibles.20="This item can only be unlocked by sending %%gifts%% gifts! To view all gifting rewards, open your Mystery Gift Inventory at a Mystery Vault." +collectibles.21="%%color%%Unlocked by reaching the\n%%number%% Gift Milestone Reward%%color%%!" +collectibles.22="This item can only be unlocked as a reward in SkyWars Ranked." +collectibles.23="SkyWars Ranked reward" +collectibles.24="Speak to the Delivery Man to see how to unlock this reward." +collectibles.25="Found in Reward Cards!" +collectibles.26="This item can only be unlocked by reaching Hypixel Level %%level%%!" +collectibles.27="Hypixel Level %%level%%%%color%% reward!" +collectibles.28="%%color%%Unlocked by reaching\nHypixel Level %%level%%%%color%%!" +collectibles.29="Click to claim in the\nHypixel Leveling Menu" +collectibles.30="This item is not yet obtainable!" +collectibles.31="Unlocked at http://store.hypixel.net/!" +collectibles.32="You must be %%rank%%!" +collectibles.33="Not enough Hypixel Credits!" +collectibles.34="You crafted the %%name%%" +collectibles.35="Transform into a %%cleanName%% for 5 minutes. While transformed, you can %%description%% by right-clicking with the Slimeball item in your hotbar." +collectibles.36="squeal" +collectibles.37="moo" +collectibles.38="teleport randomly" +collectibles.39="lay eggs" +collectibles.40="shoot webs all around you" +collectibles.41="activate Rainbow Sheep Mode" +collectibles.42="explode to knock nearby players away" +collectibles.43="shoot fireballs" +collectibles.44="infect other players and turn them into a zombie" +collectibles.45="launch other players in the air" +collectibles.46="throw special potions" +collectibles.47="throw snowballs" +collectibles.48="throw coal" +collectibles.49="shoot lasers" +collectibles.50="Pig Morph" +collectibles.51="Cow Morph" +collectibles.52="Enderman Morph" +collectibles.53="Chicken Morph" +collectibles.54="Spider Morph" +collectibles.55="Sheep Morph" +collectibles.56="Creeper Morph" +collectibles.57="Blaze Morph" +collectibles.58="Zombie Morph" +collectibles.59="Iron Golem Morph" +collectibles.60="Witch Morph" +collectibles.61="Skeleton Morph" +collectibles.62="Snowman Morph" +collectibles.63="Grinch Morph" +collectibles.64="Guardian Morph" +collectibles.65="This morph is on cooldown! Please wait %%seconds%%" +collectibles.66="Activate Morph Skill (Right Click)" +collectibles.67="You are now morphed as a %%name%% for 5 minutes." +collectibles.68="You are now morphed as an %%name%% for 5 minutes." +collectibles.69="Right-Click with the Slimeball selected to activate your morph skill!" +collectibles.70="Your Morph has worn off!" +collectibles.71="An unexpected error occurred! Please report this on the forums." +collectibles.72="Don't click too fast!" +collectibles.73="Reset Morph" +collectibles.74="Morph reset." +collectibles.75="You are not currently morphed!" +collectibles.76="Couldn't find a possible destination." +collectibles.77="You must be near players to use this skill!" +collectibles.78="You must be looking at a block to use this." +collectibles.79="For Glory!" +collectibles.80="I'm the greatest!" +collectibles.81="Epic win!" +collectibles.82="Victory Pose" +collectibles.83="Goodbye" +collectibles.84="Bye bye!" +collectibles.85="Farewell" +collectibles.86="Jump Around" +collectibles.87="Hype Dance" +collectibles.88="Wave Dance" +collectibles.89="Hi-5 mate!" +collectibles.90="Hi-5" +collectibles.91="Happy about your victory? The Hi-5 gesture will let you show your appreciation to your mates!" +collectibles.92="Watch me pirouette!" +collectibles.93="Ballet Dance" +collectibles.94="Feel like you need to dance with style? Show your moves with the Ballet Dance Gesture!" +collectibles.95="Mind... BLOWN!" +collectibles.96="You can't just believe it! This gesture will get your mind blown... Literally!" +collectibles.97="Feet up in the air!" +collectibles.98="Can Can Dance" +collectibles.99="Dance like a total pro with this Can Can Dance Gesture! Do you think you can do it for longer than 10 minutes?" +collectibles.100="Karaoke" +collectibles.101="Show your friends how it's done by singing along with this Karaoke Gesture!" +collectibles.102="Aloha!" +collectibles.103="Hula Dance" +collectibles.104="Move your hips like you are in Hawaii with this Hula Dance Gesture!" +collectibles.105="Let's celebrate!" +collectibles.106="Graduation" +collectibles.107="Yayy!!! School is over and you just graduated! Share it with your friends with the Graduation Gesture!" +collectibles.108="Woop woop woop!" +collectibles.109="Crab Dance" +collectibles.110="Praise the Sun!" +collectibles.111="Praise The Sun" +collectibles.112="Dig For Treasure" +collectibles.113="Despawned your Gesture." +collectibles.114="You must be on the ground to use this!" +collectibles.115="Cannot be found or crafted yet!" +collectibles.116="%%color%%Click to craft for %%dust%% %%color%%Mystery Dust!" +collectibles.117="You need %%dust%% more dust!" +collectibles.118="Can't be crafted with dust!" +collectibles.119="Cost: %%credits%% Hypixel Credits" +collectibles.120="Right click to add to Favorites!" +collectibles.121="Right click to remove from Favorites!" +collectibles.122="Reset your Particle Pack" +collectibles.123="Particle Pack" +collectibles.124="Reset Particle Pack" +collectibles.125="You cannot use that while you are disguised." +collectibles.126="We unequipped your Hat because it would overlap with the Suit Helmet." +collectibles.127="Reset your %%name%%" +collectibles.128="You selected %%name%%" +collectibles.129="You must be using Minecraft 1.8 to use this suit's Skill." +collectibles.130="Full Set Ability:" +collectibles.131="Reset Suit" +collectibles.132="Suits" +collectibles.133="Suits cannot be used in this lobby due to the use of resource packs." +collectibles.134="Collect and wear all the pieces from a specific suit while in a lobby to gain unique effects!" +collectibles.135="Absorb heat and chill the world around you by walking." +collectibles.136="Ice Walker Suit" +collectibles.137="What's better than a cookie? A man who can bake a million cookies!" +collectibles.138="Click to deliver baked goods around the lobby." +collectibles.139="Baker Suit" +collectibles.140="You know what's better than building things? BLOWING THEM UP!" +collectibles.141="Click to throw a bomb!" +collectibles.142="TNT Suit" +collectibles.143="%%color%%%%seconds%%s until detonation!" +collectibles.144="We aren't sure what all the buzz is about this suit." +collectibles.145="This Suit will play a classical song when you fly (requires VIP) or left-click!" +collectibles.146="Bumblebee Suit" +collectibles.147="Don't blink - not even once, not for a second... whatever you do - don't blink!" +collectibles.148="Click any player to lock on, chasing them around the lobby." +collectibles.149="Death Angel Suit" +collectibles.150="It was your Dad's favourite dance movement - bring back the boogie with this Disco Suit!" +collectibles.151="Changes colors when equipped!" +collectibles.152="Disco Suit" +collectibles.153="For generations, the wearer of the Dragon Breath Suit has protected the realms of man with its ancient abilities." +collectibles.154="Click to breathe fire on your foes!" +collectibles.155="Dragon Breath Suit" +collectibles.156="Finally, a suit that works like clockwork... because it is clockwork!" +collectibles.157="Click to play the drums!" +collectibles.158="Toy Soldier Suit" +collectibles.159="Become an everyday hero when you equip this Firefighter Suit!" +collectibles.160="Click to spray water." +collectibles.161="Firefighter Suit" +collectibles.162="Nothing moves faster than the speed of light... except you when you're wearing this Speedster Suit!" +collectibles.163="Sprint to run extremely fast." +collectibles.164="Speedster Suit" +collectibles.165="One of the rarest suits around. Browse dank memes from far above when you equip this Frog Suit." +collectibles.166="Super high jump." +collectibles.167="Frog Suit" +collectibles.168="Are you feeling spooky? Then equip this spooky scary Ghostly Skeleton Suit!" +collectibles.169="Makes the wearer invisible under the suit!" +collectibles.170="Ghostly Skeleton Suit" +collectibles.171="You can't use this while disguised." +collectibles.172="SURPRISE! As a reward for being so generous, you can equip this Surprise Gift Suit!" +collectibles.173="Click to disguise yourself as a present that other players can unwrap." +collectibles.174="Surprise Gift Suit" +collectibles.175="Allows the wearer to throw coal while stealing Christmas." +collectibles.176="Grinch Suit" +collectibles.177="Everything's better down where it's wetter! Head under the sea with this Mermaid Suit." +collectibles.178="Transform into a beautiful Squid when under water." +collectibles.179="Mermaid Suit" +collectibles.180="Put the RAVE in graveyard and bring back the dead with this Necromancer Suit!" +collectibles.181="Click to raise the dead." +collectibles.182="Necromancer Suit" +collectibles.183="Silent but deadly, skulk around your favourite lobby with this Ninja Suit." +collectibles.184="Click to throw a Ninja Shuriken!" +collectibles.185="Ninja Suit" +collectibles.186="YARR! Set sail for treasure in a boat fit for landlubbers and salty sea dogs alike with this Pirate Suit!" +collectibles.187="Click to sail around in a boat." +collectibles.188="Pirate Suit" +collectibles.189="We're sorry, your Princess is in another lobby!" +collectibles.190="Click to throw fireballs." +collectibles.191="Plumber Suit" +collectibles.192="HO HO HO! Discover who has been naughty or nice with this jolly old Santa Suit." +collectibles.193="Click to deliver presents!" +collectibles.194="Santa Suit" +collectibles.195="Your old Soccer ball has been replaced by a brand new one!" +collectibles.196="Soccer ball spawned! If you lose it, left click to spawn a new one." +collectibles.197="Forget Ronaldo, forget Messi, the best player in the world is you wearing this Soccer Suit!" +collectibles.198="Click to spawn a soccer ball, which you can kick around!" +collectibles.199="Soccer Suit" +collectibles.200="FULLY CHARGED" +collectibles.201="Uh oh! Your Solar Power suit ran out of batteries. Left click to recharge it." +collectibles.202="Harness the natural energy of the sun to super charge this Solar Suit!" +collectibles.203="Suit drains as you move around. Click to recharge!" +collectibles.204="Solar Power Suit" +collectibles.205="Wiv grat powr com grat respunsabils. Save the day with this Spooderman Suit." +collectibles.206="Click to swing around lobbies!" +collectibles.207="Spooderman Suit" +collectibles.208="That block is too far away or invalid!" +collectibles.209=""I like this suit. ANOTHER!" Wield the power of the God of Thunder with this Thor Suit." +collectibles.210="Click to strike lightning." +collectibles.211="Thor Suit" +collectibles.212="A Gold Ore has spawned. Right click to collect it!" +collectibles.213="You have collected %%count%% Pieces of Gold" +collectibles.214="Archeology is the search for facts, not truth. Explore tombs, crypts and ruins with this Treasure Hunter Suit!" +collectibles.215="Search lobbies to collect ancient golden treasures." +collectibles.216="Treasure Hunter Suit" +collectibles.217="Like a bat out of hell, become a blood-craving villain with this Vampire Suit!" +collectibles.218="Transform into a bat when you fly." +collectibles.219="You must be on the ground to use the Warrior Suit's abilities." +collectibles.220="The Warrior's way is one of honour, resilience, and butt-kicking special abilities!" +collectibles.221="Left click and look down to Ground Slam, or look ahead to Seismic Wave." +collectibles.222="Warrior Suit" +collectibles.223="If you use this in a less crowded area, you'll get more wolves!" +collectibles.224="Not enough space around you to use this!" +collectibles.225="Click to summon your wolf pack!" +collectibles.226="Wolf Princess Suit" +collectibles.227="Purchase cancelled!" +collectibles.228="Search results:" +collectibles.229="Banners" +collectibles.230="Unlock all the Banners and wear them as hats while in a lobby. They can also be used as items in housing!" +collectibles.231="Reset Hat" +collectibles.232="An error occurred, please report this to a staff member (applyHat returned false)." +collectibles.233="We unequipped your Suit Helmet because it would overlap with the Hat." +collectibles.234="We unequipped your Emote because it would overlap with the Hat." +collectibles.235="You're clicking too fast." +collectibles.236="Standard Hats" +collectibles.237="The good old standard hats." +collectibles.238="Animated Hats" +collectibles.239="Collect all the hats and wear them while in a lobby. Some hats are disabled in certain game lobbies." +collectibles.240="This gadget can only be\nobtained through a\npromotional offer with\nMCProHosting! Type\n/mcph to learn more." +collectibles.241="%%name%% (Right Click)" +collectibles.242="This gadget can only be obtained through a promotional offer with MCProHosting! Type /mcph to learn more." +collectibles.243="You already have %%name%% selected!" +collectibles.244="Fun & Games" +collectibles.245="Play games or just generally mess around in lobbies with these fun gadgets!" +collectibles.246="Mobs & NPCs" +collectibles.247="Spawn and play with wacky creatures using these Mobs & NPC gadgets!" +collectibles.248="Movement" +collectibles.249="Change the way you walk, run or fly around lobbies with these movement-altering gadgets!" +collectibles.250="Musical" +collectibles.251="Make some noise with these sound-emitting musical gadgets!" +collectibles.252="Projectile" +collectibles.253="Fire at will! Shoot your way around the lobbies with these fun projectile gadgets!" +collectibles.254="Visual" +collectibles.255="Change the way you or the lobby looks with these visual gadgets!" +collectibles.256="Ranked Rewards" +collectibles.257="Cosmetic rewards for some of our most competitive players in Ranked games." +collectibles.258="Good news! Your Stat Inspector Gadget is now available in all lobbies! You'll no longer need the item, you can just access it with /stats!" +collectibles.259="Your flower was removed." +collectibles.260="Gadgets are currently disabled!" +collectibles.261="Gadgets are currently disabled, sorry!" +collectibles.262="That Gadget is temporarily disabled!" +collectibles.263="That Gadget is currently disabled!" +collectibles.264="Gadgets are currently disabled in this lobby!" +collectibles.265="You can't activate Gadgets in this area!" +collectibles.266="You must wait another %%time%%s before using this!" +collectibles.267="Reset Gadget" +collectibles.268="Ever wanted to make your friends jealous by making a trampoline appear or just feel like throwing a poop bomb at them? Then Gadgets are for you! These fun little toys can be used while in a lobby." +collectibles.269="Please wait to use this again!" +collectibles.270="This is just an experiment, use at your own risk." +collectibles.271="Where we're going, we don't need roads... but we do need enough room to activate the gadget! Travel back to the future with this crazy Time Travel Car gadget." +collectibles.272="Hey, Doc, we better back up. We don't have enough lobby to get up to 88 miles per hour." +collectibles.273="Lobbies? Where we're going, we don't need lobbies." +collectibles.274="Unleash a wave of bats on your command!" +collectibles.275="Come on, you earned it! Celebrate a real party BBQ style!" +collectibles.276="Spawns in a Beam of assorted colors." +collectibles.277="Places a Candy Cane. Because who doesn't like candy?!" +collectibles.278="Attack your enemies with their worst fear, cats! Launches 4-6 exploding cats in the direction you aim." +collectibles.279="Experimental cannon with chicken ammo. What could go wrong with this one?" +collectibles.280="This lobby already has Christmas Carolers. Please try again in a moment." +collectibles.281="Jingle bells, jingle bells!" +collectibles.282="This lobby has reached its maximum Holiday Trees. Please wait a moment." +collectibles.283="You've already activated a Christmas tree." +collectibles.284="Run... Let's see what presents we got under the tree!" +collectibles.285="There aren't any players to ride nearby!" +collectibles.286="Allows you to ride the nearest player. Create towers by riding pets and then riding other players!" +collectibles.287="Spawn some feline friends that follow you around!" +collectibles.288="You must be looking at a block to use this!" +collectibles.289="Shoot a creeper into the air, if it makes it to the top, enjoy the spectacular show!" +collectibles.290="Freezes you inside ice, great if you're planning on surviving any random apocalypses." +collectibles.291="You rolled a %%result%%!" +collectibles.292="Don't worry, this dice won't get lost even if it falls under your sofa!" +collectibles.293="Your dice fell into the void. Time to find a new one!" +collectibles.294="Spawns a Disco Ball, complete with fancy effects and music." +collectibles.295="Cannonball!" +collectibles.296="Belly Flop!" +collectibles.297="Swan Dive!" +collectibles.298="Backflip!" +collectibles.299="Frontflip!" +collectibles.300="Your previous booth is still there, you can't place two at once!" +collectibles.301="An error occurred, please report this to a staff member. (s%%number%% == null)" +collectibles.302="If you ever wanted to become a DJ, it's now or never! Mesmerize your friends with this DJ set and dancefloor." +collectibles.303="Right out of Farm Hunt, it's the one and only Explosive Sheep back and more explosive than ever." +collectibles.304="Teleport Sticks are for losers. All the cool kids use the Explosive Bow." +collectibles.305="Sets off a firework show, broadcasting MCPH into the sky!" +collectibles.306="Right click a player to give them a flower!" +collectibles.307="You've reached the invite limit, please wait before sending another!" +collectibles.308="You can't invite this player." +collectibles.309="You've already sent a flower request to %%player%%." +collectibles.310="You sent %%player%% a flower!" +collectibles.311="%%player%% has given you a flower!" +collectibles.312="[ACCEPT]" +collectibles.313="[DECLINE]" +collectibles.314="Click here to accept the flower." +collectibles.315="Click here to decline the flower." +collectibles.316="Your invite to %%player%% has expired." +collectibles.317="Your invite from %%player%% has expired." +collectibles.318="Spread the good vibes by giving flowers to everyone around you!" +collectibles.319="You don't have any pending invites." +collectibles.320="Declined %%player%%'s invite." +collectibles.321="You don't have a pending invite from that player." +collectibles.322="That player has left the lobby already." +collectibles.323="Right-Click to remove your flower!" +collectibles.324="%%player%% accepted your flower!" +collectibles.325="Improper usage." +collectibles.326="Strong people don't put others down. They lift them up and slam them on the ground for maximum damage." +collectibles.327="Take regular breaks from playing - it's good for your health!" +collectibles.328="A clean bedroom is the sign of a broken computer." +collectibles.329="A mind is like a parachute - it doesn't work if it's not open." +collectibles.330="34% of statistics found on the internet are completely made up!" +collectibles.331="If at first you don't succeed, skydiving is not the sport for you!" +collectibles.332="Artificial intelligence is no match for natural stupidity." +collectibles.333="When life gives you lemons, make lemonade. When life gives you limes, throw the limes out the window and buy some damn lemonade!" +collectibles.334="You may or may not be an indecisive person." +collectibles.335="Tomorrow, take a left turn. Then a right turn. Then another left turn. You have now reached your destination." +collectibles.336="If you think that nobody cares about you, try not paying your bills!" +collectibles.337="Love is telling someone to go to hell then worrying about them getting there safely." +collectibles.338="If you don't want someone to ask you to do something again, do it terribly the first time!" +collectibles.339="In case of fire, exit the building BEFORE posting about it on the forums!" +collectibles.340="A balanced diet does not mean holding a cake in each hand!" +collectibles.341="Money talks; it usually says goodbye." +collectibles.342="You are very good at keeping secrets; it's the people you tell them to that aren't!" +collectibles.343="You'll win that SkyWars game. Just keep trying until you succeed!" +collectibles.344="Sometimes the best thing you can say is nothing at all." +collectibles.345="If you're not supposed to eat after dark, why is there a light in the refrigerator?" +collectibles.346="Help! I am being held prisoner in the Hypixel fortune cookie factory! Please send help for me!" +collectibles.347="Nothing ruins a Friday more than realising it's actually a Tuesday." +collectibles.348="Improve your memory by doing unforgettable things." +collectibles.349="Sell a man a fish, he'll eat for a day. Teach a man to fish, you'll lose a customer!" +collectibles.350="Only listen to advice gained from cookies - do not trust other fortune-telling foods!" +collectibles.351="You tried your best and failed miserably. The lesson is: never try." +collectibles.352="Do it! Just do it! Don't let your dreams be dreams, just do it!" +collectibles.353="Never give up, unless you have entered the International Giving Up competition." +collectibles.354="Cookies have fortunes. Cats have four tunas." +collectibles.355="Life is like a box of chocolates. Some people are soft-centered, some are tough and chewy, and a few are just plain nuts!" +collectibles.356="If you forget what you look like, just look into a mirror. If the mirror doesn't look back, it's a window!" +collectibles.357="Don't worry about stats too much - what matters is the fun you have!" +collectibles.358="Team work is important - it helps you put the blame on someone else." +collectibles.359="Always eat your tacos over a tortilla. That way if stuff spills out, you have another taco!" +collectibles.360="Make someone else's day by being a good sport, and somebody will make yours!" +collectibles.361="The early bird gets the worm, but that's gross who would want a worm???" +collectibles.362="Why not make a new friend today? Add them with /friend!" +collectibles.363="If you're not happy where you are, take a few steps to the left. If you're still not happy then we cannot help you." +collectibles.364="If you push hard enough you can get through any obstacle - except a door marked "pull"!" +collectibles.365="The only substitute for good manners is fast reflexes." +collectibles.366="Don't worry if Plan A fails - the alphabet has 25 more letters!" +collectibles.367="If you need to get your family's attention, just turn off the WiFi for a minute!" +collectibles.368="When people say they've been to all four corners of the globe, where are they talking about? The globe doesn't have corners!" +collectibles.369="If Mom says no, ask Dad!" +collectibles.370="Disregard all previous fortunes." +collectibles.371="Congratulations, you've won a pointless fortune! Tweet @HypixelNetwork with a screenshot of this to win no prizes!" +collectibles.372="Some of us learn from the mistakes of others; the rest are others." +collectibles.373="Relationships are like algebra. You look at your X and wonder Y?" +collectibles.374="You are unique, just like everybody else." +collectibles.375="You started out with nothing, and you still have most of it." +collectibles.376="Change your password to "incorrect". That way if you forget it, your computer will tell you what it is!" +collectibles.377="How much deeper would the ocean be without sea sponges?" +collectibles.378="There are three kinds of people in the world: those who can count, and those who can't." +collectibles.379="If there aren't any open doors, try a window. If there aren't any open windows, stop trying to break into my house!" +collectibles.380="The universe contains protons, neutrons, electrons and morons." +collectibles.381="The next sentence is a lie. The previous sentence is the truth." +collectibles.382="The fortune you seek is inside another cookie." +collectibles.383="In a hairdressing shop with 2 hairdressers, choose the one with the worst haircut." +collectibles.384="Today you could play a game you haven't tried yet - use the compass!" +collectibles.385="Oh look, a cookie!" +collectibles.386="That cookie was delicious!" +collectibles.387="But wait, there was a piece of paper in it! What does it say?" +collectibles.388="Fortune Cookie: %%message%%" +collectibles.389="What's better than a cookie? A cookie that gives solid life advice! Enjoy a sweet treat and wise words with this Fortune Cookie gadget." +collectibles.390="Somebody's still playing with your previous Frisbee! You can't bring two frisbees to the party, that's not fair!" +collectibles.391="You threw a Frisbee! Have your friends right click it to pick it up, and left click throw it!" +collectibles.392="Your Frisbee has been passed %%passes%% time." +collectibles.393="Your Frisbee has been passed %%passes%% times." +collectibles.394="Toss this carpet... err, frisbee to your friends for maximum fun!" +collectibles.395="First" +collectibles.396="Second" +collectibles.397="Third" +collectibles.398="Fourth" +collectibles.399="Fifth" +collectibles.400="Spawns floating ghost heads that fly away before disappearing as soon as they came." +collectibles.401="Sometimes you have to grapple with serious issues... and other times you just have to grapple! Swing around your favourite lobby with this Grappling Hook gadget." +collectibles.402="You see flashes of lightning, hear blood-curdling screams, and feel the calling of a long dead King... We've got a bad feeling about this Horror Movie gadget!" +collectibles.403="This lobby already has a Hot Air Balloon. Please try again in a moment." +collectibles.404="We asked for a regular balloon, but the balloonist only had XXL left in stock. Take to the skies in this Hot Air Balloon gadget!" +collectibles.405="Ohh, a scoop of Mint Chocolate? No problem!" +collectibles.406="Strawberry ice cream, my favorite!" +collectibles.407="Hazelnuts topping... Double chocolate... And vanilla... Forgot anything?" +collectibles.408="Sorry, we only accept cash for now!" +collectibles.409="I'm afraid I don't have change at the minute :(" +collectibles.410="Ice Cream Guy: %%message%%" +collectibles.411=""I'll have a vanilla fudge ice cream, thanks!"" +collectibles.412="Allows you to open a music player where you can select from various C418 hit singles to play." +collectibles.413="13" +collectibles.414="Blocks" +collectibles.415="Chirp" +collectibles.416="Far" +collectibles.417="Mall" +collectibles.418="Mellohi" +collectibles.419="Stal" +collectibles.420="Strad" +collectibles.421="Ward" +collectibles.422="11" +collectibles.423="Wait" +collectibles.424="Stop Track" +collectibles.425="Stop playing the current track." +collectibles.426=""3... 2... 1... we have lift off! Hold on... wait for it... yep, he hit a tree!" Blast off to infinity and beyond with this rocket-powered Jetpack gadget." +collectibles.427="Makes kookies rain around you!" +collectibles.428="Release a small snowstorm around you, covering the area in white for a short amount of time!" +collectibles.429="Learn the answers to your problems through some of the world's greatest leaders." +collectibles.430="The guy that just got killed by /that/ class" +collectibles.431="Mooooooooooo." +collectibles.432="It's 12AM, wake up." +collectibles.433="Old MacDonald" +collectibles.434="GLaDOS" +collectibles.435="Yet another teamer" +collectibles.436="VRROOOOOMMMM" +collectibles.437="EXTERMINATE!" +collectibles.438="Autoclicker" +collectibles.439="Nicholas Cage" +collectibles.440="I love you." +collectibles.441="*psst* join mc.hypixel.net" +collectibles.442="The Tree that's a Dog" +collectibles.443="YOLOOOOOOOO" +collectibles.444="SlothPixel" +collectibles.445="Fixed." +collectibles.446="I think there's something in Limbo..." +collectibles.447="Nerf that /class/!" +collectibles.448="Correction: Weeping Angels don't say anything." +collectibles.449="The Rooster" +collectibles.450="Cookie Monster" +collectibles.451="The Doctor" +collectibles.452="FEED ME." +collectibles.453="Poser." +collectibles.454="notch" +collectibles.455="Cybermen" +collectibles.456="The Cow" +collectibles.457="Dalek" +collectibles.458="I'm Batman." +collectibles.459="Rooarrrrrrr" +collectibles.460="Rick Grimes" +collectibles.461="Teenager at Starbucks Drive Thru" +collectibles.462="Everyone ever" +collectibles.463="The Cat" +collectibles.464="We're gonna steal the Declaration of Independence." +collectibles.465="AgentKid" +collectibles.466="Bark. Hehe." +collectibles.467="I can't believe it's not butter." +collectibles.468="I can smell you." +collectibles.469="Killing you and giving you good advice aren't mutually exclusive." +collectibles.470="I would be jealous of you, if I wasn't me." +collectibles.471="You will be upgraded." +collectibles.472="Cryptkeeper" +collectibles.473="Morgan Freeman" +collectibles.474="BUTTTT CARRRLLLLL!" +collectibles.475="I was just really, really, really, really good at jitterclicking" +collectibles.476="Cookies." +collectibles.477="I'm so GLaD to see you" +collectibles.478="Don't blink." +collectibles.479="Barney" +collectibles.480="#NoFilter" +collectibles.481="The Bear" +collectibles.482="That one vacuum thing from Teletubbies" +collectibles.483="A bunch of teamers just killed me!" +collectibles.484="Batman" +collectibles.485="wat" +collectibles.486="Broken." +collectibles.487="I have a farm." +collectibles.488="hcherndon" +collectibles.489="Magic 8 Ball" +collectibles.490="Weeping Angel" +collectibles.491="%%author%% says: %%message%%" +collectibles.492="Pretty much just a regular, normal carpet. Except for the whole flying thing of course. A whole new world awaits you on this Magic Carpet gadget." +collectibles.493="MobGun: %%mob%% (Click to Use)" +collectibles.494="Right-click to shoot the selected mob." +collectibles.495="Left-click to cycle between mobs." +collectibles.496="Launch exploding projectiles using %%amount%% different types of mobs." +collectibles.497="Don't worry, activating this gadget won't create another age of extinction... but it will scare your friends! Crash to Earth in a fiery explosion with this galactic Meteorite gadget." +collectibles.498="Showers you in Diamonds, fantastic for showing off your amazing wealth." +collectibles.499="Single" +collectibles.500="Triple" +collectibles.501="Quintuple" +collectibles.502="Paintball Gun: %%type%% Shot (Click to Use)" +collectibles.503="Right-click to shoot the gun." +collectibles.504="Left-click to cycle the firing switch." +collectibles.505="What better way to spruce up the lobby than with a little color? Or a lot, who's counting?" +collectibles.506="Leaves a trail of randomly colored clay behind you that disappears a few seconds later." +collectibles.507="Rockets you into the sky, shortly before deploying your parachute for a soft landing." +collectibles.508="Explodes you into a confetti complete with noises and everything to make your lobby party amazing." +collectibles.509="Ride an Ender Pearl!" +collectibles.510="SAY CHEESE!" +collectibles.511="SMILE!" +collectibles.512="HYPIXEL!" +collectibles.513="Get ready for the camera!" +collectibles.514="Take a screenshot with your best friends!" +collectibles.515="Can't go to the beach? No problem! Carry your own spot in your pocket!" +collectibles.516="Grab your friends and smack the Pinata. You can keep the candy." +collectibles.517="Ignites you into a ball of fire for 10 seconds, before cooling off." +collectibles.518="The lobbies are alive with the sound of music! Listen to your favourite Noteblock hits with this patented Radio gadget!" +collectibles.519="An error occurred trying to play that song!" +collectibles.520="Now playing %%name%%." +collectibles.521="Straight from Quakecraft, it's the basic railgun ready to fire at will!" +collectibles.522="This lobby is too busy to use this Gadget!" +collectibles.523="There is already a Rainbow spawned, try again once it's despawned!" +collectibles.524="Spawns a complete rainbow, featuring all the colors you love and can possibly see." +collectibles.525="ROCKET LAUNCH IN %%time%% SECOND!" +collectibles.526="ROCKET LAUNCH IN %%time%% SECONDS!" +collectibles.527="HOUSTON, WE HAVE LIFT OFF!" +collectibles.528="Blast off to the moon with this large scale rocket complete with countdown, sounds and an explosive ending." +collectibles.529="You must have a pet spawned to use this gadget!" +collectibles.530="Causes your pet to roll over, allowing you to rub their belly." +collectibles.531="Build your own castle with real sand!" +collectibles.532="Spawns a scarecrow that changes the head of nearby players into a pumpkin." +collectibles.533="Turn yourself into the real VIP with these Secret Service guards." +collectibles.534="You have already placed a banner." +collectibles.535="Place a banner to show off your amazing score in SkyWars Ranked." +collectibles.536="April 2016" +collectibles.537="May 2016" +collectibles.538="June 2016" +collectibles.539="July 2016" +collectibles.540="August 2016" +collectibles.541="Season 1 Banner" +collectibles.542="Season 2 Banner" +collectibles.543="Season 2 Banner" +collectibles.544="Season 3 Banner" +collectibles.545="Season 3 Banner" +collectibles.546="Season 4 Banner" +collectibles.547="Season 4 Banner" +collectibles.548="Season 5 Banner" +collectibles.549="Season 5 Banner" +collectibles.550="Iron Division" +collectibles.551="Iron Division #%%position%%" +collectibles.552="Gold Division" +collectibles.553="Gold Division #%%position%%" +collectibles.554="Diamond Division" +collectibles.555="Diamond Division #%%position%%" +collectibles.556="Masters Division" +collectibles.557="Masters Division #%%position%%" +collectibles.558="SkyWars Reward Banner" +collectibles.559="This banner was given as a reward for the SkyWars Ranked season of %%season%%" +collectibles.560="Click here to activate!" +collectibles.561="Uh oh, it's broken!" +collectibles.562="You do not have this banner unlocked." +collectibles.563="Slither like a snake!" +collectibles.564="With this technique, users replace their own body with a block of wood." +collectibles.565="Initiating teleport sequence. Please stand by!" +collectibles.566="Scanning players for a target to teleport to..." +collectibles.567="Process "findTarget" failed! Could not locate a valid target!" +collectibles.568="Target acquired: %%target%%!" +collectibles.569="Aborted teleporting sequence..." +collectibles.570="Buckle up! Teleport initiating..." +collectibles.571="Uh oh! The target has gone under the radar! Aborting..." +collectibles.572="Teleport complete! Thank you for using Hypixel Fast Travel!" +collectibles.573="That's out of the range!" +collectibles.574="You can't teleport there!" +collectibles.575="Allows you to teleport anywhere in the lobby by right-clicking and pointing with this magical stick." +collectibles.576="A Tennis Ball gadget. It's a ball, usually used for tennis. Don't play tennis? Well, if you have a pet you can play fetch!" +collectibles.577="Spawns a pole, complete with a tether ball - perfect for a quick game of tetherball!" +collectibles.578="Click here!" +collectibles.579="Click here to place your symbol here." +collectibles.580="It's not your turn!" +collectibles.581="It's currently not your turn - you can't do anything." +collectibles.582="This slot belongs to Orange." +collectibles.583="This slot belongs to Blue." +collectibles.584="Right click a player to initiate a game of Tic Tac Toe with them!" +collectibles.585="You've already invited %%player%% to a game of Tic Tac Toe." +collectibles.586="You challenged %%player%% to a game of Tic Tac Toe." +collectibles.587="%%player%% has challenged you to a game of Tic Tac Toe." +collectibles.588="Click here to accept the challenge." +collectibles.589="Click here to decline the challenge." +collectibles.590="Orange:" +collectibles.591="Blue:" +collectibles.592="Orange player is %%player%%" +collectibles.593="Blue player is %%player%%" +collectibles.594="The Tic Tac Toe game with %%player%% ended in a draw." +collectibles.595="You defeated %%player%% in Tic Tac Toe!" +collectibles.596="%%player%% defeated you in Tic Tac Toe!" +collectibles.597="Challenge your friends to a tic-tac-toe game. Who will be the winner?" +collectibles.598="%%player%% has left the Tic Tac Toe game." +collectibles.599="Spawns an animated fountain that rains down primed TNT." +collectibles.600="Summon a Tornado, as if you were playing Shaman in Mega Walls." +collectibles.601="Constructs a trampoline that sends you into the air. Invite your friends!" +collectibles.602="What's the best thing to do with Gold? Making it rain Gold." +collectibles.603="Your new Beach Ball replaced your old one." +collectibles.604="There's nothing more fun than playing with a beach ball, ask your friends to join you!" +collectibles.605="Your water balloon is still in the air somewhere!" +collectibles.606="Spawns a flying pig with you riding it into battle!" +collectibles.607="Drawing from the power of the TNT Wizards, you can cycle through the deadly magics of Kinetic, Ice and Blood! Become a magic user with this Wizard Wand gadget." +collectibles.608="%%name%% Wand (Left-click to cycle wands)" +collectibles.609="Right-click to use the wand." +collectibles.610="Left-click to cycle wands." +collectibles.611="Did you forget your sun screen when you went to the beach? Let others know how crispy you are with this Sun Tan Emote!" +collectibles.612="Feeling good? Spread the good vibes with the Heart Eyes Emote!" +collectibles.613="The rollercoaster in the main lobby is not for you? Show others how you feel with the Dizzy Emote!" +collectibles.614="Did you get that final blow? Show mercy to your opponents with this Rest in Pepperoni Emote!" +collectibles.615="Feeling cozy? You surely will with the Relax Emote!" +collectibles.616="Did that habanero pepper get to you? Let the rest know with this Spicy Emote!" +collectibles.617="Do you feel like showing off? Let others see how cool you feel with the real Deal With It Emote!" +collectibles.618="Mustache to Goatee to Epic Beard! Show off how fetching you are with this gentlemanly Mustache Emote." +collectibles.619="Emotes are currently disabled!" +collectibles.620="That Emote is temporarily disabled!" +collectibles.621="That Emote is currently disabled!" +collectibles.622="Emotes are currently disabled in this lobby!" +collectibles.623="Emotes & Gestures" +collectibles.624="Express yourself! Show the world how you're feeling with these unique animated Emotes & Gestures" +collectibles.625="Reset Emote" +collectibles.626="%%name%% Emote" +collectibles.627="Disguises are temporarily disabled" +collectibles.628="To select a hat, please open the Vanity Shop in your inventory!" +collectibles.629="You don't currently have a pet spawned!" +collectibles.630="Reset your pet's name." +collectibles.631="The pet's name cannot be longer than 16 characters!" +collectibles.632="Set your pet's name to %%name%%" +collectibles.633="The pet's name must be alphanumeric!" +collectibles.634="Set the pet's name." +collectibles.635="Teleport the pet to you." +collectibles.636="Teleport to the pet." +collectibles.637="Owners and their pets: %%result%%" +collectibles.638="We couldn't find a player with that name!" +collectibles.639="Type %%type%% does not exist!" +collectibles.640="%%target%% does not own pet of type: %%type%%" +collectibles.641="Find owner -> pet in current instance." +collectibles.642="Find all pet names of a specific player." +collectibles.643="Reset a players petname." +collectibles.644="Emotes are temporarily disabled" +collectibles.645="Gestures are temporarily disabled" +collectibles.646="Slime Particle Pack" +collectibles.647="Drip Lava Particle Pack" +collectibles.648="Drip Water Particle Pack" +collectibles.649="Note Particle Pack" +collectibles.650="Heart Particle Pack" +collectibles.651="Happy Villager Particle Pack" +collectibles.652="Angry Villager Particle Pack" +collectibles.653="Enchantment Table Particle Pack" +collectibles.654="Clapping Gesture" +collectibles.655="Cool Dance Gesture" +collectibles.656="Victory Gesture" +collectibles.657="Goodbye Gesture" +collectibles.658="Jump Gesture" +collectibles.659="Hype Dance Gesture" +collectibles.660="Wave Dance Gesture" +collectibles.661="Hi 5 Gesture" +collectibles.662="Ballet Gesture" +collectibles.663="Mind Gesture" +collectibles.664="Can Gesture" +collectibles.665="Karaoke Gesture" +collectibles.666="Hula Gesture" +collectibles.667="Graduation Gesture" +collectibles.668="Crab Dance Gesture" +collectibles.669="Sun Gesture" +collectibles.670="Treasure Gesture" +collectibles.671="Currently disabled!" +collectibles.672="Made of particles, these cloaks provide ultimate swag. To activate them, stand still for 1 second while in a lobby." +collectibles.673="Reset Cloak" +collectibles.674="Superhero Cloak" +collectibles.675="Mystical Cloak" +collectibles.676="Firewings Cloak" +collectibles.677="Vampire Wings Cloak" +collectibles.678="Frosty Cloak" +collectibles.679="Icewings Cloak" +collectibles.680="Shaman Cloak" +collectibles.681="Rise from the ashes like a phoenix in this display of flames!" +collectibles.682="The cold never bothered me anyway!" +collectibles.683="Is it just me or is it cold here?" +collectibles.684="Shrouded in mystery, this cloak is the center of numerous legends concerning its powers." +collectibles.685="Be surrounded by a tornado, similar to Shaman's Tornado from Mega Walls." +collectibles.686="Straight from the comic books comes that signature red cloak!" +collectibles.687="Giant black and red wings extend from your back to form menacing vampire wings!" +collectibles.688="Type: %%type%%" +collectibles.689="Thirst" +collectibles.690="Exercise" +collectibles.691="Status: %%happiness%%" +collectibles.692="Requires VIP to spawn or rename." +collectibles.693="Requires VIP to spawn or rename." +collectibles.694="Purchase at http://store.hypixel.net" +collectibles.695="Left-Click to despawn this companion." +collectibles.696="Left-Click to despawn this pet." +collectibles.697="Left-Click to summon this companion." +collectibles.698="Left-Click to summon this pet." +collectibles.699="(Use /pet to set name)" +collectibles.700="Click here to see all pets in the %%category%% category!" +collectibles.701="You cannot ride other people's companions!" +collectibles.702="You can't ride this pet." +collectibles.703="You cannot ride other people's pets!" +collectibles.704="You must have %%rank%% to ride your pet! Purchase it at http://store.hypixel.net" +collectibles.705="Pets are currently disabled in this lobby!" +collectibles.706="You must be VIP or higher to summon your pets! Purchase it at http://store.hypixel.net" +collectibles.707="Handling your last mission request!" +collectibles.708="This is currently on cooldown. Please wait %%minutes% more minutes." +collectibles.709="Right-Click your pets inside the Pets Menu to feed them and to increase their happiness." +collectibles.710="Collect, feed, and play with your favourite pets! Level them up by taking care of them!" +collectibles.711="Need someone to help you come out of your shell? Slow and steady always wins the race with this Turtle companion!" +collectibles.712="These little guys tend to follow the most generous person ever, and that person is " +collectibles.713="Yelping, whimpering, howling away in the middle of night... and that's just your friends when they see your cool canine friend! Take this Black Pug companion for a walk today." +collectibles.714="Looking for an Egg-cellent companion? This quacking little friend can't be beak! Become birds of a feather with this dashing Duck companion!" +collectibles.715="He was once a beautiful human prince, transformed by an old witch's curse... or at least that's what he tells people. This friendly Frog companion is just a hop, skip and jump away!" +collectibles.716="BLEEP-BLOOP. BLOOP-BLEEP. Bwwwoooooooo! That's robot for "I love you". From a desert planet to the Hypixel lobby, get ready to roll out with this lovable HP8 companion!" +collectibles.717="If dog is a man's best friend, then this little guy is man's BEST best friend! Embrace the pug life with this White Pug companion." +collectibles.718="Such pet. Many fluffy. Much doge. Wow. Befriend the cutest, fluffiest meme ever with this dank Shibe companion!" +collectibles.719="Monkey see, monkey do, monkey gonna follow you. Go bananas with this swinging Chimp companion!" +collectibles.720="You can ask him why he beats his chest, you can ask him why he loves bananas, but whatever you do... DON'T ask him where he got those glasses! Meet the real king of the jungle with this garish Gorilla companion." +collectibles.721="He may not know Kung Fu, but give this little guy a bamboo stick and he'll be your friend for life. Grin and bear it with this lazy Panda companion!" +collectibles.722="They say an elephant never forgets... to follow you around the Hypixel Lobby! Pack up your trunk and join the herd with this tiny Elephant companion." +collectibles.723="What time is it? Time to stretch your legs and go for a walk with this adventurous Magic Dog companion!" +collectibles.724="You can support the server by unlocking this Companion on the Hypixel Store: store.hypixel.net!" +collectibles.725="This pet can only be obtained through a promotional offer with MCProHosting! Type /mcph to learn more." +collectibles.726="Despawned your %%type%% companion!" +collectibles.727="Spawned your %%name%% companion!" +collectibles.728="Spawned your %%name%% pet!" +collectibles.729="You don't have any Pet Items! Find some by opening Mystery Boxes first!" +collectibles.730="Make this awesome and cuddly %%pet%% yours today!" +collectibles.731="This pet can only be\nobtained through a\npromotional offer with\nMCProHosting! Type\n/mcph to learn more." +collectibles.732="Right-Click to provide care or remove from Favorites." +collectibles.733="Right-Click to provide care or add to Favorites." +collectibles.734="Right-Click to provide care." +collectibles.735="Cat: Black" +collectibles.736="Cat: Red" +collectibles.737="Cat: Siamese" +collectibles.738="Horse: Brown" +collectibles.739="Sheep: White" +collectibles.740="Sheep: Gray" +collectibles.741="Sheep: Brown" +collectibles.742="Sheep: Silver" +collectibles.743="Horse: Creamy" +collectibles.744="Horse: Chestnut" +collectibles.745="Horse: Dark Brown" +collectibles.746="Horse: Gray" +collectibles.747="Mule" +collectibles.748="Villager: Farmer" +collectibles.749="Villager: Librarian" +collectibles.750="Villager: Priest" +collectibles.751="Villager: Blacksmith" +collectibles.752="Villager: Butcher" +collectibles.753="Sheep: Orange" +collectibles.754="Sheep: Magenta" +collectibles.755="Sheep: Light Blue" +collectibles.756="Sheep: Yellow" +collectibles.757="Sheep: Lime" +collectibles.758="Sheep: Cyan" +collectibles.759="Sheep: Purple" +collectibles.760="Sheep: Blue" +collectibles.761="Sheep: Green" +collectibles.762="Sheep: Red" +collectibles.763="Cave Spider" +collectibles.764="Slime (Tiny)" +collectibles.765="Magma Cube (Tiny)" +collectibles.766="Zombie (Baby)" +collectibles.767="Pig (Baby)" +collectibles.768="Cow (Baby)" +collectibles.769="Wolf (Baby)" +collectibles.770="Chicken (Baby)" +collectibles.771="Cat: Black (Baby)" +collectibles.772="Cat: Red (Baby)" +collectibles.773="Cat: Siamese (Baby)" +collectibles.774="Horse: Brown (Baby)" +collectibles.775="Sheep: White (Baby)" +collectibles.776="Sheep: Gray (Baby)" +collectibles.777="Sheep: Brown (Baby)" +collectibles.778="Sheep: Silver (Baby)" +collectibles.779="Horse: White" +collectibles.780="Horse: Black" +collectibles.781="Undead Horse" +collectibles.782="Villager: Zombie" +collectibles.783="Pig Zombie" +collectibles.784="Sheep: Black" +collectibles.785="Sheep: Pink" +collectibles.786="Bat" +collectibles.787="Slime (Small)" +collectibles.788="Magma Cube (Small)" +collectibles.789="Mooshroom" +collectibles.790="Horse: Creamy (Baby)" +collectibles.791="Horse: Chestnut (Baby)" +collectibles.792="Horse: Dark Brown (Baby)" +collectibles.793="Horse: Gray (Baby)" +collectibles.794="Villager: Farmer (Baby)" +collectibles.795="Villager: Librarian (Baby)" +collectibles.796="Villager: Priest (Baby)" +collectibles.797="Villager: Blacksmith (Baby)" +collectibles.798="Villager: Butcher (Baby)" +collectibles.799="Sheep: Orange (Baby)" +collectibles.800="Sheep: Magenta (Baby)" +collectibles.801="Sheep: Light Blue (Baby)" +collectibles.802="Sheep: Yellow (Baby)" +collectibles.803="Sheep: Lime (Baby)" +collectibles.804="Sheep: Cyan (Baby)" +collectibles.805="Sheep: Purple (Baby)" +collectibles.806="Sheep: Blue (Baby)" +collectibles.807="Sheep: Green (Baby)" +collectibles.808="Sheep: Red (Baby)" +collectibles.809="Sheep: Rainbow" +collectibles.810="Mooshroom (Baby)" +collectibles.811="Pig Zombie (Baby)" +collectibles.812="Sheep: Pink (Baby)" +collectibles.813="Sheep: Black (Baby)" +collectibles.814="Witch" +collectibles.815="Skeleton Horse" +collectibles.816="Snowman" +collectibles.817="Slime (Big)" +collectibles.818="Magma Cube (Big)" +collectibles.819="Wither Skeleton" +collectibles.820="Green Little Helper" +collectibles.821="Red Little Helper" +collectibles.822="Wild Ocelot" +collectibles.823="Wild Ocelot (Baby)" +collectibles.824="Rabbit: Brown" +collectibles.825="Rabbit: White" +collectibles.826="Rabbit: Black" +collectibles.827="Rabbit: Black & White" +collectibles.828="Rabbit: Gold" +collectibles.829="Rabbit: Salt & Pepper" +collectibles.830="Powered Creeper" +collectibles.831="Turtle" +collectibles.832="Gifterino" +collectibles.833="Black Pug" +collectibles.834="Duck" +collectibles.835="Frog" +collectibles.836="White Pug" +collectibles.837="Shibe" +collectibles.838="Chimp" +collectibles.839="Gorilla" +collectibles.840="Panda" +collectibles.841="Elephant" +collectibles.842="Magic Dog" +collectibles.843="Current Companion" +collectibles.844="Current Pet" +collectibles.845="This is currently on cooldown. Please wait %%minutes%% more minutes." +collectibles.846="Cooldown: READY" +collectibles.847="Click to gain Pet EXP!" +collectibles.848="Cooldown: %%minutes%% minutes" +collectibles.849="On cooldown." +collectibles.850="The amount of Pet EXP gained\nis increased the happier\nyour pet is." +collectibles.851="Sends all your Happy , Very\nHappy, and Super Happy pets\non a top-secret pet mission\nin order to gain Pet EXP!" +collectibles.852="Send Pets on a Mission" +collectibles.853="Your Pet" +collectibles.854="A delicious fruit!" +collectibles.855="Your %%name%%'s %%attribute%% is already full!" +collectibles.856="This item can only be found through the Mystery Vault! Play games to earn Mystery Boxes." +collectibles.857="Increases a pet's Hunger rating." +collectibles.858="Increases a pet's Exercise rating." +collectibles.859="Increases a pet's Thirst rating." +collectibles.860="Remaining: %%consumables%%" +collectibles.861="Click to give to pet!" +collectibles.862="Contains seeds." +collectibles.863="Serving size: All of it." +collectibles.864="Good for your eyesight!" +collectibles.865="Po-Tae-Toe Poe-Tah-Toe" +collectibles.866="Mushroom Soup" +collectibles.867="This is NOT a Mooshroom Stew!" +collectibles.868="Tastes as good as it smells!" +collectibles.869="Hay" +collectibles.870="Haaaay there how’s it goin’..." +collectibles.871="Not yet processed." +collectibles.872="Freshly baked." +collectibles.873="With chocolate chips!" +collectibles.874="This one is not a lie." +collectibles.875="Caught by the local fisherman." +collectibles.876="For those who like raw meat!" +collectibles.877="Angus Steak" +collectibles.878="Well-prepared and seasoned." +collectibles.879="Dug out of the ground." +collectibles.880="Eeewwww!" +collectibles.881="WARNING: Intense heat!" +collectibles.882="Purified." +collectibles.883="Milk" +collectibles.884="Whole milk." +collectibles.885="Very hot!" +collectibles.886="Wooden Stick" +collectibles.887="Ball" +collectibles.888="Bounces and rolls!" +collectibles.889="Leash" +collectibles.890="Let’s go for a walk!" +collectibles.891="Tickle tickle!" +collectibles.892="FETCH!" +collectibles.893="Sparring Sword" +collectibles.894="En garde!" +collectibles.895="They like it." +collectibles.896="They really like it!" +collectibles.897="Helmet" +collectibles.898="The ultimate transformation! Using these in lobbies will make you transform into a monster and unlock unique powers for everyone else to see!" +collectibles.899="Support Hypixel with these custom-built Companions - most are available to unlock on the Hypixel Store! How many can you collect?" +collectibles.900="You must have at least one pet with a Happy status in order to do that." +collectibles.901="Despawned your %%type%% pet!" +collectibles.902="Already selected!" +collectibles.903="%%name%% (Page %%page%%/%%size%%)" +collectibles.904="Do you wanna build a... wait a minute. Right click to start building a snowman, keep clicking to build it all the way up." +collectibles.905="Found throughout Europe, it's a traditional Christmas Cracker! Right-click another player to open the cracker with them; 1 of the 2 of you will receive a holiday joke!" +collectibles.906="Should Auld acquaintance be forgot? Celebrate the end of another year with this New Years Celebration countdown gadget." +collectibles.907="Pumpkin Pie. Pumpkin Soup. Pumpkin Spice. And now, Pumpkin Cannon! Jack up someone's lanterns with this versatile vegetable." +collectibles.908="Trick or Treat! Use this gadget on another player to offer them a choice, but will they get a nice treat... or a terrible trick!?" +collectibles.909="Solar Power Suit - Battery status: %%charge%%" +collectibles.910="Animated Hats" +collectibles.911="These hats take it a step further and move while on your head." +collectibles.912="Right click the snowman again to keep building!" +collectibles.913="Ender Steve Hat" +collectibles.914="Diamond Steve Hat" +collectibles.915="Gold Steve Hat" +collectibles.916="Iron Steve Hat" +collectibles.917="Stone Steve Hat" +collectibles.918="Wood Steve Hat" +collectibles.919="Ender Dragonling Hat" +collectibles.920="Polar Bear Hat" +collectibles.921="Koala Hat" +collectibles.922="Bird Hat" +collectibles.923="Bee Hat" +collectibles.924="Clownfish Hat" +collectibles.925="Ferret Hat" +collectibles.926="Walrus Hat" +collectibles.927="Monkey Hat" +collectibles.928="Cactus Hat" +collectibles.929="Burger Hat" +collectibles.930="Monitor Hat" +collectibles.931="Beach Ball Hat" +collectibles.932="Duck Hat" +collectibles.933="Earth Hat" +collectibles.934=""A" Hat" +collectibles.935=""B" Hat" +collectibles.936=""C" Hat" +collectibles.937=""D" Hat" +collectibles.938=""E" Hat" +collectibles.939=""F" Hat" +collectibles.940=""G" Hat" +collectibles.941=""H" Hat" +collectibles.942=""I" Hat" +collectibles.943=""J" Hat" +collectibles.944=""K" Hat" +collectibles.945=""L" Hat" +collectibles.946=""M" Hat" +collectibles.947=""N" Hat" +collectibles.948=""O" Hat" +collectibles.949=""P" Hat" +collectibles.950=""Q" Hat" +collectibles.951=""R" Hat" +collectibles.952=""S" Hat" +collectibles.953=""T" Hat" +collectibles.954=""U" Hat" +collectibles.955=""V" Hat" +collectibles.956=""W" Hat" +collectibles.957=""X" Hat" +collectibles.958=""Y" Hat" +collectibles.959=""Z" Hat" +collectibles.960=""0" Hat" +collectibles.961=""1" Hat" +collectibles.962=""2" Hat" +collectibles.963=""3" Hat" +collectibles.964=""4" Hat" +collectibles.965=""5" Hat" +collectibles.966=""6" Hat" +collectibles.967=""7" Hat" +collectibles.968=""8" Hat" +collectibles.969=""9" Hat" +collectibles.970=""+" Hat" +collectibles.971=""#" Hat" +collectibles.972=""?" Hat" +collectibles.973=""!" Hat" +collectibles.974="Snowglobe Hat" +collectibles.975="Toaster Hat" +collectibles.976="Egg Head Hat" +collectibles.977="Sandwich Hat" +collectibles.978="Cheese Hat" +collectibles.979="Mars Hat" +collectibles.980="Penguin Hat" +collectibles.981="Elephant Hat" +collectibles.982="Squid Hat" +collectibles.983="Horse Hat" +collectibles.984="Astronaut Hat" +collectibles.985="Clown Hat" +collectibles.986="Groopo Hat" +collectibles.987="Shibe Hat" +collectibles.988="Elf Princess Hat" +collectibles.989="Otter Hat" +collectibles.990="Dinosaur Hat" +collectibles.991="Mummy Hat" +collectibles.992="Orc Hat" +collectibles.993="Minotaur Hat" +collectibles.994="Demon Knight Hat" +collectibles.995="Scavenger Hat" +collectibles.996="Golden Knight Hat" +collectibles.997="White Wizard Hat" +collectibles.998="Miner Hat" +collectibles.999="Football Star Hat" +collectibles.1000="Monk Hat" +collectibles.1001="Wood Elf Hat" +collectibles.1002="Dead Pirate Hat" +collectibles.1003="Odin Hat" +collectibles.1004="Assassin Villager Hat" +collectibles.1005="Alien Slug Hat" +collectibles.1006="Ghost Hat" +collectibles.1007="Scarecrow Hat" +collectibles.1008="Egyptian Queen Hat" +collectibles.1009="Mage Hat" +collectibles.1010="Fox Hat" +collectibles.1011="Rainbow Glitch Hat" +collectibles.1012="Skull Hat" +collectibles.1013="Pig Zombie Hat" +collectibles.1014="Ghast Hat" +collectibles.1015="Candy Cane Hat" +collectibles.1016="Ginger Bread Man Hat" +collectibles.1017="Red Bauble Hat" +collectibles.1018="Holiday Present Hat" +collectibles.1019="Turtle Hat" +collectibles.1020="Hp8 Hat" +collectibles.1021="Frog Hat" +collectibles.1022="Parrot Hat" +collectibles.1023="Pug White Hat" +collectibles.1024="Pug Black Hat" +collectibles.1025="Owl Hat" +collectibles.1026="Panda Hat" +collectibles.1027="Duckling Hat" +collectibles.1028="Sloth Hat" +collectibles.1029="Gorilla Hat" +collectibles.1030="Magic Dog Hat" +collectibles.1031="Lucky Dragon Hat" +collectibles.1032="Hypixel H Hat" +collectibles.1033="Evil Pumpkin Hat" +collectibles.1034="Marionette Hat" +collectibles.1035="Snowman Hat" +collectibles.1036="Reindeer Hat" +collectibles.1037="Gift Giver Hat" +collectibles.1038="Hi-5 Gesture" +collectibles.1039="Ballet Dance Gesture" +collectibles.1040="Possessed Gesture" +collectibles.1041="Snowball Toss Gesture" +collectibles.1042="Victory Pose Gesture" +collectibles.1043="Mind Blown Gesture" +collectibles.1044="Can Can Dance Gesture" +collectibles.1045="Hula Dance Gesture" +collectibles.1046="Jump Around Gesture" +collectibles.1047="Praise The Sun Gesture" +collectibles.1048="Dig For Treasure Gesture" +collectibles.1049="Zombie Dance Gesture" +collectibles.1050="Have you ever felt like you just aren't quite yourself? Give up the ghost with this Possessed Gesture!" +collectibles.1051="When darkness falls across the land and the midnight hour is close at hand, Zombies Dance in search of blood to terrorize your neighbourhood!" +collectibles.1052="If you stare for too long into the darkness, the darkness might just stare back into you!" +collectibles.1053="Give your friends the best gift they could receive this holiday season: YOU! Just activate this Present Unwrap Emote." +collectibles.1054="Sloth" +collectibles.1055="HP8" +collectibles.1056="These little guys tend to follow the most generous person ever, and that person is you!" +collectibles.1057="Aqua Orb Animated Hat" +collectibles.1058="Basketball Animated Hat" +collectibles.1059="Fire Demon Animated Hat" +collectibles.1060="Forester Animated Hat" +collectibles.1061="Ice Mage Animated Hat" +collectibles.1062="Robo Bird Animated Hat" +collectibles.1063="Siren Animated Hat" +collectibles.1064="Traffic Light Animated Hat" +collectibles.1065="Space Animated Hat" +collectibles.1066="Werewolf Animated Hat" +collectibles.1067="Scarecrow Animated Hat" +collectibles.1068="Elf Boy Animated Hat" +collectibles.1069="Elf Girl Animated Hat" +collectibles.1070="Golem Animated Hat" +collectibles.1071="Broken TV Animated Hat" +collectibles.1072="Bauble Animated Hat" +collectibles.1073="Gingerbread Man Animated Hat" +collectibles.1074="Evil Eye Animated Hat" +collectibles.1075="Clown Animated Hat" +collectibles.1076="Santa Animated Hat" +collectibles.1077="Fox Spirit Animated Hat" +collectibles.1078="Monochrome Girl Animated Hat" +collectibles.1079="Scarf Guy Animated Hat" +collectibles.1080="Cyborg Girl Animated Hat" +collectibles.1081="Herobrine Animated Hat" +collectibles.1082="Chroma Slime Animated Hat" +collectibles.1083="Happy Dude Animated Hat" +collectibles.1084="Blushy Animated Hat" +collectibles.1085="Scout Girl Animated Hat" +collectibles.1086="Flower Crown Animated Hat" +collectibles.1087="Red Overall Animated Hat" +collectibles.1088="Blue Hoodie Animated Hat" +collectibles.1089="Ender Pulse Animated Hat" +collectibles.1090="Rainbow Girl Animated Hat" +collectibles.1091="Demon Eyes Animated Hat" +collectibles.1092="Derpy Eyes Animated Hat" +collectibles.1093="Hypixel Banner" +collectibles.1094="Snow Bunny Banner" +collectibles.1095="Reindeer Banner" +collectibles.1096="Holiday Tree Banner" +collectibles.1097="Santa Banner" +collectibles.1098="Holiday Wreath Banner" +collectibles.1099="Heart Banner" +collectibles.1100="Guitar Banner" +collectibles.1101="Dino Banner" +collectibles.1102="Redpool Banner" +collectibles.1103="Pengu Banner" +collectibles.1104="Skull King Banner" +collectibles.1105="New Year's Celebration Suit" +collectibles.1106="Companions" +collectibles.1107="It's Halloween, the season of fancy dress - why choose one spooky costume when you can have them all?" +collectibles.1108="The suit rapidly changes to different spooky outfits." +collectibles.1109="Celebrate the end of yet another crazy year with the New Year Celebration Suit!" +collectibles.1110="Punch to set off a firework." +collectibles.1111="Not everyone loves Christmas! Collect this full suit to transform into an evil Grinch." +collectibles.1112="Punch to spawn presents that turn into coal." +collectibles.1113="Your morph wears off in %%seconds%%" +collectibles.1114="%%name%% Helmet" +collectibles.1115="%%name%% Chestplate" +collectibles.1116="%%name%% Leggings" +collectibles.1117="%%name%% Boots" +collectibles.1118="Hoppin Blocks" +collectibles.1119="Happy" +collectibles.1120="Corpse Party" +collectibles.1121="Kirby's Gourmet Race" +collectibles.1122="Gamemode 8" +collectibles.1123="Bad Apple" +collectibles.1124="Similar" +collectibles.1125="Aztec Dash" +collectibles.1126="Chased By Creeper" +collectibles.1127="Victory" +collectibles.1128="Voting" +collectibles.1129="Pump It Up" +collectibles.1130="Suspenseful" +collectibles.1131="Interdimensional" +collectibles.1132="Feels" +collectibles.1133="Olympus" +collectibles.1134="Lobby Song" +collectibles.1135="Minecraft Is My Life" +collectibles.1136="Entertainer" +collectibles.1137="lv" +collectibles.1138="BROKEN" +collectibles.1139="MobGun Gadget" +collectibles.1140="Roll Over Gadget" +collectibles.1141="iPixel Gadget" +collectibles.1142="Cowboy Gadget" +collectibles.1143="Pyromaniac Gadget" +collectibles.1144="When Pigs Fly Gadget" +collectibles.1145="Teleport Stick Gadget" +collectibles.1146="Magic 9 Ball Gadget" +collectibles.1147="CATapult Gadget" +collectibles.1148="Diamond Shower Gadget" +collectibles.1149="Gold Fountain Gadget" +collectibles.1150="Kawarimi no Jutsu Gadget" +collectibles.1151="Railgun Gadget" +collectibles.1152="Cryotube Gadget" +collectibles.1153="Trampoline Gadget" +collectibles.1154="Diving Board Gadget" +collectibles.1155="Hypixel Radio Gadget" +collectibles.1156="Paintball Gun Gadget" +collectibles.1157="Explosive Bow Gadget" +collectibles.1158="Fortune Cookie Gadget" +collectibles.1159="Paint Trail Gadget" +collectibles.1160="Exploding Sheep Gadget" +collectibles.1161="Fire Trail Gadget" +collectibles.1162="Creeper Astronaut Gadget" +collectibles.1163="Ghosts Gadget" +collectibles.1164="Grappling Hook Gadget" +collectibles.1165="Jetpack Gadget" +collectibles.1166="Secret Service Gadget" +collectibles.1167="Parachute Gadget" +collectibles.1168="Party Popper Gadget" +collectibles.1169="Poop Bomb Gadget" +collectibles.1170="Tetherball Gadget" +collectibles.1171="Disco Ball Gadget" +collectibles.1172="Horror Movie Gadget" +collectibles.1173="Tennis Ball Gadget" +collectibles.1174="Teleporter Gadget" +collectibles.1175="Magic Carpet Gadget" +collectibles.1176="TNT Wizards Wand Gadget" +collectibles.1177="Meteorite Gadget" +collectibles.1178="Rocket Gadget" +collectibles.1179="TNT Fountain Gadget" +collectibles.1180="Rainbow Gadget" +collectibles.1181="DJ Booth Gadget" +collectibles.1182="Water Balloon Gadget" +collectibles.1183="Dice Gadget" +collectibles.1184="Pocket Beach Gadget" +collectibles.1185="Frisbee Gadget" +collectibles.1186="Beach Ball Gadget" +collectibles.1187="Tic Tac Toe Gadget" +collectibles.1188="Sand Castle Gadget" +collectibles.1189="BBQ Grill Gadget" +collectibles.1190="Chicken Cannon Gadget" +collectibles.1191="Ice Cream Stand Gadget" +collectibles.1192="Flower Giver Gadget" +collectibles.1193="MCProHosting Firework Gadget" +collectibles.1194="Kookie Fountain Gadget" +collectibles.1195="Bat Launcher Gadget" +collectibles.1196="Scarecrow Gadget" +collectibles.1197="Let It Snow Gadget" +collectibles.1198="Holiday Choir Gadget" +collectibles.1199="Holiday Tree Gadget" +collectibles.1200="SkyWars Ranked Banner Gadget" +collectibles.1201="Trick or Treat Gadget" +collectibles.1202="Pumpkin Cannon Gadget" +collectibles.1203="New Year Gadget" +collectibles.1204="Christmas Cracker Gadget" +collectibles.1205="Snowman Gadget" +collectibles.1206="Cry Emote" +collectibles.1207="Sleepy Emote" +collectibles.1208="Rage Emote" +collectibles.1209="Frown Emote" +collectibles.1210="Smile Emote" +collectibles.1211="Cheeky Emote" +collectibles.1212="Cool Emote" +collectibles.1213="Wink Emote" +collectibles.1214="Grin Emote" +collectibles.1215="Surprised Emote" +collectibles.1216="Sun Tan Emote" +collectibles.1217="Heart Eyes Emote" +collectibles.1218="Dizzy Emote" +collectibles.1219="RIP Emote" +collectibles.1220="Relax Emote" +collectibles.1221="Spicy Emote" +collectibles.1222="Deal With It Emote" +collectibles.1223="Moustache Emote" +collectibles.1224="EXP:" +collectibles.1225="Frog Suit Helmet" +collectibles.1226="Frog Suit Chestplate" +collectibles.1227="Frog Suit Leggings" +collectibles.1228="Frog Suit Boots" +collectibles.1229="Ninja Suit Helmet" +collectibles.1230="Ninja Suit Chestplate" +collectibles.1231="Ninja Suit Leggings" +collectibles.1232="Ninja Suit Boots" +collectibles.1233="Speedster Suit Helmet" +collectibles.1234="Speedster Suit Chestplate" +collectibles.1235="Speedster Suit Leggings" +collectibles.1236="Speedster Suit Boots" +collectibles.1237="Ghostly Skeleton Suit Helmet" +collectibles.1238="Ghostly Skeleton Suit Chestplate" +collectibles.1239="Ghostly Skeleton Suit Leggings" +collectibles.1240="Ghostly Skeleton Suit Boots" +collectibles.1241="Disco Suit Helmet" +collectibles.1242="Disco Suit Chestplate" +collectibles.1243="Disco Suit Leggings" +collectibles.1244="Disco Suit Boots" +collectibles.1245="Mermaid Suit Helmet" +collectibles.1246="Mermaid Suit Chestplate" +collectibles.1247="Mermaid Suit Leggings" +collectibles.1248="Mermaid Suit Boots" +collectibles.1249="Spooderman Suit Helmet" +collectibles.1250="Spooderman Suit Chestplate" +collectibles.1251="Spooderman Suit Leggings" +collectibles.1252="Spooderman Suit Boots" +collectibles.1253="Warrior Suit Helmet" +collectibles.1254="Warrior Suit Chestplate" +collectibles.1255="Warrior Suit Leggings" +collectibles.1256="Warrior Suit Boots" +collectibles.1257="Necromancer Suit Helmet" +collectibles.1258="Necromancer Suit Chestplate" +collectibles.1259="Necromancer Suit Leggings" +collectibles.1260="Necromancer Suit Boots" +collectibles.1261="Thor Suit Helmet" +collectibles.1262="Thor Suit Chestplate" +collectibles.1263="Thor Suit Leggings" +collectibles.1264="Thor Suit Boots" +collectibles.1265="Death Angel Suit Helmet" +collectibles.1266="Death Angel Suit Chestplate" +collectibles.1267="Death Angel Suit Leggings" +collectibles.1268="Death Angel Suit Boots" +collectibles.1269="Baker Suit Helmet" +collectibles.1270="Baker Suit Chestplate" +collectibles.1271="Baker Suit Leggings" +collectibles.1272="Baker Suit Boots" +collectibles.1273="Bumblebee Suit Helmet" +collectibles.1274="Bumblebee Suit Chestplate" +collectibles.1275="Bumblebee Suit Leggings" +collectibles.1276="Bumblebee Suit Boots" +collectibles.1277="Firefighter Suit Helmet" +collectibles.1278="Firefighter Suit Chestplate" +collectibles.1279="Firefighter Suit Leggings" +collectibles.1280="Firefighter Suit Boots" +collectibles.1281="Ice Walker Suit Helmet" +collectibles.1282="Ice Walker Suit Chestplate" +collectibles.1283="Ice Walker Suit Leggings" +collectibles.1284="Ice Walker Suit Boots" +collectibles.1285="Vampire Suit Helmet" +collectibles.1286="Vampire Suit Chestplate" +collectibles.1287="Vampire Suit Leggings" +collectibles.1288="Vampire Suit Boots" +collectibles.1289="Dragon Breath Suit Helmet" +collectibles.1290="Dragon Breath Suit Chestplate" +collectibles.1291="Dragon Breath Suit Leggings" +collectibles.1292="Dragon Breath Suit Boots" +collectibles.1293="Pirate Suit Helmet" +collectibles.1294="Pirate Suit Chestplate" +collectibles.1295="Pirate Suit Leggings" +collectibles.1296="Pirate Suit Boots" +collectibles.1297="TNT Suit Helmet" +collectibles.1298="TNT Suit Chestplate" +collectibles.1299="TNT Suit Leggings" +collectibles.1300="TNT Suit Boots" +collectibles.1301="Wolf Princess Suit Helmet" +collectibles.1302="Wolf Princess Suit Chestplate" +collectibles.1303="Wolf Princess Suit Leggings" +collectibles.1304="Wolf Princess Suit Boots" +collectibles.1305="Solar Power Suit Helmet" +collectibles.1306="Solar Power Suit Chestplate" +collectibles.1307="Solar Power Suit Leggings" +collectibles.1308="Solar Power Suit Boots" +collectibles.1309="Soccer Suit Helmet" +collectibles.1310="Soccer Suit Chestplate" +collectibles.1311="Soccer Suit Leggings" +collectibles.1312="Soccer Suit Boots" +collectibles.1313="Santa Suit Helmet" +collectibles.1314="Santa Suit Chestplate" +collectibles.1315="Santa Suit Leggings" +collectibles.1316="Santa Suit Boots" +collectibles.1317="Toy Soldier Suit Helmet" +collectibles.1318="Toy Soldier Suit Chestplate" +collectibles.1319="Toy Soldier Suit Leggings" +collectibles.1320="Toy Soldier Suit Boots" +collectibles.1321="Surprise Gift Suit Helmet" +collectibles.1322="Surprise Gift Suit Chestplate" +collectibles.1323="Surprise Gift Suit Leggings" +collectibles.1324="Surprise Gift Suit Boots" +collectibles.1325="Treasure Hunter Suit Helmet" +collectibles.1326="Treasure Hunter Suit Chestplate" +collectibles.1327="Treasure Hunter Suit Leggings" +collectibles.1328="Treasure Hunter Suit Boots" +collectibles.1329="Costume Suit Helmet" +collectibles.1330="Costume Suit Chestplate" +collectibles.1331="Costume Suit Leggings" +collectibles.1332="Costume Suit Boots" +collectibles.1333="New Year's Celebration Suit Helmet" +collectibles.1334="New Year's Celebration Suit Chestplate" +collectibles.1335="New Year's Celebration Suit Leggings" +collectibles.1336="New Year's Celebration Suit Boots" +collectibles.1337="Grinch Suit Helmet" +collectibles.1338="Grinch Suit Chestplate" +collectibles.1339="Grinch Suit Leggings" +collectibles.1340="Grinch Suit Boots" +collectibles.1341="Present Unwrap Emote" +collectibles.1342="Face Melter Emote" +collectibles.1343="Not available" +collectibles.1344="This item is not available." +collectibles.1345="Enter your" +collectibles.1346="search query!" +collectibles.1347="%%name%% rolled a %%result%%!" +collectibles.1348="Click here to accept the Christmas Cracker." +collectibles.1349="Click here to decline the Christmas Cracker." +collectibles.1350="**CRACK** The Christmas cracker was split in two!" +collectibles.1351="Season 6 Banner" +collectibles.1352="Season 6 Banner" +collectibles.1353="Season 7 Banner" +collectibles.1354="Season 7 Banner" +collectibles.1355="Season 8 Banner" +collectibles.1356="Season 8 Banner" +collectibles.1357="Season 9 Banner" +collectibles.1358="Season 9 Banner" +collectibles.1359="Season 10 Banner" +collectibles.1360="Season 10 Banner" +collectibles.1361="Season 11 Banner" +collectibles.1362="Season 11 Banner" +collectibles.1363="Season 12 Banner" +collectibles.1364="Season 12 Banner" +collectibles.1365="Season 13 Banner" +collectibles.1366="Season 13 Banner" +collectibles.1367="Season 14 Banner" +collectibles.1368="Season 14 Banner" +collectibles.1369="Season 15 Banner" +collectibles.1370="Season 15 Banner" +collectibles.1371="Season 16 Banner" +collectibles.1372="Season 16 Banner" +collectibles.1373="Season 17 Banner" +collectibles.1374="Season 17 Banner" +collectibles.1375="Season 18 Banner" +collectibles.1376="Season 18 Banner" +collectibles.1377="Season 19 Banner" +collectibles.1378="Season 19 Banner" +collectibles.1379="Season 20 Banner" +collectibles.1380="Season 20 Banner" +collectibles.1381="Season 21 Banner" +collectibles.1382="Season 21 Banner" +collectibles.1383="Add to Favorites" +collectibles.1384="Remove from Favorites" +collectibles.1385="Click here to remove this pet from your Favorites menu." +collectibles.1386="Pet Consumables" +collectibles.1387="You got a Bag of Candy, but it was out of date!" +collectibles.1388="You got a Firetruck, but it burned to ashes!" +collectibles.1389="You got a Radio Controlled Car, but it's out of batteries!" +collectibles.1390="You got a Fairy Doll, but it flew away!" +collectibles.1391="You got a Bike, but the tires are flat!" +collectibles.1392="You got a Plush Dog, but it's not domesticated!" +collectibles.1393="You got some Firecrackers, but they all exploded!" +collectibles.1394="You got a Pair of Socks, which is just what you wanted!" +collectibles.1395="by %%author%%" +collectibles.1396="Right click a player to give them a Christmas Cracker!" +collectibles.1397="You've already sent a Christmas Cracker request to %%name%%." +collectibles.1398="You sent %%name%% a Christmas Cracker!" +collectibles.1399="%%name%% has given you a Christmas Cracker!" +collectibles.1400="Waaaaa!" +collectibles.1401="zzzZZZZZZ" +collectibles.1402="GRRRRR!!!" +collectibles.1403="sniff" +collectibles.1404="smiles" +collectibles.1405=":P" +collectibles.1406="B)" +collectibles.1407="winks" +collectibles.1408="Yay!" +collectibles.1409="OMG" +collectibles.1410="Sunny" +collectibles.1411="❤_❤" +collectibles.1412="x_x" +collectibles.1413="Rest In Pepperoni" +collectibles.1414="Phew" +collectibles.1415="Burns!" +collectibles.1416="Deal With It ;)" +collectibles.1417="How fetching!" +collectibles.1418="I'M MELTINGGGG!" +collectibles.1419="❄" +collectibles.1420="It's like you're in Times Square..." +collectibles.1421="It only happens once a year..." +collectibles.1422="Quick, make some resolutions" +collectibles.1423=" Right click a player to ask them "Trick or Treat?"!" +collectibles.1424="You've knocked on too many doors, please wait before doing that again!" +collectibles.1425="You can't knock on this player's door." +collectibles.1426="You've already knocked on %%name%%'s door." +collectibles.1427="You knocked on %%name%%'s door and asked: "Trick or Treat?"" +collectibles.1428="%%name%% asks "Trick or Treat?"" +collectibles.1429="[TRICK] " +collectibles.1430="[TREAT] " +collectibles.1431="[DECLINE] " +collectibles.1432=" You selected %%subType%%!" +collectibles.1433="That player is no longer at your door." +collectibles.1434="Closed the door when %%name%% was trick-or-treating." +collectibles.1435="Nobody has been trick-or-treating at your house, or they already left." +collectibles.1436="%%name%% didn't answer the door when you were trick-or-treating." +collectibles.1437="You didn't answer the door when %%name%% was trick-or-treating." +collectibles.1438="%%name%% selected %%subType%%!" +collectibles.1439="Improper usage." +collectibles.1440="RIGHT CLICK" +collectibles.1441="Season 1 Banner" +collectibles.1442="Your %%color%%%%pet%% ate a %%name%%." +collectibles.1443="Your %%color%%%%pet%% ate an %%name%%." +collectibles.1444="Your %%color%%%%pet%% drank a %%name%%." +collectibles.1445="Your %%color%%%%pet%% drank an %%name%%." +collectibles.1446="Your %%color%%%%pet%% played with a %%name%%." +collectibles.1447="Your %%color%%%%pet%% played with an %%name%%." +collectibles.1448="Reset Banner" +collectibles.1449="shoot arrows" +collectibles.1450="Guardian" +collectibles.1451="Super Happy" +collectibles.1452="Super Happy" +collectibles.1453="Happy" +collectibles.1454="Okay" +collectibles.1455="Reset %%name%%" +collectibles.1456="Spawn the swingiest of swings." +collectibles.1457="Lets you start a hype train! Ride the air and have other players join you by clicking on the train." +collectibles.1458="Players riding your Hype Train: %%count%%" +collectibles.1459="You already have a Pong Ball out!" +collectibles.1460="Players riding %%name%%'s Hype Train: %%count%%" +collectibles.1461="Shoot a pong ball in front of you. The ball can be hit by anyone to send it flying around!" +collectibles.1462="%%player%%'s Pong: %%count%% Hit" +collectibles.1463="%%player%%'s Pong: %%count%% Hits" +collectibles.1464="Final score:" +collectibles.1465="You cannot use gadgets right now!" +collectibles.1466="Right click a player to initiate a game of Rock Paper Shears with them!" +collectibles.1467="Challenge your friends to a Rock Paper Shears game. Who will be the (lucky) winner?" +collectibles.1468="That invite doesn't exist or has expired!" +collectibles.1469="You're already in a game!" +collectibles.1470="Rock Paper Shears - %%target%%" +collectibles.1471="Left: %%name%%" +collectibles.1472="Right: %%name%%" +collectibles.1473="Left side player is %%name%%" +collectibles.1474="Right side player is %%name%%" +collectibles.1475="Your Choice: %%choice%%" +collectibles.1476="Revealing..." +collectibles.1477="Opponent's Choice: %%choice%%" +collectibles.1478="Cruise around the lobby with this special enderpearl!" +collectibles.1479="You picked %%name%%!" +collectibles.1480="%%who%% picked %%name%%!" +collectibles.1481="You won the Rock Paper Shears game against %%opponent%%!" +collectibles.1482="You lost the Rock Paper Shears game." +collectibles.1483="Even game!" +collectibles.1484="You've already invited %%player%% to a game of Rock Paper Shears." +collectibles.1485="You cannot use that skill for %%time%%." +collectibles.1486="Need to congratulate someone on a Good Game, Well Played? Just activate this Clapping Gesture!" +collectibles.1487="Show off your ice cold moves - Own the dancefloor by activating this Cool Dance Gesture!" +collectibles.1488="Feeling proud? Celebrate in style by activating this Victory Pose Gesture!" +collectibles.1489="Whether it's time to go or you're just switching lobbies, bid farewell by activating this Goodbye Gesture!" +collectibles.1490="Overly excited? Feeling crazy? Get rid of all that excess energy - activate this Jump Around Gesture!" +collectibles.1491="Put your arms in the air like you just don't care! Amp yourself up by activating this Hype Dance Gesture!" +collectibles.1492="Close your eyes, nod your head, and move to the music by activating this Wave Dance Gesture!" +collectibles.1493="If you feel like dancing... why not Crab Dance? Woop woop woop your way around the lobby with this Crab Dance Gesture!" +collectibles.1494="Feeling jolly? Celebrate Summer with this Praise the Sun Gesture! If only we could be so grossly incandescent..." +collectibles.1495="You've raided tombs, you've explored uncharted territories, and now you're ready to gather your riches with this Dig for Treasure Gesture!" +collectibles.1496="No, she doesn't want to build a snowman ... and don't tell her to "Let it go!"." +collectibles.1497="As protector of the forest, the wearer of the Wolf Princess Suit can call upon her animal allies." +collectibles.1498="Everything was going swimmingly, until suddenly... CANNONBALL! Show off your aquatic skills with this Diving Board gadget." +collectibles.1499="Gives you Speed II and leaves a trail of blazing fire behind you." +collectibles.1500="You left the Rock Paper Shears game!" +collectibles.1501="Your opponent left the Rock Paper Shears game!" +collectibles.1502="If the name doesn't say enough, this is pretty much just a bomb that explodes, releasing poop everywhere. Yup." +collectibles.1503="This summer's surely warm! Let's all chill throwing water balloons at each other!" +collectibles.1504="Sad you can't play Hypixel all the time? Shed tears with this animated Crying Emote!" +collectibles.1505="Stayed up all night playing your favorite minigame? Fall asleep with this animated Sleepy Emote!" +collectibles.1506="Is something boiling your blood? Let off steam with this animated Rage Emote!" +collectibles.1507="Has something got you down? Let the world know with this animated Frown Emote!" +collectibles.1508="Feeling great? Show the world how happy you are with this animated Smile Emote!" +collectibles.1509="Up to some mischief? Warn everyone how you're feeling with this animated Cheeky Emote!" +collectibles.1510="Feel like the coolest cat on the server? Strut your stuff with this animated Cool Emote!" +collectibles.1511="Having fun? Let someone know you're in on the joke with this animated Wink Emote!" +collectibles.1512="If you are feeling amazing, there's no better way to show it than with this animated Grin Emote!" +collectibles.1513="Has something shocked you!? Let the lobby know with this animated Surprised Emote!" +collectibles.1514="Your Lv %%level%% %%name%% earned %%exp%% EXP from the pet mission! It leveled up!" +collectibles.1515="Your Lv %%level%% %%name%% earned %%exp%% EXP from the pet mission!" +collectibles.1516="He's migrating all the way from the South Pole to your friends list! Collect this cute little Penguin companion today." +collectibles.1517="Throwing snowballs is snow joke! Give someone the cold shoulder with this Winter Gesture." +collectibles.1518="Moustache to Goatee to Epic Beard! Show off how fetching you are with this gentlemanly Moustache Emote!" +collectibles.1519="Give your friends the best gift they could receive this holiday season: YOU! Just activate this Present Unwrap Emote!" +collectibles.1520="In the blink of an eye you vanish, and magically appear somewhere else. Traverse the space-time continuum with this Teleporter gadget." +collectibles.1521="I've sent %%gifts%% gifts!" +collectibles.1522="You cannot use this so close to the spawn point!" +collectibles.1523="Vintage Astrochiever Animated Hat" +collectibles.1524="Points Eater Animated Hat" +collectibles.1525="Unlock Machine Animated Hat" +collectibles.1526="Click to customize outfit!" +collectibles.1527="Rainy Day" +collectibles.1528="It's like a portable shower." +collectibles.1529="Scanner" +collectibles.1530="Bleep Bloop!" +collectibles.1531="Rock Paper Shears" +collectibles.1532="Hype Train" +collectibles.1533="Can't stop this!" +collectibles.1534="Pong" +collectibles.1535="Rush Pearl" +collectibles.1536="Rainy Day Cloak" +collectibles.1537="Scanner Cloak" +collectibles.1538="Rock Paper Shears Gadget" +collectibles.1539="Hype Train Gadget" +collectibles.1540="Pong Gadget" +collectibles.1541="Rush Pearl Gadget" +collectibles.1542="Vintage Astrochiever" +collectibles.1543="Points Eater" +collectibles.1544="Unlock Machine" +collectibles.1545="%%points%%K" +collectibles.1546="Displays how many Achievement Points you have (1K = 1000)." +collectibles.1547="Challenging %%target%%" +collectibles.1548="The Advent Proof" +collectibles.1549="%%count%% Advent Reward Claimed" +collectibles.1550="%%count%% Advent Rewards Claimed" +collectibles.1551="Choose the dark side and oversee the Hypixel Empire from the height of this jolly, snow-filled HP9-B6 robot." +collectibles.1552="HP9-B6" +collectibles.1553="Equipped with an infra-red eye and a stealthy coat of paint, spread the rule of the Hypixel Empire across all lobbies with this upgraded HP9-B companion." +collectibles.1554="HP9-B" +collectibles.1555="Swing Gadget" +collectibles.1556="Swing" +collectibles.1557="Players riding your Hype Train: %%count%%" +collectibles.1558="Crown" +collectibles.1559="Devourer" +collectibles.1560="Wall Crusher" +collectibles.1561="Deal With It Bunny" +collectibles.1562="Achievement Points" +collectibles.1563="Can't use Jetpack gadget!" +collectibles.1564="Can't use grappling hook!" +collectibles.1565="Dread Pirate" +collectibles.1566="Dread Pirate Hat" +collectibles.1567="GingerBread Man" +collectibles.1568="GingerBread Man Hat" +collectibles.1569="You cannot teleport your pet to you, it would get stuck in a block!" +collectibles.1570="You cannot teleport to your pet, you would get stuck in a block!" +collectibles.1571="You cannot do that close to the spawn." +collectibles.1572="Right-Click to provide care\nor remove from Favorites." +collectibles.1573="Right-Click to provide care\nor add to Favorites." +collectibles.1574="Sends all your Happy, Very\nHappy, and Super Happy pets\non a top-secret pet mission\nin order to gain Pet EXP!" +collectibles.1575="Hypixel's Sword" +collectibles.1576="You're still nicknamed as a non-MVP+ so you can't ride pets! Use /unnick to remove your nickname." +collectibles.1577="Hot Potato" +collectibles.1578="Four in a Row" +collectibles.1579="Piggy Bank" +collectibles.1580="This gadget can only be obtained through a promotional offer." +collectibles.1581="Emote" +collectibles.1582="Little You" +collectibles.1583="We all have the little voice inside our head representing the thinking we do and feelings we have. This companion is this little voice, and it looks just like you!" +collectibles.1584="Cloak" +collectibles.1585="A snowball in the face is surely the perfect beginning to a lasting friendship." +collectibles.1586="Your guild had to be top 100 in the legacy guild system!" +collectibles.1587="Unlocked by playing The Pit!" +collectibles.1588="This item is unlocked by participating in tournaments!" +collectibles.1589="Gadget" +collectibles.1590="Morph" +collectibles.1591="Mini Wither" +collectibles.1592="during the Holidays!" +collectibles.1593="This item requires you to be in a Guild that's at least level %%level%%." +collectibles.1594="A stylish way to stand out. In fact, you will stand out so much that everyone around will start hitting you." +collectibles.1595="Archangel Cloak" +collectibles.1596="Avalanche Cloak" +collectibles.1597="Banner" +collectibles.1598="Bleep Bloop! " +collectibles.1599="Boxes you in, one color at a time." +collectibles.1600="Casts spell particles at your feet in the color of your Hypixel '+'. (red by default)" +collectibles.1601="Clouds Particle Pack" +collectibles.1602="Colorbox Cloak" +collectibles.1603="Cosmetic rewards for some of our most competitive players." +collectibles.1604="Crits Particle Pack" +collectibles.1605="Flame Particle Pack" +collectibles.1606="Guild Cloak" +collectibles.1607="Happy about your victory? The Hi-5 Gesture will let you show your appreciation to your mates!" +collectibles.1608="Hat" +collectibles.1609="Impress other players by being showing off your Guild Cloak." +collectibles.1610="Limited Time Pet (No longer available to purchase): Equipped with an infra-red eye and a stealthy coat of paint, spread the rule of the Hypixel Empire across all lobbies with this upgraded HP9-B companion." +collectibles.1611="Magic Particle Pack" +collectibles.1612="Mysterious Cat Banner" +collectibles.1613="Pit Bounty Cloak" +collectibles.1614="Plumber Suit Helmet" +collectibles.1615="Pumpkin Banner" +collectibles.1616="Rank Spell Particle Pack" +collectibles.1617="Rings Particle Pack" +collectibles.1618="Show off your guild's leaderboard position before the 2018 guild update." +collectibles.1619="Snow Particle Pack" +collectibles.1620="Sphere Particle Pack" +collectibles.1621="Suit" +collectibles.1622="Top 100 Guild Cloak" +collectibles.1623="Tornado Particle Pack" +collectibles.1624="Tryhard Banner" +collectibles.1625="???" +collectibles.1626="Challenge your friends to a game of Four in a Row. Who will be the winner?" +collectibles.1627="Comet the Reindeer Animated Hat" +collectibles.1628="Explosion a piggy and get all the gold." +collectibles.1629="Hot, hot, hot!" +collectibles.1630="Hypixel Tournament reward" +collectibles.1631="Joe the Penguin Animated Hat" +collectibles.1632="Mushroom Hat" +collectibles.1633="Place a banner to show off your amazing score in the Turbo Kart Race Grand Prix." +collectibles.1634="Place a banner to show off your position in an event from the Tournament Hall." +collectibles.1635="Play music using your keyboard as a piano!" +collectibles.1636="Sammy the Cookie Animated Hat" +collectibles.1637="TKR Grand Prix reward" +collectibles.1638="Hypixel Sword" +collectibles.1639="Phoenix Suit" +collectibles.1640="Phoenix Suit Helmet" +collectibles.1641="Phoenix Suit Chestplate" +collectibles.1642="Phoenix Suit Leggings" +collectibles.1643="Phoenix Suit Boots" +collectibles.1644="This majestic bird rises from the ashes of its predecessor!" +collectibles.1645="Click to play the resurrection animation from Mega Walls!" +collectibles.1646="Unlocked in the %%season%% Battle Pass." +collectibles.1647="Lovely Cloak" +collectibles.1648="Heart-shaped wings will cover your back!" +collectibles.1649="Evil Cloak" +collectibles.1650="I'm scared!" +collectibles.1651="Holy Cloak" +collectibles.1652="A beautiful flower emerges from your back!" +collectibles.1653="Ping Cloak" +collectibles.1654="Displays your current ping." +collectibles.1655="Crayon Cloak" +collectibles.1656="Your wings will glow in a variety of colors!" +collectibles.1657="Elder Guardian" +collectibles.1658="Sweat Particle Pack" +collectibles.1659="Lava Particle Pack" +collectibles.1660="Four in a Row Gadget" +collectibles.1661="Ducklings Gadget" +collectibles.1662="Spawns 3 ducklings who will follow you around the lobby." +collectibles.1663="Piggy Bank Gadget" +collectibles.1664="Synthesizer Gadget" +collectibles.1665="The Advent Proof Gadget" +collectibles.1666="Duels Season Banner Gadget" +collectibles.1667="TKR Grand Prix Banner Gadget" +collectibles.1668="Tournament Hall Banner Gadget" +collectibles.1669="Click Effects" +collectibles.1670="Become the center of attention by using a click effect! These cosmetics trigger whenever another player clicks you." +collectibles.1671="Crits Click Effect" +collectibles.1672="Just like jump-critting a player, but way more stylish." +collectibles.1673="Coiled Click Effect" +collectibles.1674="Hearts Click Effect" +collectibles.1675="Someone likes you! Little hearts will chase them in return." +collectibles.1676="Zeus Click Effect" +collectibles.1677="Showoff Click Effect" +collectibles.1678="Show off your favorite color! (Based on your %%color%%+ color!)" +collectibles.1679="Headpunch Click Effect" +collectibles.1680="Send your head to space! Maybe someone will need it there?" +collectibles.1681="Eggy Click Effect" +collectibles.1682="Which came first: the chicken or the egg? THE CLICK." +collectibles.1683="Duels Season reward" +collectibles.1684="Sometimes angels are just ordinary people that help us believe in miracles again.\n\nThe trim of this cloak depends on your + color (red by default)." +collectibles.1685="Place a banner to show off your amazing score in a Duels Season." +collectibles.1686="A sweet spiral circles you from toe to head." +collectibles.1687="Click Effect" +collectibles.1688="This item is only available from https://store.hypixel.net/ around December!" +collectibles.1689="Purchased from Halloween Bundle!" +collectibles.1690="Purchased from Easter Bundle!" +collectibles.1691="You don't have any suit pieces to equip!" +collectibles.1692="You equipped 1 piece of the %%suit%%" +collectibles.1693="You equipped %%amount%% pieces of the %%suit%%" +collectibles.1694="Equip Entire Suit" +collectibles.1695="Equip all pieces of the %%name%% that you have unlocked." +collectibles.1696="Bouncy Spider" +collectibles.1697="Killer Rabbit" +collectibles.1698="Spooky Ghost" +collectibles.1699="Ever wanted a spooky companion to scare off other players? Now you can bring along a ghost!" +collectibles.1700="Turn into a spooky ghost!" +collectibles.1701="Ghostly Click Effect" +collectibles.1702="Display a flurry of skulls!" +collectibles.1703="Skull Click Effect" +collectibles.1704="Show your support for our Magma Boss overlord with this suit." +collectibles.1705="Use your ability to spray magma cream and create a ritual pattern on the ground below you." +collectibles.1706="Magma Boss Suit Helmet" +collectibles.1707="Magma Boss Suit Chestplate" +collectibles.1708="Magma Boss Suit Leggings" +collectibles.1709="Magma Boss Suit Boots" +collectibles.1710="Headless Horseman Suit Helmet" +collectibles.1711="Headless Horseman Suit Chestplate" +collectibles.1712="Headless Horseman Suit Leggings" +collectibles.1713="Headless Horseman Suit Boots" +collectibles.1714="Spooky Scary Skeleton Suit Helmet" +collectibles.1715="Spooky Scary Skeleton Suit Chestplate" +collectibles.1716="Spooky Scary Skeleton Suit Leggings" +collectibles.1717="Spooky Scary Skeleton Suit Boots" +collectibles.1718="Treat Fountain" +collectibles.1719="Treat yourself to some Pumpkin Pie, Cake, Golden Apples, and Cookies with this sugary fountain!" +collectibles.1720="Turn the area into a graveyard stirring with ghosts!" +collectibles.1721="Graveyard Gadget" +collectibles.1722="throw wither skulls" +collectibles.1723="leap into the air" +collectibles.1724="Wither Skeleton Morph" +collectibles.1725="Cave Spider Morph" +collectibles.1726="Dark Angel Cloak" +collectibles.1727="Dark Energy Cloak" +collectibles.1728="Release your dark energy by shooting out strings of black magic from your mortal body!" +collectibles.1729="Twisted Cloak" +collectibles.1730="A dark energy spirals around you!" +collectibles.1731="%%player%% ranked #%%rank%% with %%points%% points" +collectibles.1732="Tournament Hall Banners" +collectibles.1733="You need to purchase this banner in order to show off with it!" +collectibles.1734="Use tributes to unlock it in the Tournament Hall when it's open!" +collectibles.1735="You haven't participated in this tournament!" +collectibles.1736="You didn't participate!" +collectibles.1737="Points: %%points%%" +collectibles.1738="Position: #%%pos%%" +collectibles.1739="Click to spawn!" +collectibles.1740="Banner not purchased!" +collectibles.1741="Tournament Banner" +collectibles.1742="Show off your ranking in the %%gametype%% tournament that took place in %%month%% %%year%%." +collectibles.1743="This player can't receive a flower at this time." +collectibles.1744="These dusty wings help the dark angels ascend into the sky for battle!" +collectibles.1745="You can unlock this companion by sending Gifts to other players. Gifts can be purchased on the Hypixel Store: store.hypixel.net!" +collectibles.1746="Summon clones and send them up, up and away." +collectibles.1747="This item is only available from https://store.hypixel.net/ around Easter!" +collectibles.1748="This item is unlocked as a leaderboard reward for tournaments!" +collectibles.1749="was there in December %%year%%" +collectibles.1750="Advent Proof Years" +collectibles.1751="Show off how many Advent Calendar rewards you claimed during the %%year%% season!" +collectibles.1752="%%year%% Advent Proof" +collectibles.1753="Treat Fountain Gadget" +collectibles.1754="The proof that you were there during a holiday season." +collectibles.1755="This item is only available from https://store.hypixel.net/ around Black Friday!" +collectibles.1756="Frozen Skeleton" +collectibles.1757="You tried to punch the skeleton but it froze you instead!" +collectibles.1758="Frozen Zombie" +collectibles.1759="Sellout Cloak" +collectibles.1760="Black Friday, the day (week?) of sales galore." +collectibles.1761="Candy Spiral Cloak" +collectibles.1762="What's better than some sweet treats?" +collectibles.1763="Candy Cane Cloak" +collectibles.1764="The wondrous colors of candy." +collectibles.1765="Sweetwings Cloak" +collectibles.1766="Almost edible." +collectibles.1767="Spooky Scary Skeleton Suit" +collectibles.1768="Dance around as a spooky scary skeleton!" +collectibles.1769="This suit also plays a spooky tune." +collectibles.1770="Spook other players by becoming a Headless Horseman!" +collectibles.1771="Use your ability to mount an undead steed." +collectibles.1772="Yeti Suit" +collectibles.1773="Yeti Suit Helmet" +collectibles.1774="Yeti Suit Chestplate" +collectibles.1775="Yeti Suit Leggings" +collectibles.1776="Yeti Suit Boots" +collectibles.1777="Rawrrrrrrr" +collectibles.1778="Click to throw snowballs at those pesky humans." +collectibles.1779="Elf Suit" +collectibles.1780="Elf Suit Helmet" +collectibles.1781="Elf Suit Chestplate" +collectibles.1782="Elf Suit Leggings" +collectibles.1783="Elf Suit Boots" +collectibles.1784="Ever wanted to be one of Santa's helpers? Now you can!" +collectibles.1785="Click to launch a gift!" +collectibles.1786="Frozen Particle Pack" +collectibles.1787="Tinsel Particle Pack" +collectibles.1788="Snow Trail Particle Pack" +collectibles.1789="Firework Launcher Gadget" +collectibles.1790="It's a time for celebration!" +collectibles.1791="New Year Countdown Gadget" +collectibles.1792="Cornucopia Gadget" +collectibles.1793="Whether the horn of an immortal goat or a river god, this horn is capable of spewing forth unlimited, high-velocity nutrition." +collectibles.1794="Present Click Effect" +collectibles.1795="Who says a present can't be a person?" +collectibles.1796="Holiday Firework Click Effect" +collectibles.1797="Fireworks are appropriate for any time of year!" +collectibles.1798="Make particles appear around you while standing in lobbies using these cool particle effects!" +collectibles.1799="Competitive Showoff" +collectibles.1800="Present Cloak" +collectibles.1801="Arguably the best part of the holidays" +collectibles.1802="Available for a limited time at http://store.hypixel.net/ in a %%event%% Bundle" +collectibles.1803="This item was available in a %%event%% Bundle for a limited time and may return in the future!" +collectibles.1804="Available in a %%event%% Bundle at http://store.hypixel.net/" +collectibles.1805="This item is not currently obtainable!" +collectibles.1806="Artemis Cloak" +collectibles.1807="Mice Gadget" +collectibles.1808="Lunar Particle Pack" +collectibles.1809="This item is available in the Ingame Store for a limited time during our %%event%% event!" +collectibles.1810="This item was available in the Ingame Store for a limited time during our %%event%% event and may return in the future!" +collectibles.1811="Available in the Ingame Store under Limited Items" +collectibles.1812="Spooktacular gadgets that are available during Halloween events!" +collectibles.1813="With the holidays in the air, these gadgets are only available during chilly Holiday events!" +collectibles.1814="While the temperature is high, cool off with these fun gadgets that are available during our Summer events!" +collectibles.1815="With a new lunar year come these gadgets available during our Lunar New Year events!" +collectibles.1816="Spring is upon us and so are our allergies, escape them with these gadgets from our Easter events!" +collectibles.1817="You cannot use gadgets on that player!" +collectibles.1818="Growing Zombie" +collectibles.1819="Buggy Companion" +collectibles.1820="Spring Particle Pack" +collectibles.1821="Rabbit Hat" +collectibles.1822="Easter Egg Hat" +collectibles.1823="Lady Bug Hat" +collectibles.1824="Chocolate Egg Hat" +collectibles.1825="Damage Indicators Click Effect" +collectibles.1826="Chicken Suit" +collectibles.1827="Chicken Suit Helmet" +collectibles.1828="Chicken Suit Chestplate" +collectibles.1829="Chicken Suit Leggings" +collectibles.1830="Chicken Suit Boots" +collectibles.1831="Easter Egg Suit Helmet" +collectibles.1832="Easter Egg Suit Chestplate" +collectibles.1833="Easter Egg Suit Leggings" +collectibles.1834="Easter Egg Suit Boots" +collectibles.1835="Tree Planter Gadget" +collectibles.1836="Planted By" +collectibles.1837="Rabbit Morph" +collectibles.1838="jump super high" +collectibles.1839="Easter Egg Cloak" +collectibles.1840="Monarch Wings Cloak" +collectibles.1841="Swarm Cloak" +collectibles.1842="Halloween" +collectibles.1843="Holiday" +collectibles.1844="Summer" +collectibles.1845="Lunar" +collectibles.1846="Easter" +collectibles.1847="Easter Egg Click Effect" +collectibles.1848="This can be unlocked through a special quest!" +collectibles.1849="Click here to add this pet to your Favorites menu. Favoriting this pet will allow you to spawn and despawn it straight from your inventory." +collectibles.1850="Storm Cloak" +collectibles.1851="School Cloak" +collectibles.1852="Emperor Wings Cloak" +collectibles.1853="Beach Particle Pack" +collectibles.1854="Flying Squid" +collectibles.1855="Bouncy Sheep" +collectibles.1856="%%name%% burnt to a crisp due to a hot potato!" +collectibles.1857="Spooky Wings Cloak" +collectibles.1858="Jack o' Lantern Cloak" +collectibles.1859="Burning Zombie" +collectibles.1860="Smoldering Skeleton" +collectibles.1861="Swarm Gadget" +collectibles.1862="Pumpkin Hat" +collectibles.1863="Cauldron Hat" +collectibles.1864="Jason Hat" +collectibles.1865="Pumpkin Suit Helmet" +collectibles.1866="Pumpkin Suit Chestplate" +collectibles.1867="Pumpkin Suit Leggings" +collectibles.1868="Pumpkin Suit Boots" +collectibles.1869="Skeleton Samurai Helmet" +collectibles.1870="Skeleton Samurai Chestplate" +collectibles.1871="Skeleton Samurai Leggings" +collectibles.1872="Skeleton Samurai Boots" +collectibles.1873="Jack o' Lantern Companion" +collectibles.1874="Currently available!" +collectibles.1875="Currently unavailable!" +collectibles.1876="Name a better time to throw around some pumpkins? I thought not." +collectibles.1877="Click to fire spinning pumpkins around you!" +collectibles.1878="Silent as the shadows, the skeleton samurai roams the lobbies with its bone blades ready." +collectibles.1879="Click to throw a deadly accurate bone knife." +collectibles.1880="As you walk, the fish will follow." +collectibles.1881="Spawn fish in your wake as you walk around the lobby!" +collectibles.1882="Spawn a swarm of spiders to creep out those around you!" +collectibles.1883="Show off your Halloween spirit with this flashing Jack O Lantern that fits on your back!" +collectibles.1884="These wings change color between orange and purple, two of the spookiest colors!" +collectibles.1885="Bring the light show wherever you go, this spooky Jack o' Lantern will light up as it follows you." +collectibles.1886="Celebrate the Hypixel Network with this neat effect that displays the Hypixel logo above your head in a burst of fireworks!" +collectibles.1887="Shines bright in the night. This cloak follows the actual, real-time phase of the Moon!" +collectibles.1888="A bunch of Easter Eggs shoot out of your body." +collectibles.1889="This little buggy friend will buzz around you in lobbies!" +collectibles.1890="Spooky Particle Pack" +collectibles.1891="Crown Banner" +collectibles.1892="Devourer Banner" +collectibles.1893="Wall Crusher Banner" +collectibles.1894="Deal With It Bunny Banner" +collectibles.1895="Portal Banner" +collectibles.1896="Hypixel Sword Banner" +collectibles.1897="Merry Sheep" +collectibles.1898="Grinch Hat" +collectibles.1899="Bell Hat" +collectibles.1900="Snow Globe Hat" +collectibles.1901="Festive Puffer Fish Hat" +collectibles.1902="Festive Zombie Hat" +collectibles.1903="Festive Skeleton Hat" +collectibles.1904="Festive Villager Hat" +collectibles.1905="Festive Squid Hat" +collectibles.1906="Festive Herobrine Hat" +collectibles.1907="Rainbow Present Animated Hat" +collectibles.1908="Blizzard Click Effect" +collectibles.1909="Dreidel Gadget" +collectibles.1910="Blizzard Cloak" +collectibles.1911="Shimmering Wings Cloak" +collectibles.1912="Spout Click Effect" +collectibles.1913="Water will spout out of your head!" +collectibles.1914="Face Cloak" +collectibles.1915="Displays your face!" +collectibles.1916="Ranks Gifted Cloak" +collectibles.1917="Displays how many ranks you have gifted to other players." +collectibles.1918="Piñata Gadget" +collectibles.1919="Dragon Rider Gadget" +collectibles.1920="Ride around on a magnificent Ender Dragon!" +collectibles.1921="There's already someone in the lobby using this gadget." +collectibles.1922="Your dragon must rest!" +collectibles.1923="They don't like it very much." +collectibles.1924="It's their favourite food!" +collectibles.1925="It's their favourite drink!" +collectibles.1926="It's their favourite toy!" +collectibles.1927="You already had the Hot Potato, don't be greedy! :)" +collectibles.1928="You have been given an Enchanted Hot Potato!" +collectibles.1929="Buggy" +collectibles.1930="Little Helper" +collectibles.1931="Cluck cluck, bah-gawk" +collectibles.1932="Click to lay an egg" +collectibles.1933="So many colors, too many to choose from! So why not all of them?" +collectibles.1934="The suit rapidly changes between different Easter Egg designs" +collectibles.1935="Spawns some mice that are hungry! Give them some cheese to make them happy." +collectibles.1936="Piglin Suit" +collectibles.1937="This suit contains all the riches of the world... even the Piglins are after it!" +collectibles.1938="As you walk, shiny items will drop out of you" +collectibles.1939="Rose Cloak" +collectibles.1940="A beautiful rose, given to you by the Hypixel Team!" +collectibles.1941="Sloth Face Cloak" +collectibles.1942="Displays a Sloth Face" +collectibles.1943="Menorah Cloak" +collectibles.1944="A lampstand of pure gold" +collectibles.1945="Clover Cloak" +collectibles.1946="A dewy clover sparking in the sunlight! There's a very rare chance for it to have four leaves..." +collectibles.1947="Prettily decorated easter egg!" +collectibles.1948="Spring represents new beginnings, including butterflies emerging from their cocoons. Display your colorful wings with pride!" +collectibles.1949="Blub" +collectibles.1950="Create a chilly ice skating rink right here in the lobby!" +collectibles.1951="Ice Skating Gadget" +collectibles.1952="Snowball Hat" +collectibles.1953="Stocking Hat" +collectibles.1954="Derpy Snowman Hat" +collectibles.1955="Chicken Banner" +collectibles.1956="Scrambled Egg Banner" +collectibles.1957="Bring the storm whenever someone clicks you." +collectibles.1958="Show detailed facial expressions to all that will watch!" +collectibles.1959="Show off your moves, wave at your friends or more with these fancy gestures!" +collectibles.1960="Impress other players by showing off your guild's level." +collectibles.1961="Fallen Angel Cloak" +collectibles.1962="Showcase your SkyWars Progress with this cloak!" +collectibles.1963="The Emperor Butterfly and its beautiful blue wings." +collectibles.1964="With summer come the storms." +collectibles.1965="Bzzzz" +collectibles.1966="The storms can be brutal, but maybe we'll get a snow day!?" +collectibles.1967="These beautiful wings shimmer in the sunlight, reflecting the light just like snow and ice." +collectibles.1968="Spin and see what you get!" +collectibles.1969="Is this SkyBlock?" +collectibles.1970="This note is on cooldown. It happens when you play too fast!" +collectibles.1971="You challenged %%player%% to a game of Four in a Row." +collectibles.1972="You can't activate Gadgets near parkour plates!" +collectibles.1973="Obtained from Seasonal Fishing" +collectibles.1974="Press 1-8 on your keyboard!" +collectibles.1975="Something went wrong! Please report this." +collectibles.1976="Collectibles are disabled on the alpha server!" +collectibles.1977="This item can only be obtained by VIPs and up through logging in on Valentine's Day!" +collectibles.1978="Opponent's Choice: ???" +collectibles.1979="No one hit anybody! Sad!" +collectibles.1980="You're too high up to use this right now!" +collectibles.1981="Hot Potato" +collectibles.1982="Switch!" +collectibles.1983="Happy Valentine's Day %%year%%!" +collectibles.1984="Keyboard Mode" +collectibles.1985="Click to use!" +collectibles.1986="This can be obtained by fishing in the Main Lobby during seasonal events!" +collectibles.1987=" • Press 1-8 on your keyboard" +collectibles.1988="You're currently nicknamed as a rank that doesn't have access to this pet! Use /unnick to remove your nickname." +collectibles.1989="%%month%% %%year%%" +collectibles.1990="This item can only be unlocked as a reward in a Duels Season." +collectibles.1991="%%player%% has left the Four in a Row game." +collectibles.1992="Loading..." +collectibles.1993="Right-Click to preview" +collectibles.1994="Hit as many players as possible before time runs out!" +collectibles.1995="%%player%% has challenged you to a game of Four in a Row." +collectibles.1996="The Blitz Star effect directly from Blitz. The end is near!" +collectibles.1997="You must be VIP or higher to summon your pets! Purchase it at https://store.hypixel.net" +collectibles.1998="Instructions:" +collectibles.1999="You have been given the enchanted hot potato!" +collectibles.2000="Who knows what your opponent might pick?" +collectibles.2001="Happy St. Patrick's Day %%year%%!" +collectibles.2002="TKR Grand Prix Banner" +collectibles.2003="%%prefix%%Division %%division%% x%%stars%%" +collectibles.2004="Reset your Click Effect" +collectibles.2005="Currently Unavailable" +collectibles.2006="Beats %%what%%" +collectibles.2007="The Snowball Fight has ended!" +collectibles.2008="You have entered the Snowball Fight! Hit as many players as possible before time runs out!" +collectibles.2009="This can be unlocked through a special achievement!" +collectibles.2010="Click here to view your available Cloaks!" +collectibles.2011="Blue" +collectibles.2012="Your opponent has decided and is awaiting your choice." +collectibles.2013="This item can only be unlocked as a reward in the TKR Grand Prix." +collectibles.2014="Lower Octave" +collectibles.2015="You need more dust!" +collectibles.2016=" • Use Q or 9 to switch octave" +collectibles.2017="Click here to view your available Cloaks!" +collectibles.2018="iPixel" +collectibles.2019="Your current pet doesn't support this gadget!" +collectibles.2020="You cannot use abilities in this area!" +collectibles.2021="Originating from Warlords, it literally pushes the ground away from you." +collectibles.2022="Golden" +collectibles.2023="%%points%%ms" +collectibles.2024="MAX EXP" +collectibles.2025="PASS ON THE HOT POTATO!" +collectibles.2026="No Season Banners Available" +collectibles.2027="Spawns a cozy bench for you and your friends!" +collectibles.2028="Cooldown!" +collectibles.2029=" • Keep your mouse on any hotbar quartz" +collectibles.2030="You challenged %%player%% to a game of Rock Paper Shears." +collectibles.2031="Nearby sound will not play when close to spawn!" +collectibles.2032="Snowball (Right-Click)" +collectibles.2033="Duels Season %%season%% Banner" +collectibles.2034="Click here to place your piece in this column." +collectibles.2035="Click here to decline." +collectibles.2036="TOURNAMENT BANNER" +collectibles.2037="You cant use this whilst riding other players!" +collectibles.2038="Orange" +collectibles.2039="Duels Season %%season%%" +collectibles.2040="You have received the Clover Cloak for logging in on St. Patrick's Day!" +collectibles.2041="Allows you to spray fire with a 100% chance of Smokey the Bear crying. Only you can stop forest fires." +collectibles.2042="You must be using Minecraft 1.8 to use this gadget." +collectibles.2043="Can't be unlocked!" +collectibles.2044="Pick a different one!" +collectibles.2045="Instrument" +collectibles.2046="You didn't claim any rewards during that year!" +collectibles.2047="%%player%% defeated you in Four in a Row!" +collectibles.2048="ERRPR" +collectibles.2049="This item is unlocked in The Pit!" +collectibles.2050="Show off the best division you reached in Duels Season %%season%%!" +collectibles.2051="You do not own any Tournament banners! Purchase one in the Tournament Hall." +collectibles.2052="Click!" +collectibles.2053="Keyboard Key" +collectibles.2054="BROKEN" +collectibles.2055="Play with your keyboard!" +collectibles.2056="Unobtainable!" +collectibles.2057="Hypixel Radio" +collectibles.2058="#%%num%%" +collectibles.2059="There is already a Snowball Fight going on in this lobby!" +collectibles.2060="Winning move!" +collectibles.2061="This item can only be obtained by VIPs and up through logging in on St. Patrick's Day!" +collectibles.2062="Upper!" +collectibles.2063="You've already invited %%player%% to a game of Four in a Row." +collectibles.2064="You defeated %%player%% in Four in a Row!" +collectibles.2065="There is already a hot potato gadget in use in this lobby!" +collectibles.2066="You can't use that while morphed!" +collectibles.2067="Keep this hovered!" +collectibles.2068="Right click a player to initiate a game of Four in a Row with them!" +collectibles.2069="No Duels Season Banners are available as no Duels Seasons have finished." +collectibles.2070="Masters Division" +collectibles.2071="You did not reach a high enough Division in Duels Season %%season%% to place this banner!" +collectibles.2072="You tried to punch the skeleton but it blinded you with smoke!" +collectibles.2073="The Four in a Row game with %%player%% ended in a draw." +collectibles.2074="%%player%% has challenged you to a game of Rock Paper Shears." +collectibles.2075="Click here to give a treat." +collectibles.2076="It's their favourite %%type%%!" +collectibles.2077="Upper Octave" +collectibles.2078="You cannot use this here!" +collectibles.2079="This is visible to Admins only!" +collectibles.2080="You have received the Rose Cloak for logging in on Valentine's Day!" +collectibles.2081="You did not reach a high enough division!" +collectibles.2082="Instrument Selector" +collectibles.2083="You're currently nicknamed as a rank that doesn't have access to this gadget! Use /unnick to remove your nickname." +collectibles.2084="Click here to give a trick." +collectibles.2085="Up, Up and Away Gadget" +collectibles.2086="This can be found in the Rotating Items pool in the Hypixel Store!" +collectibles.2087="Hypixel Store Exclusive" +collectibles.2088="Rock" +collectibles.2089="%%winner%% won Four in a Row against %%loser%%!" +collectibles.2090="%%loser%% lost Four in a Row against %%winner%%!" +collectibles.2091="Egg Scanner Cloak" +collectibles.2092="Flaming Egg Launcher Gadget" +collectibles.2093="Bunny Party Gadget" +collectibles.2094="Easter Basket Hat" +collectibles.2095="Chick Hat" +collectibles.2096="Bee Pet" +collectibles.2097="Globe Cloak" +collectibles.2098="Look Mom, I can see the whole world!" +collectibles.2099="Purchased from the In-Game Hypixel Store around Earth Day!" +collectibles.2100="Hypixel Store Earth Day Exclusive" +collectibles.2101="Requires MVP++" +collectibles.2102="You will no longer be affected by lobby gadgets." +collectibles.2103="You will now be affected by lobby gadgets." +collectibles.2104="You are now blocking usage of the Cowboy Gadget on you." +collectibles.2105="You are now allowing the Cowboy Gadget to be used on you." +collectibles.2106="Note: /stopabusingme may still block the gadget" +collectibles.2107="You must be MVP++ to use that! Purchase ranks at https//store.hypixel.net" +collectibles.2108="Reset your Cloak" +collectibles.2109="Portable Pond Gadget" +collectibles.2110="Bring the fish wherever you go!" +collectibles.2111="Golden Pufferfish Hat" +collectibles.2112="Seasoned Fisher Banner" +collectibles.2113="Spider Jockey" +collectibles.2114="Chicken Jockey" +collectibles.2115="Cyclops" +collectibles.2116="Spirit Click Effect" +collectibles.2117="Snowball Cloak" +collectibles.2118="Encases a snowball around you!" +collectibles.2119="Snowman Jockey Pet" +collectibles.2120="Snow Globe Gadget" +collectibles.2121="Celebrate with festive tunes in the lobby!" +collectibles.2122="Present Companion" +collectibles.2123="Customize this floating present to your liking and have it follow you around in the lobby!" +collectibles.2124="Present Companion Skin" +collectibles.2125="Changes the look of your Present Companion!" +collectibles.2126="Changed Present Companion appearance!" +collectibles.2127="Red and Yellow" +collectibles.2128="Green and Aqua" +collectibles.2129="Blue and Magenta" +collectibles.2130="Orange and Blue" +collectibles.2131="Pink and Yellow" +collectibles.2132="Aqua and Green" +collectibles.2133="Purple and Aqua" +collectibles.2134="Purple and Pink" +collectibles.2135="Gray and Purple" +collectibles.2136="Blue and Green" +collectibles.2137="Gold and Purple" +collectibles.2138="Blue and Silver" +collectibles.2139="Pink and Aqua" +collectibles.2140="Black and Green" +collectibles.2141="Purple and Green" +collectibles.2142="Purple and Red" +collectibles.2143="Orange and Green" +collectibles.2144="Yellow and Purple" +collectibles.2145="Silver and Gold" +collectibles.2146="Light Blue and Gold" +collectibles.2147="Blue and Tan" +collectibles.2148="Red and Green" +collectibles.2149="Brown and Blue" +collectibles.2150="Green and Pink" +collectibles.2151="Aqua and Purple" +collectibles.2152="Plumber Suit Chestplate" +collectibles.2153="Plumber Suit Leggings" +collectibles.2154="Plumber Suit Boots" +collectibles.2155="Purchasable from store bundles\nduring the Holidays!" +collectibles.2156="Purchasable from store bundles\nduring Black Friday!" +collectibles.2157="Help the Earth, plant a tree in the lobby!" +collectibles.2158="Reset Favorites?" +collectibles.2159="Blub" +collectibles.2160="Legendary Fisher Banner" +collectibles.2161="Spooky Fisher Banner" +collectibles.2162="Festive Fisher Banner" +collectibles.2163="Spooked Pufferfish Hat" +collectibles.2164="Particle Packs" +collectibles.2165="Harness the power of gods and shock anyone who dares click you." +collectibles.2166="Knock the soul right out of them!" +collectibles.2167="Firefly" +collectibles.2168="Construct a trampoline that shows off your veteran status on the Hypixel Network!" +collectibles.2169="Explode a piggy and get all the gold." +collectibles.2170="Witch's Cauldron Gadget" +collectibles.2171="Bring the alchemy wherever you go!" +collectibles.2172="Spooky Fish Gadget" +collectibles.2173="The fish are flying!" +collectibles.2174="Blast them all!!!" +collectibles.2175="So many bunnies!" +collectibles.2176="Jack O Lantern Cloak" +collectibles.2177="Falling Angel Cloak" +collectibles.2178="Don't crack it!" +collectibles.2179="What do you get if you cross Santa with a duck?" +collectibles.2180="A Christmas Quacker" +collectibles.2181="Who delivers presents to baby sharks at Christmas?" +collectibles.2182="Santa Jaws!" +collectibles.2183="What happened to the man who stole an Advent Calendar?" +collectibles.2184="He got 25 days!" +collectibles.2185="What is the best Christmas present in the world?" +collectibles.2186="A broken drum, you just can't beat it!" +collectibles.2187="Who is Santa's favorite singer?" +collectibles.2188="Elf-is Presley!" +collectibles.2189="Why are Christmas trees so bad at sewing?" +collectibles.2190="They always drop their needles!" +collectibles.2191="Did Rudolph go to school?" +collectibles.2192="No. He was Elf-taught!" +collectibles.2193="What do you get when you cross a snowman with a vampire?" +collectibles.2194="Frostbite!" +collectibles.2195="Where does Frosty keep his money?" +collectibles.2196="In a snowbank." +collectibles.2197="Why was the man afraid of Christmas?" +collectibles.2198="He was Claustrophobic." +collectibles.2199="What does a Snow Golem eat for breakfast?" +collectibles.2200="Snowflakes." +collectibles.2201="When does New Year's Day come before Christmas?" +collectibles.2202="Every year." +collectibles.2203="What did one spice say to the other spice when it walked into the room?" +collectibles.2204="Season's greetings!" +collectibles.2205="What keeps falling but never gets hurt?" +collectibles.2206="Snow." +collectibles.2207="What do you call a snowman on summer vacation?" +collectibles.2208="A puddle." +collectibles.2209="Why does Scrooge love reindeer?" +collectibles.2210="Because every buck is dear to him!" +collectibles.2211="Sneak to lay an egg" +collectibles.2212="Harnest the power of gods and shock anyone who dares click you." +collectibles.2213="Downpour Cloak" +collectibles.2214="Don't forget your umbrella!" +collectibles.2215="Latte Gadget" +collectibles.2216="You cannot activate this while in the parkour!" +collectibles.2217="All the energy you need." +collectibles.2218="Heat Wave Particle Pack" +collectibles.2219="Fish Monger Suit Helmet" +collectibles.2220="Fish Monger Suit Chestplate" +collectibles.2221="Fish Monger Suit Leggings" +collectibles.2222="Fish Monger Suit Boots" +collectibles.2223="This item is unlocked in SkyWars Angel's Descent!" +collectibles.2224="Unlocked by purchasing it in SkyWars Angel's Descent!" +collectibles.2225="Aquarium Cloak" +collectibles.2226="An umbrella won't help you here." +collectibles.2227="Salmon" +collectibles.2228="Even bones hold legends." +collectibles.2229="Dragon Wings Cloak" +collectibles.2230="Spread your wings and fly." +collectibles.2231="Unlocked in the %%festival%% Event Shop!" +collectibles.2232="Snowman Jockey" +collectibles.2233="Rabbit Jockey" +collectibles.2234="This can be obtained from Main Lobby Fishing Rewards!" +collectibles.2235="Obtained from Main Lobby Fishing" +collectibles.2236="Blood" +collectibles.2237="Kinetic" +collectibles.2238="Chicken Suit Leggings" +collectibles.2239="Chicken Suit Boots" +collectibles.2240="Easter Egg Suit" +collectibles.2241="Pumpkin Suit" +collectibles.2242="Pumpkin Suit Chestplate" +collectibles.2243="Fish Monger Suit" +collectibles.2244="Piglin Suit Helmet" +collectibles.2245="Piglin Suit Chestplate" +collectibles.2246="Piglin Suit Leggings" +collectibles.2247="Piglin Suit Boots" +collectibles.2248="You must not be morphed to start the parkour!" +collectibles.2249="Spawn a glorious knight to guard the lobby!" +collectibles.2250="%%player%%'s Knight" +collectibles.2251="Structures" +collectibles.2252="Gadgets that shape the world around you, from trampolines to rockets!" +collectibles.2253="Unleash the sea and send forth a tidal wave in front of you!" +collectibles.2254="%%event%% Cosmetics" +collectibles.2255="View cosmetics available during the %%event%% Event." +collectibles.2256="Certain cosmetics are only available during specific events. View the contents and availability for each event." +collectibles.2257="Blaze Cloak" +collectibles.2258="Unlocked in the %%festival%% Bingo Cards!" +collectibles.2259="Corrupted Gadget" +collectibles.2260="Corrupt the world around you." +collectibles.2261="Pumpkin Rain Gadget" +collectibles.2262="12ft Giant-Sized Skeleton Gadget" +collectibles.2263="You can't use this type of gadget near spawn!" +collectibles.2264="Only %%amount%% of these gadgets can be active at the same time!" +collectibles.2265="%%player%%'s Giant-Sized Skeleton" +collectibles.2266="Makes a spine-tingling centerpiece for Halloween." +collectibles.2267="Let the pumpkins rain!" +collectibles.2268="Snow Click Effect" +collectibles.2269="Rabbit: White (Baby)" +collectibles.2270="Feathered Cloak" +collectibles.2271="Pastel Sheep" +collectibles.2272="Hay Bale" +collectibles.2273="Neeeeeed aaaaaa friennnnnnnnd? Hypixel's favorite animal arrives in the form of this cute Sloth companion!" +collectibles.2274="Enderman: Pumpkin" +collectibles.2275="Specter" +collectibles.2276="Levitation Gun Gadget" +collectibles.2277="Magically pick up blocks and launch them at your friends!" +collectibles.2278="Enderman: Hay Bale" +collectibles.2279="Pig Cannon Gadget" +collectibles.2280="Launch a pig high in the sky while you ride it!" +collectibles.2281="Melon" +collectibles.2282="Golden Chicken Statue Gadget" +collectibles.2283="%%player%%'s Golden Chicken" +collectibles.2284="Just like from the fairytale! Or was that a goose?" +collectibles.2285="Golem: Rose" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/daily_rewards.properties b/configuration/i18n/en_US/official/daily_rewards.properties new file mode 100644 index 000000000..374544319 --- /dev/null +++ b/configuration/i18n/en_US/official/daily_rewards.properties @@ -0,0 +1,76 @@ +daily_rewards.claim_reward="Claim your Reward" +daily_rewards.1="Play award winning minecraft games and mini-games with your friends for free. Only on the Hypixel minecraft server!" +daily_rewards.2="Hypixel Reward Card" +daily_rewards.3="This link either never existed or has already expired." +daily_rewards.4="This service is currently not available, please report this to the team." +daily_rewards.5="Visit the Hypixel Website" +daily_rewards.6="Tablets and mobile devices are currently not supported. Please visit this website with a desktop browser." +daily_rewards.7="Your browser is either outdated or does not support modern web technologies and won't be able to run this website. Please change or upgrade your browser. We do heavily recommend Chrome for the best experience." +daily_rewards.8="Get Chrome" +daily_rewards.9="§a-----------------------------------------------------\n§fYou have claimed a {$color}§l[{$rarity} {$item}] §freward card!\nCheck back tomorrow to claim your next reward, or use\n§eReward Tokens §fat the Delivery Man to try again!\n§a-----------------------------------------------------" +daily_rewards.10="Common" +daily_rewards.11="Epic" +daily_rewards.12="Rare" +daily_rewards.13="Legendary" +daily_rewards.14="Rarity: " +daily_rewards.15="Daily Streak" +daily_rewards.16="After claiming each day for 9 days in a row, you receive +1 Reward Token which gives you one more chance to claim a reward" +daily_rewards.17="Daily Streak Reward" +daily_rewards.18="Current Score: " +daily_rewards.19="High Score: " +daily_rewards.20="Skip" +daily_rewards.21="You can skip this video because of your rank." +daily_rewards.22="Skip these videos by purchasing a rank on our store." +daily_rewards.23="Watch this video for {$seconds}s and claim your reward!" +daily_rewards.24="Watch this video and claim your reward!" +daily_rewards.25="{$game} Coins" +daily_rewards.26="In-game Coins for {$game}" +daily_rewards.27="Mystery Dust" +daily_rewards.28="Used to craft cosmetic items" +daily_rewards.29="Hypixel EXP" +daily_rewards.30="Used to increase your Hypixel Level" +daily_rewards.31="Mystery Box" +daily_rewards.32="Open to unlock cosmetic items!" +daily_rewards.33="SkyWars Souls" +daily_rewards.34="Used with the SkyWars Soul Well" +daily_rewards.35="Gift Box" +daily_rewards.36="Send a Mystery Box to your friends!" +daily_rewards.37="Housing Item" +daily_rewards.38="1 of 6 unique Housing Blocks in this set" +daily_rewards.39="Reward Token" +daily_rewards.40="Each token gives you 1 more go at drawing Reward Cards" +daily_rewards.41="1 of 4 unique cosmetic suit parts" +daily_rewards.42="A unique animated Emote item" +daily_rewards.43="A unique animated Gesture item" +daily_rewards.44="Treasure Hunter Suit" +daily_rewards.45="Helmet" +daily_rewards.46="Leggings" +daily_rewards.47="Boots" +daily_rewards.48="Chestplate" +daily_rewards.49="Moustache Emote" +daily_rewards.50="Dig for Treasure Gesture" +daily_rewards.51="Housing Block" +daily_rewards.52="Housing Block" +daily_rewards.53="Housing Block" +daily_rewards.54="Red Treasure Chest" +daily_rewards.55="Blue Treasure Chest" +daily_rewards.56="Green Treasure Chest" +daily_rewards.57="Gold Nugget" +daily_rewards.58="Pot O' Gold" +daily_rewards.59="Rubik's Cube" +daily_rewards.60="Piggy Bank" +daily_rewards.61="Health Potion" +daily_rewards.62="Coin Bag" +daily_rewards.63="Ornamental Helmet" +daily_rewards.64="Pocket Galaxy" +daily_rewards.65="Mystic Pearl" +daily_rewards.66="Agility Pearl" +daily_rewards.67="Golden Chalice" +daily_rewards.68="Jewelery Box" +daily_rewards.69="Crown" +daily_rewards.70="Molten Core" +daily_rewards.71="Mana Potion" +daily_rewards.72="Help" +daily_rewards.73="Close" +daily_rewards.74="We have detected that you are using an Ad Blocker. To claim your reward, you must disable Ad Blocking on this website." +daily_rewards.75="<h1>HOW IT WORKS</h1>\n\nEach time you claim, 3 cards are drawn at random from our deck. Rewards include minigame coins, Hypixel Experience, Mystery Box items and more! You can left-click to claim 1 of these 3 rewards to receive in-game. Hover over a revealed card to find out more about it.\n\nReward Cards can be Common, Rare, Epic or Legendary rarity level. Common is the least valuable, and Legendary is the most valuable and most difficult to find.\n\nBy default you can claim 1 time per day - the timer resets each day at midnight EST (04:00AM UTC).\n\n<h1>REWARD TOKENS</h1>\n\nYou can use Reward Tokens to claim more rewards - 1 token can be spent at the Delivery Man to let you claim 1 extra time. Reward Tokens can currently be found in cards, and we may add more ways to unlock them across the server.\n\n<h1>DAILY STREAK</h1>\n\nIncluded in the system is a Daily Streak counter. For each day you claim in a row, you build up your streak which is displayed on the Rewards web page. After claiming each day for 9 days in a row, you get 1 free Reward Token, which lets you claim 1 extra time!\n\n<h1>SHARING ON SOCIAL MEDIA</h1>\n\nAfter claiming a card you can share it on Twitter or Facebook by clicking the icons. You can also download the card image for uploading on other websites, or sharing right here on the forums!" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/game_menu.properties b/configuration/i18n/en_US/official/game_menu.properties new file mode 100644 index 000000000..1710546fd --- /dev/null +++ b/configuration/i18n/en_US/official/game_menu.properties @@ -0,0 +1,298 @@ +game_menu.0="Game Menu (Right Click)" +game_menu.1="Right Click to bring up the Game Menu!" +game_menu.2="Game in Progress!" +game_menu.3="➠ Network Booster by %%player%%" +game_menu.4="➠ %%multiplier%%" +game_menu.5="➠ No booster active :(" +game_menu.6="Coins Multiplier: %%multiplier%%x" +game_menu.7="%%amount%% currently playing!" +game_menu.8="Return to the Game Menu." +game_menu.9="Paintball" +game_menu.10="A fast-paced shooter using snowballs." +game_menu.11="One-hit kills and killstreaks are\nguaranteed to keep you awake!" +game_menu.12="The Walls" +game_menu.13="Four teams fight each other for\nvictory after 15 minutes of\npreparation. An excellent game\nfor players who enjoy regular\nMinecraft PvP." +game_menu.14="Blitz Survival Games" +game_menu.15="A free-for-all survival game\nwith kits. Be the first player\nto find the Blitz Star and\nfight your way to victory!" +game_menu.16="VampireZ" +game_menu.17="A Humans vs Vampires game of hide\nand seek. Dying as a Survivor will\nmake you respawn as a Vampire." +game_menu.18="Arcade" +game_menu.19="∙ Galaxy Wars" +game_menu.20="∙ Hole in the Wall" +game_menu.21="∙ The Blocking Dead" +game_menu.22="∙ Farm Hunt" +game_menu.23="∙ Creeper Attack" +game_menu.24="∙ Ender Spleef" +game_menu.25="∙ Bounty Hunters" +game_menu.26="∙ Dragon Wars" +game_menu.27="Quakecraft" +game_menu.28="A fast-paced shooter with railguns." +game_menu.29="Inspired by the popular game\nQuake, this game will test your\ntwitch-shooting skills!" +game_menu.30="Mega Walls" +game_menu.31="An epic 100 player game with fun\nand unique classes. Defeat the\nenemy Withers to prevent\nyour enemies from respawning." +game_menu.32="Cops n' Crims" +game_menu.33="Gun game inspired by the\npopular FPS, Counter-Strike." +game_menu.34="TNT Games" +game_menu.35="Fun minigames with TNT involved!" +game_menu.36="∙ TNT Run" +game_menu.37="∙ PVP Run" +game_menu.38="∙ Bow Spleef" +game_menu.39="∙ TNT Tag" +game_menu.40="∙ TNT Wizards" +game_menu.41="Arena Brawl" +game_menu.42="UHC" +game_menu.43="A team based survival game with 111\nplayers. Randomly generated worlds, \nvanilla PvP, custom crafting, unique kits\nand professions await you." +game_menu.44="Warlords" +game_menu.45="SkyWars" +game_menu.46="Hypixel's take on the Skywars gamemode." +game_menu.47="Featuring the Angel of Death,\nSoul Well and INSANE MODE!" +game_menu.48="Play on your own or in teams." +game_menu.49="Pixel Painters" +game_menu.50="Paint a masterpiece based on a theme!" +game_menu.51="Use a variety of tools to make the most\ncreative picture! Win the vote of\nother players to claim victory!" +game_menu.52="Build Battle" +game_menu.53="Turbo Kart Racers" +game_menu.54="Compete against 11 other\nracers in a dash to the first!" +game_menu.55="Customize your kart and use\nitems to be the best." +game_menu.56="Player Housing" +game_menu.57="Customize and build on your own\npersonal plot, hang out with\nyour friends, visit other people's\nhouses, and more!" +game_menu.58="Crazy Walls" +game_menu.59="16 players or teams battle across\ntwo gamemodes. Mine, Build & Trade\nbefore the sets of walls drop\nand be the last man standing!" +game_menu.60="The Lucky Block mode throws an\nelement of chaos into the mix!" +game_menu.61="Super Smash" +game_menu.62="Become one of many unique heroes\nand unleash devastating attacks in\na Team or Solo battle for ultimate\ndomination! Can you SMASH your rivals\nout of the arena before they smash you?" +game_menu.63="Football" +game_menu.64="It's Football (Soccer), you should\nknow how to play this!" +game_menu.65="Speed UHC" +game_menu.66="A fast-paced twist on the popular\nUHC gamemode." +game_menu.67="Featuring Tears, Salt, and the Nether!" +game_menu.68="Play on your own or in teams." +game_menu.69="Mini Walls" +game_menu.70="4 teams of 4 battle it out in this\nfast-paced PvP Arcade game!" +game_menu.71="Choose 1 of 3 kits & protect your\nMini Wither to keep respawning." +game_menu.72="Games last less than 5 minutes!" +game_menu.73="CLOSED BETA" +game_menu.74="POPULAR!" +game_menu.75="OPEN BETA" +game_menu.76="NEW GAME!" +game_menu.77="NEW!" +game_menu.78="Survival" +game_menu.79="Competitive" +game_menu.80="Team Survival" +game_menu.81="Shooter" +game_menu.82="Casual Games" +game_menu.83="Hardcore Survival" +game_menu.84="Domination" +game_menu.85="Featured Arcade Game" +game_menu.86="Special Event" +game_menu.87="Housing" +game_menu.88="Racing" +game_menu.89="NEW UPDATE!" +game_menu.90="Get the most votes out of 16 players to win!" +game_menu.91="Christmas Build Battle" +game_menu.92="Love Build Battle? Create over\n100 festive themes in this new,\ntime limited, Christmas version!" +game_menu.93="Grinch Simulator" +game_menu.94="Ruin everyone's Christmas by\nstealing the most presents in this\nparkour-inspired collect-a-thon.\nSteal more presents than any\nother Grinch to win!" +game_menu.95="Prototype" +game_menu.96="Crazy fun minigames to play\nwith friends!" +game_menu.97="WARNING!\nThis is a true hardcore experience, \nnot recommended for new players." +game_menu.98="Play as a Mage, Warrior, Shaman\nor Paladin in Capture the Flag or\nDomination gamemodes.\nParticipate in epic PvP battles like\nyou've never seen before with custom\n3D weapons, class helms and much more!" +game_menu.99="PTL is a place for testing fun\nand creative new minigames\nand systems on Hypixel." +game_menu.100="Hypixel Level %%level%%" +game_menu.101="UHC Champions" +game_menu.102="Bed Wars" +game_menu.103="Zombies" +game_menu.104="Protect your bed along with\nyour teammates and destroy\nenemy beds to win!" +game_menu.105="Work with your teammates to\nfight hoards of zombies and\nother undead enemies! Survive\nas long as possible." +game_menu.106="The Classic Lobby is the hub for all Classic\nHypixel minigames, including:" +game_menu.107="∙ VampireZ" +game_menu.108="∙ Quakecraft" +game_menu.109="∙ Paintball Warfare" +game_menu.110="∙ Arena Brawl" +game_menu.111="∙ The Walls" +game_menu.112="∙ Turbo Kart Racers" +game_menu.113="Murder Mystery" +game_menu.114="∙ Duels" +game_menu.115="∙ Murder Mystery" +game_menu.116="∙ Zombies" +game_menu.117="Smash Heroes" +game_menu.118="Cops and Crims" +game_menu.119="∙ Party Games 1 / 2 / 3" +game_menu.120="∙ Hypixel Says" +game_menu.121="∙ Pixel Painters" +game_menu.122="∙ Throw Out" +game_menu.123="∙ Football" +game_menu.124="∙ Mini Walls" +game_menu.125="RELEASED!" +game_menu.126="1 Murderer. 1 Detective.\nAnd a whole lot of Innocents.\nCan you survive this tense social\ngame of betrayal and murder?" +game_menu.127="NEW PTL GAME!" +game_menu.128="Arcade Games" +game_menu.129="The TNT Games" +game_menu.130="∙ Build Battle" +game_menu.131="More games will be added soon!" +game_menu.132="Coming soon" +game_menu.133="UPDATED!" +game_menu.134="Create a build based on a theme\nin just 5 minutes! Vote on competing\nbuilds with ratings ranging from \n"Super Poop" to "Legendary"" +game_menu.135="∙ Blitz Duels" +game_menu.136="∙ TNT Games Duels" +game_menu.137="∙ Sumo Duels" +game_menu.138="Quick paced 1v1, 2v2, 4v4 and Tournament Duels!" +game_menu.139="∙ King of the Hill" +game_menu.140="A team based survival game with 111 players. Randomly generated worlds, vanilla PvP, custom crafting, unique kits and professions await you." +game_menu.141="Protect your bed along with your teammates and destroy enemy beds to win!" +game_menu.142="Create a build based on a theme in just 5 minutes! Vote on competing builds with ratings ranging from "Super-Poop" to "Legendary"." +game_menu.143="Fight in teams to cross The Bridge and score goals. First team to 5 goals wins!" +game_menu.144="4 teams of 4 battle it out in this fast-paced PvP Arcade game!" +game_menu.145="Choose 1 of 3 kits & protect your Mini Wither to keep respawning." +game_menu.146="Games last less than 5 minutes!" +game_menu.147="Gun game inspired by the popular FPS, Counter-Strike." +game_menu.148="1 Murderer. 1 Detective.\nAnd a whole lot of Innocents.\nCan you survive this tense social game of betrayal and murder?" +game_menu.149="An epic 100 player game with fun and unique classes. Defeat the enemy Withers to prevent your enemies from respawning." +game_menu.150="Customize and build on your own personal plot, hang out with your friends, visit other people's houses, and more!" +game_menu.151="Featuring the Angel of Death, Soul Well and INSANE MODE!" +game_menu.152="PTL is a place for testing fun and creative new minigames and systems on Hypixel." +game_menu.153="∙ Capture The Wool" +game_menu.154="∙ The Pit" +game_menu.155="Become one of many unique heroes and unleash devastating attacks in a Team or Solo battle for ultimate domination! Can you SMASH your rivals out of the arena before they smash you?" +game_menu.156="A fast-paced twist on the popular UHC gamemode." +game_menu.157="Featuring Tears, Salt, and the Nether!" +game_menu.158="Play as a Mage, Warrior, Shaman or Paladin in Capture the Flag or Domination gamemodes." +game_menu.159="Participate in epic PvP battles like you've never seen before with custom 3D weapons, class helms and much more!" +game_menu.160="16 players or teams battle across two gamemodes. Mine, Build & Trade before the sets of walls drop and be the last man standing!" +game_menu.161="The Lucky Block mode throws an element of chaos into the mix!" +game_menu.162="Quick paced 1v1, 2v2, 4v4 and Tournament Duels!" +game_menu.163="∙ The Bridge" +game_menu.164="Work with your teammates to fight hoards of zombies and other undead enemies! Survive as long as possible." +game_menu.165="Jump down The Pit to instantly fight with over 50 other players." +game_menu.166="The most fast-paced combat on Hypixel." +game_menu.167="Get on the Hill in the middle of the map and earn points for your team!" +game_menu.168="The Classic Lobby is the hub for all Classic Hypixel minigames, including:" +game_menu.169="Four teams fight each other for victory after 15 minutes of preparation. An excellent game for players who enjoy regular Minecraft PvP." +game_menu.170="One-hit kills and killstreaks are guaranteed to keep you awake!" +game_menu.171="A Humans vs Vampires game of hide and seek. Dying as a Survivor will make you respawn as a Vampire." +game_menu.172="Compete against 11 other racers in a dash to the first!" +game_menu.173="Customize your kart and use items to be the best." +game_menu.174="Inspired by the popular game Quake, this game will test your twitch-shooting skills!" +game_menu.175="Blend in with AI-controlled NPCs and avoid detection to complete objectives in this tense game of social deduction." +game_menu.176="We don't even know what is real any more!" +game_menu.177="Hide and Seek" +game_menu.178="King of the Hill" +game_menu.179="The Pit" +game_menu.180="The Bridge" +game_menu.181="Blitz SG" +game_menu.182="Duels" +game_menu.183="TOWERWARS!" +game_menu.184="NEW ITEM!" +game_menu.185="NEW LOBBY!" +game_menu.186="➠ Double Coins + EXP Weekend" +game_menu.187="TowerWars" +game_menu.188="Tower Defense" +game_menu.189="Return to the Main Lobby" +game_menu.190="Lobby open!" +game_menu.191="NEW UHC MODE!" +game_menu.192="NEW TEAM MODE!" +game_menu.193="Place towers and summon monsters as you earn income to defeat 5 other players!" +game_menu.194="%%purple%%NEW MODE!" +game_menu.195="NEW UPDATE!" +game_menu.196="Persistent Game" +game_menu.197="SkyBlock" +game_menu.198="The Hypixel Pit" +game_menu.199="SkyBlock has finally arrived on Hypixel! Play with friends (or solo!), build your private islands and collect all the items! " +game_menu.200="Jump down The Pit to instantly fight with over 50 other players. The most fast-paced combat on Hypixel." +game_menu.201="Hypixel's take on the SkyWars gamemode. Featuring the Angel of Death, Soul Well and INSANE MODE! Play on your own or in teams." +game_menu.202="1 Murderer. 1 Detective. And a whole lot of Innocents. Can you survive this tense social game of betrayal and murder?" +game_menu.203="Crazy fun minigames to play with friends!" +game_menu.204="Create a build based on a theme in just 5 minutes! Vote on competing builds with ratings ranging from "Super-Poop" to "Legendary". Get the most votes out of 16 players to win!" +game_menu.205="Quick paced 1v1, 2v2, 4v4!" +game_menu.206="∙ UHC Deathmatch" +game_menu.207="∙ SkyBlock" +game_menu.208="∙ TowerWars" +game_menu.209="Play as a Mage, Warrior, Shaman or Paladin in Capture the Flag or Domination gamemodes. Participate in epic PvP battles like you've never seen before with custom 3D weapons, class helms and much more!" +game_menu.210="16 players or teams battle across two gamemodes. Mine, Build & Trade before the sets of walls drop and be the last man standing! The Lucky Block mode throws an element of chaos into the mix!" +game_menu.211="∙ Party Games" +game_menu.212="∙ Hide and Seek" +game_menu.213="Join a game of %%mode%%" +game_menu.214="Solo" +game_menu.215="Doubles" +game_menu.216="3v3v3v3" +game_menu.217="4v4v4v4" +game_menu.218="Solo Normal" +game_menu.219="Solo Insane" +game_menu.220="Doubles Normal" +game_menu.221="Doubles Insane" +game_menu.222="Ranked" +game_menu.223="Mega Doubles" +game_menu.224="Creeper Attack" +game_menu.225="Farm Hunt" +game_menu.226="Zombies: Dead End" +game_menu.227="Zombies: Bad Blood" +game_menu.228="Zombies: Alien Arcadium" +game_menu.229="Hide and Seek: Prop Hunt" +game_menu.230="Hide and Seek: Party Pooper" +game_menu.231="Hypixel Says" +game_menu.232="Blocking Dead" +game_menu.233="Hole In The Wall" +game_menu.234="Bounty Hunters" +game_menu.235="Dragon Wars" +game_menu.236="Ender Spleef" +game_menu.237="Galaxy Wars" +game_menu.238="Throw Out" +game_menu.239="Solo Mode" +game_menu.240="Teams Mode" +game_menu.241="Pro Mode" +game_menu.242="Guess The Build" +game_menu.243="Bow Duel" +game_menu.244="Classic Duel" +game_menu.245="Potion Duel" +game_menu.246="Combo Duel" +game_menu.247="Blitz Duel" +game_menu.248="Bow Spleef Duel" +game_menu.249="Sumo Duel" +game_menu.250="Teams of 3" +game_menu.251="TNT Run" +game_menu.252="PVP Run" +game_menu.253="Bow Spleef" +game_menu.254="TNT Tag" +game_menu.255="Wizards" +game_menu.256="Standard" +game_menu.257="Defusal" +game_menu.258="Team Deathmatch" +game_menu.259="1v1v1v1" +game_menu.260="2v2" +game_menu.261="2v2v2" +game_menu.262="1v1" +game_menu.263="Capture the Flag" +game_menu.264="Solo Lucky" +game_menu.265="Teams Normal" +game_menu.266="Teams Lucky" +game_menu.267="Click to Open" +game_menu.268="Join a random game." +game_menu.269="Random Game" +game_menu.270="BETA" +game_menu.271="View icons available for %%game%%" +game_menu.272="Select Game Menu Icon" +game_menu.273="Reset ALL custom slots back to their default." +game_menu.274="Your Game Menu custom slots have been reset to their defaults!" +game_menu.275="Click to Connect" +game_menu.276="Lobby Open!" +game_menu.277="Everything in this lobby is currently in development, and may be removed at any time." +game_menu.278="Right Click to change this slot!" +game_menu.279="A fast-paced twist on the popular UHC gamemode, featuring the Nether! Play on your own or in teams." +game_menu.280="∙ Capture the Wool" +game_menu.281="A team or solo survival game with kits. Be the first player to find the Blitz Star and fight your way to victory!" +game_menu.282="Wool Wars" +game_menu.283="Hypixel SMP" +game_menu.284="Create your own SMP server on Hypixel and play with friends." +game_menu.285="∙ OP Duels" +game_menu.286="∙ Boxing Duels" +game_menu.287="∙ Parkour Duels" +game_menu.288="Face Off" +game_menu.289="A competitive PvP game. Create your\nown class by selecting your favorite\nskills and then queue for either\n2v2 or 4v4 team matches." +game_menu.290="A competitive PvP game. Create your own class by selecting your favorite skills and then queue for either 2v2 or 4v4 team matches." +game_menu.291="Sheep Wars" +game_menu.292="Capture the Wool" +game_menu.293="Wool Wars (Tournament)" +game_menu.294="Wool Games" +game_menu.295="A series of team-based PvP games with wool as the theme!" +game_menu.296="∙ Disasters" +game_menu.297="From a zombie apocalypse to meteor showers, work alone or with friends to survive!" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/general.properties b/configuration/i18n/en_US/official/general.properties new file mode 100644 index 000000000..9fe97ea81 --- /dev/null +++ b/configuration/i18n/en_US/official/general.properties @@ -0,0 +1,5568 @@ +general.0="The game starts in %%time%% seconds!" +general.1="The game starts in %%time%% second!" +general.2="%%player%% has joined (%%count%%)!" +general.3="Right Click" +general.4="Click to Connect" +general.5="Coming soon!" +general.6="Cancel" +general.7="Confirm" +general.8="Closes this menu." +general.9="Are you sure?" +general.10="Click to purchase!" +general.11="Rarity: %%rarity%%" +general.12="Cost: %%cost%%" +general.13="Requires Hypixel Level %%level%%" +general.14="SELECTED!" +general.15="Click to select!" +general.16="There are no players to spectate!" +general.17="Teleporter" +general.18=" (Page %%page%%)" +general.19="Page %%page%%" +general.20="Spectator Settings" +general.21="No Speed" +general.22="You no longer have any speed effects!" +general.23="Speed %%tier%%" +general.24="You now have Speed %%tier%%!" +general.25="You can now see other spectators!" +general.26="You can no longer see other spectators!" +general.27="Show Spectators" +general.28="Click to show other spectators!" +general.29="Hide Spectators" +general.30="Click to hide other spectators!" +general.31="You no longer have night vision!" +general.32="You now have night vision!" +general.33="Disable Night Vision" +general.34="Click to disable night vision!" +general.35="Enable Night Vision" +general.36="Click to enable night vision!" +general.37="You will no longer auto teleport to targets!" +general.38="Once you select a player using your compass, it will auto teleport you to them!" +general.39="Disable Auto Teleport" +general.40="Click to disable auto teleport!" +general.41="Enable Auto Teleport" +general.42="Click to enable auto teleport!" +general.43="You are now able to stop flying!" +general.44="You are no longer able to stop flying!" +general.45="Disable Always Flying" +general.46="Click to disable always flying!" +general.47="Enable Always Flying" +general.48="Click to enable always flying!" +general.49="Target: " +general.50="HP: " +general.51="Class: " +general.52="Distance: " +general.53="Teleporter (Right Click)" +general.54="Right-click to spectate players!" +general.55="Target Lost (Right Click)" +general.56="Return to Lobby (Right Click)" +general.57="Right-click to leave to the lobby!" +general.58="Spectator Settings (Right Click)" +general.59="Right-click to change your spectator settings!" +general.60="Play Again (Right Click)" +general.61="Right-click to play another game!" +general.62="All Players" +general.63="Click to show all players!" +general.64="You have already chosen that blood effect." +general.65="You have disabled blood effects." +general.66="You have selected the %%name%% blood effect." +general.67="Disguised as a %%entityType%%!" +general.68="Particle quality set to %%qualityType%%!" +general.69="Disabled particles!" +general.70="You already have that quality level selected!" +general.71="%%frame%%" +general.72="Read full story: %%frame%%" +general.73="Read full story: [link]" +general.74="An error occurred in the system! Try again." +general.75="Since you are VIP, you can create a Guild using /guild create (name)" +general.76="You can join a Guild regardless of your rank. Browse Guilds:" +general.77="%%underline%%http://hypixel.net/forums/59" +general.78="%%DEFAULT%%%%msg%%" +general.79="Failed to open inventory, an error has occurred!" +general.80="Combat Mode activated!" +general.81="Wait %%color%%%%countdown%%s..." +general.82="Combat Mode deactivated!" +general.83="Combat Mode cancelled!" +general.84="Teleported you to %%newPlayer%%!" +general.85="Teleport cancelled!" +general.86="Teleporting you to the lobby in 3 seconds... Right-click again to cancel the teleport!" +general.87="Hmm, seems there was an error creating the song player :(" +general.88="You already have that gun equipped!" +general.89="Equipping %%gun%%!" +general.90="Missing Parts: %%parts%%" +general.91="Reset your %%name%%!" +general.92="You don't have any %%name%% equipped!" +general.93="You've already purchased that!" +general.94="You already have that equipped!" +general.95="You don't have enough coins!" +general.96="Missing arguments! Pick a mob!" +general.97="Car not found!" +general.98="Go! Go! Go!!!!!" +general.99="No Particles" +general.100="Disables all particles. Not recommended unless needed!" +general.101="Low Quality" +general.102="Heavily reduces the amount of particles you will see." +general.103="Medium Quality" +general.104="Reduces the amount of particles seen." +general.105="High Quality" +general.106="Shows all particles for the best experience." +general.107="Click to select" +general.108="SELECTED" +general.109="Particle Quality" +general.110="Particle Quality" +general.111="Allows you to control, or disable, particles and the amount of them." +general.112="Possible Values: %%values%%" +general.113="Not Found. Possible Values: %%values%%" +general.114="Maximum Particles per Tick now: %%amount%%" +general.115="Guild Information" +general.116="You are not currently in a Guild." +general.117="Click to learn more!" +general.118="Name: %%name%%" +general.119="Guild Rank: %%rank%%" +general.120="Daily Limit: %%coins%%/%%max%%" +general.121="Daily Limit resets in %%timer%%" +general.122="Members: %%members%%/%%max%%" +general.123="Rank: %%rank%%" +general.124="Default" +general.125="Level: %%level%%" +general.126="Experience until next Level: %%exp%%" +general.127="Achievement Points: %%points%%" +general.128="Karma: %%karma%%" +general.129="Click to see the Hypixel Store link." +general.130="Character Information" +general.131="Total Coins: %%coins%%" +general.132="Coins: %%coins%%" +general.133="Shop (Right Click)" +general.134="1st Place - %%player%%" +general.135="2nd Place - %%player%%" +general.136="3rd Place - %%player%%" +general.137="Winner: %%player%%" +general.138="Winning Team: %%team%%" +general.139="Active Booster" +general.140="%%name%%'s Network Booster" +general.141="%%prefix%%%%amount%% coins" +general.142="+%%amount%% coins" +general.143="Repairing" +general.144="Combat Mode VIP ONLY!" +general.145="Hold for %%time%% seconds to activate combat mode." +general.146="This allows you to fight other players." +general.147="Requires %%rank%%or higher to use!" +general.148="Purchase %%rank%% at https://store.hypixel.net" +general.149="Combat Mode (Hold & Wait)" +general.150="Hold for 5 seconds to activate combat mode." +general.151="The game is starting within %%time%% seconds!" +general.152="To leave %%game%%, type /lobby" +general.153="We don't have enough players! Start cancelled." +general.154="%%player%% has quit!" +general.155="Map: %%world%%" +general.156="Players: %%size%%/%%max%%" +general.157="Waiting..." +general.158="Starting in %%time%%s" +general.159="Started!" +general.160="Server: %%server%%" +general.161="Are you AFK? You could be kicked for AFKing!" +general.162="You were kicked for being AFK in a game!" +general.163="You have already unlocked this tier!" +general.164="Reloading..." +general.165="Done!" +general.166="An error occurred." +general.167="You already have a booster active!" +general.168="Booster use aborted." +general.169="You don't have any %%gameType%% Boosters to activate!" +general.170="You already have a %%gameType%% Booster active!" +general.171="You don't have any Network Boosters to activate!" +general.172="You already have a Network Booster active!" +general.173="Aborted booster activation." +general.174="You are not allowed to use commands as a spectator!" +general.175="We couldn't find a player to teleport you to!" +general.176="You were teleported to %%PlayerManager%%" +general.177="Sending you to %%session%%!" +general.178="No game to rejoin. This usually happens when the last game you played has already ended and is nothing to worry about." +general.179="Overall Rating" +general.180="Overall Wins" +general.181="Overall Kills" +general.182="Monthly Kills" +general.183="Weekly Kills" +general.184="Couldn't find any leaderboard data." +general.185="This command can only be used in minigames or minigame lobbies." +general.186="This command is only available in lobbies!" +general.187="Sorry, that isn't a valid username!" +general.188="I couldn't find a player by that name!" +general.189="Click to execute /resource to get the resource pack!" +general.190="The Hypixel Leveling Menu is currently disabled. Check back soon!" +general.191="You must be %%rank%% to use this command!" +general.192="Quest Completed: Space Mission" +general.193="You received: 1875 experience" +general.194="Click to see Hypixel Level rewards" +general.195="Friends" +general.196="An error occurred please notify an administrator." +general.197="Loading..." +general.198="No friends?" +general.199="Use /friend add to add friends!" +general.200="Previous Page" +general.201="Next Page" +general.202="Please try again in a moment!" +general.203="Loading, please wait..." +general.204="Something went wrong handling that!" +general.205="You must be in a guild to use this!" +general.206="You must be the Guild Master to use this!" +general.207="Purchase" +general.208="Abort" +general.209="Activates the item listed above. Cannot be undone." +general.210="Closes this menu." +general.211="30 minutes!" +general.212="1 hour!" +general.213="3 hours!" +general.214="??? hours!" +general.215="%%purchaser%% activated triple coins for %%length%%" +general.216="Gain extra Karma by doing /tip and /thanks on that player!" +general.217="%%purchaser%%'s Network Booster expired!\nNetwork Boosters are available at http://store.hypixel.net/" +general.218="Click to go to the next page!" +general.219="Click to go to the previous page!" +general.220="Game Menu" +general.221="Click to open the Game Menu!" +general.222="Main" +general.223="Adventure" +general.224="Lobby Selector" +general.225="Offline!" +general.226="%%name%% Lobby #%%number%%" +general.227="Players: %%players%%/%%max%%" +general.228="Already connected!" +general.229="You are already in %%name%% Lobby #%%number%%" +general.230="Online Friends:" +general.231="Full!" +general.232="That lobby is currently full!" +general.233="Click to connect!" +general.234="%%name%% Lobby #%%number%%" +general.235="The party is full!" +general.236="Something went wrong. Please try again." +general.237="An error occurred while handling your sign click. Please try again." +general.238="You are trying to do that too fast. Try again in a moment." +general.239="The queue is offline at the moment. Try again in a second!" +general.240="That sign doesn't have a map! Try another!" +general.241="Please slow down!" +general.242="Coming soon!" +general.243="Map Selector" +general.244="You are playing on MC.HYPIXEL.NET" +general.245="You've already claimed that reward!" +general.246="You can't claim that reward!" +general.247="Something went wrong, try again in a moment!" +general.248="Please wait for us to finish reloading your player!" +general.249="You haven't unlocked (or claimed) that yet!" +general.250="You already have that selected!" +general.251="Selected!" +general.252="You are no longer a horse" +general.253="There are currently no voting sessions open!" +general.254="Could not find a target for you to vote for! Have you been voting for us outside of your session?" +general.255="That delivery has expired!" +general.256="You have already claimed this delivery!" +general.257="Purchase it at http://store.hypixel.net" +general.258="That delivery hasn't arrived yet! Check back later!" +general.259="You're currently invalidating! Try again in a second!" +general.260="Error! No state found!" +general.261="Something went wrong!" +general.262="Your data is currently being updated! Please wait just a second and try again!" +general.263="You have already looted this delivery! Check back in %%EugeneUtils%%!" +general.264="Report this to staff: PAS:%%e%%" +general.265="Report this to staff: RTP:%%e%%" +general.266="Report this to staff: INV:%%e%%" +general.267="You do not have the rank required for this bonus! Purchase ranks at http://store.hypixel.net" +general.268="You've already received this reward!" +general.269="Something went wrong executing that. Please try again in a moment!" +general.270="There is no survey open for this week yet, or there is not one planned! Check back soon!" +general.271="There is no survey open for this week! This should typically not be seen! If not yet done so, contact an administrator!" +general.272="You do not have an open survey! Next Delivery: %%delivery%%" +general.273="Something weird internally happened!" +general.274="Question: %%data%%" +general.275=" (Click an option below)" +general.276="Do not use this command without accessing it though the delivery man." +general.277="You're not eligible to do this action, try again in %%cooldown%%." +general.278="Answered survey with response "%%response%%"! You have received 15,000 XP and 5,000 Arcade Coins!" +general.279="This reward doesn't work for this lobby!" +general.280="You're invalidating, try again in a second!" +general.281="More deliveries may have just arrived! Check it out!" +general.282="New Packages have just arrived!" +general.283="%%data%%" +general.284=" %%response%%. %%response%%" +general.285="Week: %%data%% | ID: %%data%%" +general.286="Survey not found!" +general.287="The Delivery Man is currently disabled! Check back later!" +general.288="Today's voting link is %%url%%" +general.289="Click here to go to the voting site!" +general.290="Follow the instructions on the website to redeem 5,000 XP and 3,000 Arcade Coins!" +general.291="Click to loot!" +general.292="This delivery arrives in %%arrive%%" +general.293="Expires in %%time%%" +general.294="Click to claim delivery!" +general.295="Summer" +general.296="Requires %%rank%%" +general.297="You already picked up this delivery, come back later!" +general.298="Click to loot!" +general.299="Survey Question" +general.300="This weeks survey isn't open just yet! Hang in there pal!" +general.301="Weekly survey answered!" +general.302="Click to open answers!" +general.303="Click to respond with %%response%% as your answer!" +general.304="Invalid choice!" +general.305="%%amount%% Delivery! " +general.306="%%amount%% Deliveries! " +general.307="%%amount%% Delivery! " +general.308="%%amount%% Deliveries! " +general.309="There are no sessions currently available! Check back soon!" +general.310="You're done for the day!\nNext Delivery: %ttn!" +general.311="Do not ride a vehicle" +general.312="Do not fly" +general.313="This feature has been disabled." +general.314="You must be %%rank% to join this server." +general.315="Get free coins by clicking on this message" +general.316="You are currently playing on %%name%%" +general.317="You were given 15,000 EXP for linking your website account!" +general.318="You have %%amount%% unclaimed leveling reward!" +general.319="Click here to view it!" +general.320="You have %%amount%% unclaimed leveling rewards!" +general.321="Click here to view them!" +general.322="You are currently muted for %%reason%% for %%time%%." +general.323="You are currently muted for %%time%%." +general.324="You will now see chat!" +general.325="You will no longer see chat!" +general.326="You don't have permission to use this command!" +general.327="You haven't liked us on Facebook! If you have, log out and back in again!" +general.328="You were awarded 250 coins in all games for liking us on Facebook!" +general.329="Invalid code! If you just liked us, log out and back in again!" +general.330="You are not allowed to do this!" +general.331="Turned global chat on!" +general.332="Turned global chat off!" +general.333="Turned all chat on!" +general.334="Turned all chat off!" +general.335="You are now OP." +general.336="You are no longer OP." +general.337="/myfilter add (word) - Adds a word to your filter." +general.338="/myfilter remove (word) - Removes a word from your filter." +general.339="/myfilter list - Lists all words on your filter." +general.340="/myfilter clear - Clears all words on your filter." +general.341="Please supply a word to add!" +general.342="You cannot have more than 16 words!" +general.343="You already have that word on your filter list!" +general.344="Added %%word%% to your filter!" +general.345="Please supply a word to remove!" +general.346="You don't have that word on your filter list!" +general.347="Removed %%word%% from your filter!" +general.348="Empty " +general.349="Filtered: %%filter%%" +general.350="Cleared %%size%% word from your filter!" +general.351="Cleared %%size%% words from your filter!" +general.352="Lobby Selector (Right Click)" +general.353="Right-click to switch between different lobbies!" +general.354="Use this to stay with your friends." +general.355="Achievements (Right Click)" +general.356="Right-click to view your achievements!" +general.357="Settings Menu" +general.358="Right-click to open settings" +general.359="Players: Visible (Right Click)" +general.360="Right-click to toggle player visibility!" +general.361="Players: Hidden (Right Click)" +general.362="You must be using 1.8 to play Adventures!" +general.363="You were given the %%package%% package!" +general.364="You were given the %%package%% package in gameType %%type%%!" +general.365="You cannot use this!" +general.366="Fireworks are currently turned off!" +general.367="You have to wait 15 seconds between sending fireworks!" +general.368="You cannot use TPA at this time! Report this to staff: (CORE_LINK_DOWN)" +general.369="Snowball is disabled!" +general.370="You must wait to spawn more snowballs!" +general.371="You spawned 15 snowballs!" +general.372="Declined Test Network access." +general.373="Accepted Test Network access. You can now connect to test.hypixel.net" +general.374="You are currently in a parkour race. Use /parkour reset" +general.375="You are currently not in a parkour race. Use /parkour start" +general.376="You are currently not in a parkour race." +general.377="This server is still booting up, try again in a second!" +general.378="Do not get punched :)" +general.379="You are still radiating with %%generosity%%" +general.380="Generosity" +general.381="My Profile (Right Click)" +general.382="My Profile" +general.383="Stats Viewer" +general.384="ERROR!" +general.385="Click to open!" +general.386="Your active booster has expired." +general.387="Close" +general.388="Go Back" +general.389="Coming soon!" +general.390="Daily Recommendation" +general.391="We're cooking up something just for you!" +general.392="Hold tight!" +general.393="Page" +general.394="Settings" +general.395="Settings & Visibility" +general.396="Allows you to edit and control\nvarious personal settings." +general.397="Click to edit your settings!" +general.398="Player Visibility" +general.399="Toggles ability to see players." +general.400="Pet Visibility" +general.401="Toggles ability to see pets." +general.402="Auto Spawn Pet" +general.403="Toggles whether or not your pet will auto spawn upon joining a lobby" +general.404="Blood & Gore" +general.405="Toggles ability to see blood and gore." +general.406="Chat Visibility" +general.407="Toggles ability to see chat." +general.408="Friend Requests" +general.409="Toggles ability to receive friend requests." +general.410="Party Requests" +general.411="Toggles ability to receive party requests." +general.412="Guild Requests" +general.413="Toggles ability to receive guild requests." +general.414="Chat Alerts" +general.415="/lobby Protection" +general.416="Requires you to type the /lobby command twice to avoid accidents." +general.417="%%setting%% is now %%state%%!" +general.418="%%setting%% are now %%state%%!" +general.419="Enabled" +general.420="Disabled" +general.421="Click to enable!" +general.422="Click to disable!" +general.423="You don't have enough coins to buy that!" +general.424="You need %%cost%% more Mystery Dust!" +general.425="You need to be level %%required%% or above!" +general.426="You must be at least %%rank%% to purchase that!" +general.427="You already own this item!" +general.428="You need to buy %%name%% to be able to purchase this!" +general.429="You have already selected this item!" +general.430="You already have this tier!" +general.431="You have already purchased the highest level!" +general.432="%%state%%'s triple coins is active for this game!" +general.433="Network Boosters are available at http://store.hypixel.net/" +general.434="Your game was boosted by %%state%%'s triple coins!" +general.435="You're not allowed to do this!" +general.436="You have chat disabled! Enable it again with /togglechat" +general.437="Chat is currently turned off for regular users!" +general.438="Chat is currently turned off for all users!" +general.439="-----------------------------------------" +general.440="Set your view distance to %%inner%%" +general.441="You must wait 3s between uses!" +general.442="Player visibility disabled!" +general.443="Player visibility enabled!" +general.444="You are now %%packageRank%%" +general.445="Turned off flight!" +general.446="Turned on flight!" +general.447="Launched a firework!" +general.448="Punch is temporarily disabled in this lobby!" +general.449="Your punch ability is in cooldown!" +general.450="You cannot punch this person!" +general.451="This person has been punched too frequently in the past 60 seconds!" +general.452="You cannot punch staff during a party!" +general.453="Only available in lobbies!" +general.454="Left-Click a sign to edit it!" +general.455="You do not have a sign selected! Use /editsign select!" +general.456="Missing args! /editsign line <line index> [text...]" +general.457="Updated sign!" +general.458="You need to be looking at a sign to use this!" +general.459="Sign selected! Use /editsign line <line index> [text...] to edit the sign!" +general.460="Stopping the sign editor!" +general.461="Missing args! /editsign <editor/select/line/stop>" +general.462="You must not be flying to start the parkour!" +general.463="You must not be in a vehicle to start the parkour!" +general.464="You left the previous parkour challenge!" +general.465="Parkour challenge started! Use /parkour reset to restart!" +general.466="Reset your timer to 00:00! Get to the finish line!" +general.467="You must not be flying to end the parkour!" +general.468="You must not be in a vehicle to end the parkour!" +general.469="This is the finish line for the parkour! Get to the start line and climb back up here!" +general.470="That's a new record of %%timeTook%%! Try again to get an even better record!" +general.471="You reached Checkpoint #%%checkpoint%%. You can type /parkour checkpoint to get back to this place." +general.472="Parkour challenge failed! %%message%%!" +general.473="Parkour challenge failed! You took more than 10 minutes!" +general.474="Sorry, try again in a minute!" +general.475="This feature has not been released yet!" +general.476="You don't have enough Mystery Dust to craft that!" +general.477="This game is coming soon!" +general.478="An error occurred while executing that. Please try again." +general.479="Congratulations! Your prize is %%prize%%" +general.480="Please don't spam!" +general.481="We haven't loaded a recommendation for you yet! Please wait!" +general.482="Sorry, I couldn't teleport you to that player!" +general.483="An error has occurred, please report this!" +general.484="You don't have a party to disband!" +general.485="Please wait as we load your party..." +general.486="+%%karma%% Karma!" +general.487="An exception occurred in the QuestStorage! Please report this to staff!" +general.488="You activated a Smash Heroes EXP Booster!" +general.489="Status:" +general.490="%%i%%. %%Utilities%% %%objective%%" +general.491="You started the %%quest%% quest!" +general.492="You can't start this quest right now!" +general.493="You purchased %%quantity%% %%allow%%!" +general.494="You purchased %%allow%%!" +general.495="You now have Speed %%net%%!" +general.496="You will now see things from your own perspective!" +general.497="Once you select a player using your compass, you will spectate them from their perspective!" +general.498="%%formatted%%!" +general.499="I can't help you right now, please come back later! :(" +general.500="%%title%%" +general.501="%%subtitle%%" +general.502="The Housing list is disabled for maintenance and will be back later!" +general.503="That world is coming soon!" +general.504="Attempting to teleport you to %%targetName%%..." +general.505="Something went wrong while processing this. Please try again." +general.506="Attempting to teleport you to your house..." +general.507="Attempting to teleport you to %%targetName%%'s house..." +general.508="Now playing %%name%%" +general.509="You weren't playing any music!" +general.510="Stopped music." +general.511="You earned a total of %%val%% experience!" +general.512="Achievements" +general.513="Achievements" +general.514="Click to view your achievements!" +general.515="Achievement Perks" +general.516="Game Menu" +general.517="Achievements Menu" +general.518="View achievements of other games!" +general.519="Achievement Perks" +general.520="View your Achievement progression!" +general.521="Achievement Points: %%points%%" +general.522="Super Perk Level %%tier%%" +general.523="Perk Level %%tier%%" +general.524="Locked!" +general.525="%%points%% Achievement Points" +general.526="Click to see your progress!" +general.527="Progress: %%amount%%/%%required%%" +general.528="Armor Color Creator" +general.529="%%verb%% Helmet" +general.530="%%verb%% Chestplate" +general.531="%%verb%% Leggings" +general.532="%%verb%% Boots" +general.533="Grab" +general.534="Red" +general.535="Green" +general.536="Blue" +general.537="Click to add %%color%%25 %%type%%!" +general.538="Boosters" +general.539="Coin Boosters" +general.540="Click to activate boosters!" +general.541="Personal Boosters" +general.542="Click to see available personal boosters!" +general.543="Booster" +general.544="Personal Boosters" +general.545="Click to see your available legacy boosters!" +general.546="Network Boosters" +general.547="Network Boosters" +general.548="Network Boosters" +general.549="Click to see your available Network Boosters!" +general.550="You don't have any Network Boosters available!" +general.551="You can purchase them at %%store%%" +general.552="You don't have any available personal boosters!" +general.553="Click to see your available Network Boosters" +general.554="The booster queue command is unavailable at the moment. Try again in a second!" +general.555="You do not have permission to use this command!" +general.556="Invalid length! Valid lengths: " +general.557="Invalid multiplier! Format: 1.5, 2.0, 10.0, etc." +general.558="Couldn't find a player by that name!" +general.559="%%length%% Booster - %%multiplier%%x Coins" +general.560="Active for another %%time%%" +general.561="%%length%% Booster - %%multiplier%%x Coins" +general.562="Click to activate this booster!" +general.563="Confirm" +general.564="Activates this Booster. Cannot be undone." +general.565="Cancel" +general.566="Closes this menu." +general.567="ALL GAMES" +general.568="Quests & Challenges" +general.569="Coins" +general.570="Hypixel\nExperience" +general.571="%%Name%% Completed!" +general.572="You can complete %%remaining%% more challenges today." +general.573="You don't have to manually start Challenges! Join a game and complete them!" +general.574="You've already started the %%name%% quest!" +general.575="Rewards:" +general.576="Reward: %%line%%" +general.577="You can complete the same challenge\nmultiple times per day, but only\nonce per game." +general.578="Challenges remaining today: " +general.579="Daily Quests can be completed once every day." +general.580="Weekly Quests can be completed once every week. Resets Thursday night." +general.581="You can do this quest again in %%time%%" +general.582="You have already completed this one-time quest!" +general.583="Quest resets in %%time%%" +general.584="This quest is currently in cooldown." +general.585="Requires Level %%level%%" +general.586="You've already started this quest!" +general.587="Click to start this quest." +general.588="View all available quests and challenges that you can complete by playing %%game%%." +general.589="Click to view!" +general.590="Auto-Accept Quests: ON" +general.591="Click to no longer automatically\naccept quests whenever you\njoin a game lobby." +general.592="Auto-Accept Quests: OFF" +general.593="Click to automatically accept\nquests whenever you join a\ngame lobby." +general.594="Auto-Accept Quests: OFF" +general.595="Requires %%rank%%" +general.596="No longer automatically accepting quests!" +general.597="You are now automatically accepting quests!" +general.598="You need to be %%rank%% to use this feature!" +general.599="You set your language to %%name%%!" +general.600="%%name%%" +general.601="Set your language to %%name%%!" +general.602="Select Language" +general.603="Set your default language for use on the server." +general.604="Click to automatically detect your language when you login to Hypixel." +general.605="Click to no longer automatically detect your language when you login to Hypixel." +general.606="Auto-Detect Language: Yes" +general.607="Auto-Detect Language: No" +general.608="We will no longer detect your language automatically!" +general.609="We will now detect your language automatically!" +general.610="Travel to someone else's house" +general.611="Hop into the hot air balloon and\nvisit other people's houses." +general.612="You can see people whose house\nyou can join, like PUBLIC\nor FRIENDS ONLY" +general.613="Click to view houses you can join!" +general.614="Search by tags" +general.615="Search for houses based on their\ntags that the owner has set" +general.616="Click here to select a category!" +general.617="No results found" +general.618="No currently active houses\nmatched the tag search that\nyou selected!" +general.619="Click here to start a new search!" +general.620="Nobody has a house that\nyou can currently join! Try\nagain later!" +general.621="Click here to go back to the main menu!" +general.622="Random House" +general.623="Click to visit a Random Featured House" +general.624="Click to visit!" +general.625="Joinable Houses" +general.626="Featured Worlds" +general.627="Travel to a Featured World" +general.628="Hop into the hot air balloon and\nvisit featured worlds. You can\njoin worlds here even if their\nowner is offline." +general.629="Click to view worlds you can join!" +general.630="Roleplay" +general.631="General" +general.632="Parkour" +general.633="Staff" +general.634="Maze" +general.635="Chat" +general.636="Guild Hangout" +general.637="Staff / YouTuber" +general.638="Click this to clear\nyour filter." +general.639="Click this to search for\nhomes where the owner is\neither Staff or YouTuber!" +general.640="Click this to clear\nyour tag filter." +general.641="Click this to search\nfor homes with this tag." +general.642="Go Back" +general.643="Error!" +general.644="Click here to sort by Cookie count!" +general.645="Click to go back to Normal sorting!" +general.646="Cookie Sort" +general.647="Owner: %%name%%" +general.648="%%owner%%'s House" +general.649="This house is open to the public." +general.650="You are in this person's party." +general.651="You are friends with this person." +general.652="You are in this person's guild." +general.653="This house is private." +general.654="Requires a password." +general.655="Visiting Rules: " +general.656="Tags: %%wrapped%%" +general.657="Cookies: %%cookies%%" +general.658="Blocks Unlocked: " +general.659="Current Guests: " +general.660="Travel to your house" +general.661="Hop into the hot air balloon\nand travel to your own House!" +general.662="Click to go to your house!" +general.663="Next Delivery: " +general.664="Completing quests and challenges\nwill reward you with %%coins%%, %%exp%% and more!\n\nYou can complete a maximum of %%max%% \nchallenges every day.\n\nChallenges completed today: %%color%%%%completed%%\n\nClick to view Quests & Challenges" +general.665="Veteran Rewards" +general.666="You have already claimed this reward!" +general.667="Click to claim!" +general.668="You can't claim this yet!" +general.669="You must be MVP+ to claim this!" +general.670="%sHypixel Level Reward %d" +general.671="Hypixel Leveling" +general.672="Coin Multiplier" +general.673="Unlocked!" +general.674="You must be level %%level%% to unlock this perk." +general.675="Increases the amount of coins you\nearn when playing games." +general.676="You already own this because you\npurchased %%rank%% before August 2014." +general.677="Automatically unlocks upon reaching\nthe required level." +general.678="Arcade Coins" +general.679="Arcade Coins can be exchanged for\nother game coins inside the Arcade\nLobby." +general.680="+ %%banner%% Banner" +general.681="Personal Coin Booster" +general.682="To activate a coin booster, go to\nMy Profile > Coin Boosters or type\n/booster" +general.683="Yellow" +general.684="Light Purple" +general.685="White" +general.686="Dark Green" +general.687="Dark Red" +general.688="Dark Aqua" +general.689="Dark Purple" +general.690="Dark Gray" +general.691="Black" +general.692="+%%name%% %%color%%+ option for %%rank%%" +general.693="Playing games and completing quests\nwill reward you with Hypixel Experience,\nwhich is required to level up and\nacquire new perks and rewards!" +general.694="Experience until next level: %%exp%%" +general.695="Click to see your rewards!" +general.696="Rewards for the most dedicated\nplayers!" +general.697="You must be Hypixel Level 100 or\nhigher to access this menu!" +general.698="Click to see your veteran rewards!" +general.699="Quest Log" +general.700="Completing quests will reward you\nwith Coins, Hypixel Experience and\nmore!" +general.701="Talk to Quest Masters located in\ngame lobbies to accept quests." +general.702="Click to view quest progress!" +general.703="MVP+ Rank Color" +general.704="Changes the color of the plus in %%rank%%\nto %%name%%, turning it into MVP%%color%%+" +general.705="Shown in tab list also when chatting\nand joining lobbies." +general.706="The default color for %%rank%%." +general.707="Unlocked at Hypixel Level %%level%%" +general.708="Currently selected!" +general.709="Congratulations on completing the parkour! You finished in %%timeTook%%! Try again to get an even better record!" +general.710="Your time of %%timeTook%% did not beat your previous record of %%prevBestTime%%! Try again to beat your old record!" +general.711="The set language command is currently disabled! Please try again later!" +general.712="Selected language: %%language%%" +general.713="Selected language: %%name%%" +general.714="Click the link to visit our website and claim your reward: " +general.715="Click to visit our website" +general.716="You have already claimed this reward and you have no tokens! Check again in %%time%%!" +general.717="Using 1 token for this roll since you have claimed your daily free reward! You now have %%tokens%% token!" +general.718="Using 1 token for this roll since you have claimed your daily free reward! You now have %%tokens%% tokens!" +general.719="Buy Network Boosters at https://store.hypixel.net\n " +general.720="\n%%purchaser%% activated 3x coins for this game! Gain XP and coins by " +general.721="\nYour game was boosted by %%purchaser%%'s 3x coins Network Booster! Gain XP and coins by " +general.722="CLICKING HERE!" +general.723="Click to /tip all" +general.724="Loading..." +general.725="Daily Reward" +general.726="Daily Reward" +general.727="Click here to get the link in chat!" +general.728="You have claimed this reward and have no tokens! Check back in %%time%%!" +general.729="\n%%purchaser%% activated 3x coins for this game! Gain XP and coins by typing » /TIP ALL«" +general.730="Buy Network Boosters at https://store.hypixel.net\n " +general.731="%%purchaser%%'s Network Booster expired!\nBuy Network Boosters at https://store.hypixel.net\n " +general.732="%%purchaser%% activated 3x coins for this game! Gain XP and coins by typing » /TIP ALL«" +general.733="Hypixel Experience" +general.734="SkyWars Souls" +general.735="You don't have permission to do this!" +general.736="You don't have permissions to that command!" +general.737="That player is not online!" +general.738="Usage: %%command%%" +general.739="Cleared your inventory!" +general.740="You don't have permission to do that!" +general.741="Invalid input %%input%%, please enter a number" +general.742="Invalid input %%input%%" +general.743="Right click" +general.744="Left click" +general.745="Clickable" +general.746="sky" +general.747="theme" +general.748="biome" +general.749="rule" +general.750="weather" +general.751="group" +general.752="permission" +general.753="value" +general.754="player" +general.755="item" +general.756="data" +general.757="line" +general.758="message" +general.759="text" +general.760="reason" +general.761="mode" +general.762="coins" +general.763="The chat is currently muted for%%time%% seconds." +general.764="Automatically activated: %%name%%" +general.765="Stop Track" +general.766="Stop playing the current track." +general.767="Your nick has been reset!" +general.768="You do not have a nick. To get one, use /nick (username)!" +general.769="That name is too long or short to be used as a nick!" +general.770="Nicks can't have special characters in them!" +general.771="You cannot nick as an NPC's name! Choose another name!" +general.772="You can't nick as a player that exists!" +general.773="Correct usage:" +general.774="/nick - Change your nickname to a random name" +general.775="/nick reset - Reset your nickname" +general.776="/nick check (username) - Check who has the nickname 'username'" +general.777="You have already voted for this map!" +general.778="Your vote has been registered! %%text%%" +general.779="Click to vote!" +general.780="Rate this map by clicking:" +general.781="Completing quests and challenges\nwill reward you with %%coins%%, %%exp%%and more!" +general.782="%%name%% Achievements" +general.783="View %%achievements%%" +general.784="Showcases your stats for each\ngame and an overview of all." +general.785="Players ranked MVP or higher\ncan use /stats (username) to view\nother player's stats." +general.786="Click to view your stats!" +general.787="You can complete a maximum of %%max%% \nchallenges every day." +general.788="Challenges completed today: %%color%%%%completed%%" +general.789="Click to view Quests & Challenges" +general.790="Slow down there!" +general.791="RIGHT CLICK" +general.792="RIGHT CLICK" +general.793="New Daily Reward!" +general.794="%%tokens%% Daily Reward Token!" +general.795="%%tokens%% Daily Reward Tokens!" +general.796="%%amount%% Delivery!" +general.797="%%amount%% Deliveries!" +general.798="Start" +general.799="End" +general.800="Checkpoint" +general.801="Hypixel currently supports translation for these games:" +general.802="You chose not to change your language!" +general.803="Click to spectate!" +general.804="Click to only show %%team%%!" +general.805="We are sorry that you are having resource pack issues, please ensure that you have them enabled in your server settings.\n\nYou can also use %%command%% to attempt to force download the pack.\n\nIf you need further assistance, click on the link below:\n%%link%%" +general.806="Purchase %%rank%% at https://store.hypixel.net to create Guilds." +general.807="You need to be %%rank%% to equip that!" +general.808="You have to be %%rank%% to select that!" +general.809="You must be at least %%rank%% to claim this delivery!" +general.810="You must be %%rank%% to use the quick join feature! You can always use the Play signs!" +general.811="You must be a %%rank%% to use this jukebox! Purchase %%rank%% at http://store.hypixel.net/" +general.812="You can join a Guild using /guild join\nregardless of your rank." +general.813="Players ranked %%rank%% or higher\ncan create Guilds using /guild create." +general.814="The Delivery Man" +general.815="Achievement Unlocked:" +general.816="Quest Master" +general.817="COMING SOON" +general.818="2000 XP Delivery" +general.819="Earn 2000 experience Daily!\nClick to loot!" +general.820="2000 XP Delivery" +general.821="You've already used this for the day!\nNext Delivery: r(time)" +general.822="Two Free Quad Boosters" +general.823="Like us on Facebook and receive two FREE Three Hour Quad Boosters!\n&eClick to loot!" +general.824="Two Free Quad Boosters" +general.825="You have already liked us on Facebook and received your free boosters!" +general.826="Website Link" +general.827="Create and link your forums account to your in game account with /linkaccount and earn 15,000 XP" +general.828="Website Link" +general.829="You have linked your account to the forums" +general.830="You earned 2,000 experience!" +general.831="You don't have r(rank)!" +general.832="This is currently on cooldown! Next Delivery: r(time)!" +general.833="To get your redemption code, visit http://hypixel.net/quad and follow the simple instructions! Then in game use /redeem (code) with the code you just received!" +general.834="You have completed this task!" +general.835="To receive this delivery, use the command "/linkaccount" and link your forums account to your in game account! If you do not have a forums account, create one and join the community! After you do this, you will receive 15,000 XP the next time you login!" +general.836="Click to see Guild members." +general.837="You can purchase Network Boosters at %%store%%" +general.838="%%player%% is radiating with Generosity!" +general.839="%%amount%% Available" +general.840="Deny" +general.841="Deny" +general.842="Parkour Challenge" +general.843="This language is currently not supported! Check back soon!" +general.844="COMING SOON" +general.845="Track your progress as you unlock\nAchievements and rack up points." +general.846="You've already claimed this month's reward!" +general.847="Something went wrong! Please try again in a moment!" +general.848="Activated your booster. You now have %%time%%s of %%b%%x coins." +general.849="Open" +general.850="Would you like to change your Hypixel language to %%language%%?" +general.851="YES" +general.852="NO" +general.853="Click to change your Hypixel language to %%language%%!" +general.854="Click to keep your Hypixel language set as %%language%%!" +general.855="Hypixel Tutorial" +general.856="January" +general.857="February" +general.858="March" +general.859="April" +general.860="May" +general.861="June" +general.862="July" +general.863="August" +general.864="September" +general.865="October" +general.866="November" +general.867="December" +general.868="Like us on Facebook and receive two FREE Three Hour Quad Boosters!\nClick to loot!" +general.869="Click to change your language!" +general.870="Currently available:" +general.871="Coming Soon" +general.872="Help us Translate Hypixel" +general.873="Click this icon for the website link." +general.874="Click the link below to find out how to help us translate Hypixel:" +general.875="Click this link to help us Translate Hypixel:" +general.876="Change your language." +general.877="Change your language to %%language%%." +general.878="Click to disable!" +general.879="Click to enable!" +general.880="More languages coming soon!" +general.881="Hey %%player%%," +general.882="You have a new Daily Reward to claim!" +general.883="Visit the Delivery Man or %%click_here%%" +general.884="click here" +general.885="%%visit_the_delivery_man_or_click_here%% to choose from %%exp%%, %%souls%%, %%coins%%, %%dust%%, and more FREE rewards!" +general.886="Sorry, this language is not yet supported, but will be soon!" +general.887="You can speed this up by helping us translate!" +general.888="We noticed you haven't claimed your free Daily Reward yet!" +general.889="To choose your reward you have to click the link to visit our website! As a reminder, here's your link for today:" +general.890="Right-click to browse quests,\nview achievements, Network Boosters and more!" +general.891="Something went wrong while processing your player data!" +general.892="Something went wrong while processing that purchase!" +general.893="You don't have enough %%color%%Mystery Dust" +general.894="Daily Reward" +general.895="Free 2,000 Network Experience and 3,000 Arcade Coins!" +general.896="Click here to claim!" +general.897="You have claimed this reward recently! Check back in %%time%%!" +general.898="You have successfully claimed %%exp%% and %%coins%%!" +general.899="Already processing a purchase for you!" +general.900="Clicking this will sort the houses by the amount of cookies the owner has received this week!" +general.901="Clicking too fast! Please slow down!" +general.902="Convert" +general.903="This game is currently in a closed beta." +general.904="Click to open the Hypixel Leveling menu" +general.905="Click here to claim your reward!" +general.906="Click here to view all the Hypixel Leveling rewards!" +general.907="Don't use Gadgets!" +general.908="Poll: %%poll%%" +general.909="Question: %%question%%" +general.910="Answer: %%answer%%" +general.911="Time Remaining: %%color%%%%time%%" +general.912="Current Votes: %%color%%%%percentage%%!" +general.913="Live vote percentages are shown on the right in bar form." +general.914="Click to vote %%option%%!" +general.915="What Theme?" +general.916="Holiday" +general.917="Map: %%map%%" +general.918="In Queue: %%players%%/%%max%%" +general.919="Mode: Faceoff" +general.920="Mode: Teams (%%maps%%)" +general.921="Mode: Solo" +general.922="Total Players: %%players%%" +general.923="%%color%%You must be %%rank%% %%color%%or\n%%color%%higher to use the\n%%color%%Quick-Join feature!" +general.924="Click to play!" +general.925="Play %%game%%" +general.926="Completing quests and challenges\nwill reward you with %%coins%%, %%exp%% and more!" +general.927="You started the %%name%% quest!" +general.928="www.hypixel.net" +general.929="Unlimited" +general.930="Angel of Death" +general.931="Queued! Use the bed to return to lobby!" +general.932="Queued! Use the bed to cancel!" +general.933="Food: %%food%%" +general.934="Free Daily Reward!" +general.935="hour" +general.936="Total Mystery Dust: " +general.937="Click to change!" +general.938="day" +general.939="Welcome Package" +general.940="That code isn't valid!" +general.941="Redeem a Code" +general.942="Click to redeem a code!" +general.943="You already claimed this!" +general.944="Have 1 minute of powerups left at the end of an Ender Spleef game" +general.945="MiniWalls Winner" +general.946="Farm Domination" +general.947="Team Work" +general.948="Football Pro" +general.949="Hit 5 players with the "Notched Sword" in 1 race" +general.950="Winner!" +general.951="Kill 2 or more players with one Fireball" +general.952="Kill a Vampire while on half a heart" +general.953="Win a game as Phoenix with yourself and at least four teammates, who you've resurrected, still alive" +general.954="Craft an iron sword and get 7 final kills with that sword without dying as Spider" +general.955="Chop 20,000 pieces of wood as Golem" +general.956="Get 20 FK's or FA's in a single game as Spider" +general.957="Get 10 Final Kills with Arcane Explosion as Arcanist" +general.958="Get 20 FK's or FA's in a single game as Pirate" +general.959="Get 20 FK's or FA's in a single game as Creeper" +general.960="Get 20 FK's or FA's in a single game as Blaze" +general.961="Get 9 Final Kills with Fireballs as Blaze in one game" +general.962="Collect 2 stacks of TNT from your gathering talent before the walls fall" +general.963="Heal 10000 HP from mining iron ore as Blaze" +general.964="Get 20 FK's or FA's in a single game as Arcanist" +general.965="Get 20 FK's or FA's in a single game as Herobrine" +general.966="Gather from your mining ability and consume 8 absorption potions in one game as Squid" +general.967="Activate Tempest 5 times in a row, without losing Speed III" +general.968="Get 20 FK's or FA's in a single game as Moleman" +general.969="Spawn 5,000 wolves as Shaman" +general.970="Heal teammates for 1500 total HP using inferno as Phoenix" +general.971="Get 15 total defensive FK's or FA's as Squid" +general.972="Deal 100,000 wither damage total as Dreadlord" +general.973="Get 20 FK's or FA's in a single game as Pigman" +general.974="Damage 5 different players with one Splash as Squid" +general.975="Craft 2,500 bread as Dreadlord" +general.976="Harvest 50 Steaks from killing players in a single game." +general.977="Break 15,000 blocks with detonate as Creeper" +general.978="Get 5 total final kills with your Minion as Creeper" +general.979="Get 200 total final kills from behind as Enderman" +general.980="Get 7 melee FK's as Skeleton in a single game" +general.981="Get 25 total FK's with Parrots as Pirate" +general.982="Get 20 FK's or FA's in a single game as Dreadlord" +general.983="Wolf smash" +general.984="Get 10 Final Kills with an indirect hit using Lycanthropy." +general.985="Eat 10,000 Steaks as Werewolf" +general.986="Hit an enemy with your cannonball from over 50 blocks away Pirate" +general.987="Attack all three enemy withers within 2 minutes after the walls have fallen as Enderman" +general.988="Give away 10000 pieces of iron armor to your team during the month of December" +general.989="Teleport to 5000 total players as Enderman" +general.990="Place 25,000 total blocks in preparation time as Moleman" +general.991="Get 20 FK's or FA's in a single game as Enderman" +general.992="Get 20 FK's or FA's in a single game as Squid" +general.993="Get 20 FK's or FA's in a single game as Shaman" +general.994="Circle of trust" +general.995="Damage 10 people at once with one Pigman bubble" +general.996="Get 20 FK's or FA's in a single game as Werewolf" +general.997="Get 30 FK's with your wolves as Shaman." +general.998="Get 20 FK's or FA's as Skeleton in a single game" +general.999="Martyrdom" +general.1000="Get 10 total FK's with your nest spiders as Spider" +general.1001="Get 5 Final Kills in 7 seconds as Dreadlord" +general.1002="Craft and place a bed in 100 games as Zombie" +general.1003="Gather 1500 total armor pieces as Pigman" +general.1004="Travel 100,000 blocks with Speed as Werewolf" +general.1005="Get 5 Final kills in a period of 7 seconds as Herobrine" +general.1006="Mine 100 diamond ore as Skeleton" +general.1007="Blowing bubbles" +general.1008="Activate 6 Pigman bubbles within 25 seconds" +general.1009="Heal at least 240 hearts to your teammates as Zombie in a single game." +general.1010="Get 40 FK's from over 50 blocks as Skeleton" +general.1011="Have the treasure looter ability activate 1000 times as Pirate" +general.1012="Feels bad...?" +general.1013="Final kill an enemy by dropshocking to your own death" +general.1014="Heal 25,000 total HP as Squid" +general.1015="Get 20 FK's or FA's as Zombie in a single game" +general.1016="Get 10 FK's with Animal Companion as Hunter" +general.1017="Get 20 FK's or FA's in a single game as Phoenix" +general.1018="Damage 6 different players with one Iron Punch as Golem" +general.1019="Get 20 FK's or FA's in a single game as Golem" +general.1020="Get 20 FK's or FA's in a single game as Hunter" +general.1021="This is not Skywars" +general.1022="Kill 5 players within 10 seconds" +general.1023="Get 10 kills in a one game" +general.1024="Win a game using the Gun of Darkness" +general.1025="Players ranked %%rank%% can unlock and switch the color of their +." +general.1026="Small Bag of Hypixel Experience" +general.1027="Medium Bag of Hypixel Experience" +general.1028="Large Bag of Hypixel Experience" +general.1029="Mystery Dust" +general.1030="store.hypixel.net" +general.1031="https://store.hypixel.net" +general.1032="Mystery Dust: %%dust%%" +general.1033="Quests Completed: %%quests%%" +general.1034="Extreme Quality" +general.1035="Removes all rate limiting on particles. Recommended for high end machines and fast internet connections only." +general.1036="Black Smoke" +general.1037="Classic" +general.1038="Diamonds" +general.1039="Eggs" +general.1040="Emeralds" +general.1041="Enchanting" +general.1042="Chunky" +general.1043="Fire" +general.1044="Hearts" +general.1045="Musical Notes" +general.1046="None" +general.1047="Rainbow" +general.1048="Red Dust" +general.1049="Roses" +general.1050="Slime" +general.1051="Snow" +general.1052="White Smoke" +general.1053="Right-click to leave to the lobby!" +general.1054="Selects the %%blood_effect%% blood effect for whenever blood is displayed." +general.1055="+%%amount%% Magical Key" +general.1056="+%%amount%% Magical Keys" +general.1057="+%%amount%% Soul" +general.1058="%%amount%% Game Smash Heroes EXP Booster" +general.1059="%%amount%% Games Smash Heroes EXP Booster" +general.1060="+%%amount%% Broken Weapon" +general.1061="+%%amount%% Broken Weapons" +general.1062="+%%amount%% Magic Dust" +general.1063="+%%amount%% Void Shard" +general.1064="+%%amount%% Void Shards" +general.1065="+%%amount%% Hypixel Experience" +general.1066="+%%amount%% Mystery Dust" +general.1067="Win 2 games of TNT Wizards" +general.1068="Win 15 games of TNT Wizards" +general.1069="Kill a total of 50 players" +general.1070="Stats Viewer" +general.1071="#Unranked" +general.1072="%%name%% Lobby #%%number%% is currently offline!" +general.1073="a day" +general.1074="a minute" +general.1075="a month" +general.1076="a year" +general.1077="about " +general.1078="about a second" +general.1079="an hour" +general.1080=" and " +general.1081=" and a day" +general.1082=" and a month" +general.1083=" and an hour" +general.1084=" days" +general.1085=" hours" +general.1086=" minutes" +general.1087=" months" +general.1088=" seconds" +general.1089=" years" +general.1090="Command Failed: This command is on cooldown! Try again in %%time%%!" +general.1091="Skeleton" +general.1092="Zombie" +general.1093="Creeper" +general.1094="Enderman" +general.1095="Spider" +general.1096="Squid" +general.1097="Blaze" +general.1098="1v1 Kills" +general.1099="1v1 Wins" +general.1100="2v2 Kills" +general.1101="2v2 Wins" +general.1102="4v4 Kills" +general.1103="4v4 Wins" +general.1104="Blocking Dead: Kills" +general.1105="Blocking Dead: Wins" +general.1106="Bombs Defused" +general.1107="Bombs Planted" +general.1108="Bounty Hunters: Wins" +general.1109="Bow Spleef Shots" +general.1110="Bow Spleef Wins" +general.1111="Box Pickups" +general.1112="Bronze Trophies" +general.1113="Build Battle: Solo Wins" +general.1114="Build Battle: Team Wins" +general.1115="Class" +general.1116="Creeper Attack: Best Wave" +general.1117="CTF Wins" +general.1118="Defusal Kills" +general.1119="Defusal Wins" +general.1120="Domination Wins" +general.1121="Doubles Kills" +general.1122="Doubles Wins" +general.1123="Dragon Wars: Wins" +general.1124="Ender Spleef: Wins" +general.1125="Farm Hunt: Animal Wins" +general.1126="Farm Hunt: Poop Collected" +general.1127="Football: Wins" +general.1128="Galaxy Wars: Wins" +general.1129="Gold Trophies" +general.1130="Heads Eaten" +general.1131="Headshots" +general.1132="Hole in the Wall: Wins" +general.1133="Human Kills" +general.1134="Human Wins" +general.1135="Hypixel Says: Wins" +general.1136="Kills Solo" +general.1137="Kills Teams" +general.1138="Laps Completed" +general.1139="Mega Kills" +general.1140="Mega Wins" +general.1141="Mini Walls: Wins" +general.1142="Party Games: Wins" +general.1143="Pixel Painters: Wins" +general.1144="PVP Run Kills" +general.1145="PVP Run Wins" +general.1146="Ranked Kills" +general.1147="Ranked Position" +general.1148="Ranked Rating" +general.1149="Ranked Wins" +general.1150="Round Wins" +general.1151="Shots Fired" +general.1152="Silver Trophies" +general.1153="Smash Level" +general.1154="Solo Kills" +general.1155="Solo Wins" +general.1156="TDM Kills" +general.1157="TDM Wins" +general.1158="Team Kills" +general.1159="Team War Kills" +general.1160="Team War Wins" +general.1161="Team Wins" +general.1162="Throw Out: Wins" +general.1163="TNT Run Wins" +general.1164="TNT Tag Wins" +general.1165="Vampire Kills" +general.1166="Wins" +general.1167="Wins Solo" +general.1168="Wins Teams" +general.1169="Wizard Kills" +general.1170="Wizard Wins" +general.1171="Total Stats" +general.1172="%%game%% Stats" +general.1173="Parkour Challenge" +general.1174="Default" +general.1175="ADMIN" +general.1176="MODERATOR" +general.1177="%%playerCount%% Currently Playing!" +general.1178="http://store.hypixel.net" +general.1179="Bed Wars Experience" +general.1180="[SPECTATOR]" +general.1181="[TEAM]" +general.1182="%%playerCount%% Currently Playing!" +general.1183="%%prefix%%%%amount%% coins!%%builder%%%%reason%%" +general.1184="This person has been punched too frequently in the past 30 seconds!" +general.1185="Rating" +general.1186="Keys" +general.1187="Killstreaks" +general.1188="You are currently %%states%%" +general.1189="VANISHED" +general.1190="NICKED" +general.1191="I'm sorry, but you do not have permission to perform this command. Please contact the server administrators if you believe that this is in error." +general.1192="%%prefix%%%%amount%% coin!%%builder%%%%reason%%" +general.1193="+%%amount%% coin" +general.1194="You have received no rewards due to anti addiction." +general.1195="Your rewards have been halved due to anti addiction." +general.1196="Your multiplier is currently %%multiplier%% due to anti addiction." +general.1197="[emote name]" +general.1198="[gesture name]" +general.1199="[lobby number]" +general.1200="[name]" +general.1201="[word]" +general.1202="You can only chat once every 3 seconds! Buy VIP to bypass this restriction!" +general.1203="Please be respectful of other players." +general.1204="You cannot say the same message twice!" +general.1205="Swearing and attempting to circumvent the filter are against the rules." +general.1206="Advertising is against the rules. You will be permanently banned from the server if you attempt to advertise." +general.1207="Use of excessive caps is against the rules." +general.1208="Please do not spam chat with excessive spamming of characters." +general.1209="HypixelCapes is a phishing attempt." +general.1210="Blocked automated message sent by you containing 'minechat' or 'minecraft connect'" +general.1211="Blocked automated update messages from your client." +general.1212="Please avoid accusing people. If they are hacking, please report them on the forums or use /watchdogreport <name>!" +general.1213="Loading..." +general.1214="You can only use this command in a game!" +general.1215="You gave yourself a lightning stick! Buzz!" +general.1216="%%giver%% gave everyone a Lightning Stick!" +general.1217="%%giver%% gave you a Lightning Stick!" +general.1218="You gave %%target%% a Lightning Stick!" +general.1219="Lightning Stick" +general.1220="Tesla would be happy!" +general.1221="Target player not found!" +general.1222="You must be %%rank%% or higher to use this command!" +general.1223="%%underline%%Click to toggle!" +general.1224="Health: %%health%%" +general.1225="Playing %%game%% on %%color%%MC.HYPIXEL.NET" +general.1226="Invalid arguments, try: %%usage%%" +general.1227="/nick check Nickname" +general.1228="This command is temporarily disabled. Please try again later." +general.1229="You cannot use this command while alive in-game!" +general.1230="You can only use this command in lobbies!" +general.1231="Enter your desired\nusername here" +general.1232="You have finished setting up your nickname!" +general.1233=" %%underline%%TRY AGAIN" +general.1234="Click here to enter a different username." +general.1235="We've generated a random username for you:" +general.1236=" %%underline%%USE NAME" +general.1237="Click here to use this name." +general.1238="Click here to generate another name." +general.1239="Or enter a name to use." +general.1240="Click here to enter a name to use." +general.1241="Uh-oh! An error occurred while trying to generate you a name." +general.1242="➤ Try again" +general.1243="Click here to try again." +general.1244="➤ Enter a name" +general.1245="Click here if you'd like to enter a name to use instead." +general.1246="Let's get you set up with your nickname!" +general.1247="First, you'll need to choose which RANK you would like to be shown as when nicked." +general.1248="Awesome! Now, which SKIN would you like to have while nicked?" +general.1249="➤ My normal skin" +general.1250="Click here to use your normal skin" +general.1251="➤ Steve/Alex skin" +general.1252="Click here to use a Steve/Alex skin" +general.1253="➤ Random skin" +general.1254="Click here to use a random preset skin" +general.1255="Alright, now you'll need to choose the NAME to use!" +general.1256="Click here to enter the name to use" +general.1257="➤ Use a random name" +general.1258="Click here to use a randomly generated name" +general.1259="➤ Use '%%name%%'" +general.1260="Click here to use '%%name%%'" +general.1261="To go back to being your usual self, type:" +general.1262="Click here to be shown as %%rank%%" +general.1263="Set your nick rank to %%rank%%!" +general.1264="Unrecognized rank!" +general.1265="This is already your nickname!" +general.1266="That name is too long or too short to be used as a nick!" +general.1267="Another player is using this as their nickname!" +general.1268="You are now nicked as %%name%%!" +general.1269="Nicknames can't be shorter than 4 characters or longer than 16!" +general.1270="Nicknames can only contain letters, numbers and underscores!" +general.1271="This name belongs to a NPC!" +general.1272="This name belongs to a Hypixel player!" +general.1273="Somebody else is currently using this nickname!" +general.1274="/nick skin random, /nick skin real or /nick skin reset" +general.1275="Unrecognized skin, try /nick skin random for a random skin." +general.1276="You will now show up as a Steve/Alex." +general.1277="You will now have your Minecraft character's skin even when nicked!" +general.1278="Your skin has been set to %%skin%%." +general.1279="You purchased %%item%%!" +general.1280="Stone" +general.1281="Granite" +general.1282="Polished Granite" +general.1283="Diorite" +general.1284="Polished Diorite" +general.1285="Andesite" +general.1286="Polished Andesite" +general.1287="Grass Block" +general.1288="Dirt" +general.1289="Coarse Dirt" +general.1290="Podzol" +general.1291="Cobblestone" +general.1292="Oak Wood Planks" +general.1293="Spruce Wood Planks" +general.1294="Birch Wood Planks" +general.1295="Jungle Wood Planks" +general.1296="Acacia Wood Planks" +general.1297="Dark Oak Wood Planks" +general.1298="Oak Sapling" +general.1299="Spruce Sapling" +general.1300="Birch Sapling" +general.1301="Jungle Sapling" +general.1302="Acacia Sapling" +general.1303="Dark Oak Sapling" +general.1304="Bedrock" +general.1305="Water (No Spread)" +general.1306="Water" +general.1307="Lava (No Spread)" +general.1308="Lava" +general.1309="Sand" +general.1310="Red Sand" +general.1311="Gravel" +general.1312="Gold Ore" +general.1313="Iron Ore" +general.1314="Coal Ore" +general.1315="Oak Wood" +general.1316="Spruce Wood" +general.1317="Birch Wood" +general.1318="Jungle Wood" +general.1319="Oak Leaves" +general.1320="Spruce Leaves" +general.1321="Birch Leaves" +general.1322="Jungle Leaves" +general.1323="Sponge" +general.1324="Wet Sponge" +general.1325="Glass" +general.1326="Lapis Lazuli Ore" +general.1327="Lapis Lazuli Block" +general.1328="Dispenser" +general.1329="Sandstone" +general.1330="Chiseled Sandstone" +general.1331="Smooth Sandstone" +general.1332="Note Block" +general.1333="Bed" +general.1334="Powered Rail" +general.1335="Detector Rail" +general.1336="Sticky Piston" +general.1337="Web" +general.1338="Shrub" +general.1339="Grass" +general.1340="Fern" +general.1341="Dead Bush" +general.1342="Piston" +general.1343="Piston (Head)" +general.1344="Wool" +general.1345="Orange Wool" +general.1346="Magenta Wool" +general.1347="Light Blue Wool" +general.1348="Yellow Wool" +general.1349="Lime Wool" +general.1350="Pink Wool" +general.1351="Gray Wool" +general.1352="Light Gray Wool" +general.1353="Cyan Wool" +general.1354="Purple Wool" +general.1355="Blue Wool" +general.1356="Brown Wool" +general.1357="Green Wool" +general.1358="Red Wool" +general.1359="Black Wool" +general.1360="Dandelion" +general.1361="Rose" +general.1362="Blue Orchid" +general.1363="Allium" +general.1364="Azure Bluet" +general.1365="Red Tulip" +general.1366="Orange Tulip" +general.1367="White Tulip" +general.1368="Pink Tulip" +general.1369="Oxeye Daisy" +general.1370="Brown Mushroom" +general.1371="Red Mushroom" +general.1372="Gold Block" +general.1373="Iron Block" +general.1374="Stone Slab (Double)" +general.1375="Sandstone Slab (Double)" +general.1376="Wooden Slab (Double)" +general.1377="Cobblestone Slab (Double)" +general.1378="Brick Slab (Double)" +general.1379="Stone Brick Slab (Double)" +general.1380="Nether Brick Slab (Double)" +general.1381="Quartz Slab (Double)" +general.1382="Smooth Stone Slab (Double)" +general.1383="Smooth Sandstone Slab (Double)" +general.1384="Stone Slab" +general.1385="Sandstone Slab" +general.1386="Wooden Slab" +general.1387="Cobblestone Slab" +general.1388="Brick Slab" +general.1389="Stone Brick Slab" +general.1390="Nether Brick Slab" +general.1391="Quartz Slab" +general.1392="Brick" +general.1393="TNT" +general.1394="Bookcase" +general.1395="Moss Stone" +general.1396="Obsidian" +general.1397="Torch" +general.1398="Oak Wood Stairs" +general.1399="Chest" +general.1400="Redstone Wire" +general.1401="Diamond Ore" +general.1402="Diamond Block" +general.1403="Crafting Table" +general.1404="Wheat (Crop)" +general.1405="Farmland" +general.1406="Furnace" +general.1407="Furnace (Smelting)" +general.1408="Sign (Block)" +general.1409="Wood Door (Block)" +general.1410="Ladder" +general.1411="Rails" +general.1412="Stone Stairs" +general.1413="Sign (Wall Block)" +general.1414="Lever" +general.1415="Pressure Plate" +general.1416="Iron Door (Block)" +general.1417="Redstone Ore" +general.1418="Redstone Ore (Glowing)" +general.1419="Redstone Torch" +general.1420="Redstone Torch (On)" +general.1421="Button" +general.1422="Ice" +general.1423="Snow Block" +general.1424="Cactus" +general.1425="Clay Block" +general.1426="Sugar Cane (Block)" +general.1427="Jukebox" +general.1428="Fence" +general.1429="Pumpkin" +general.1430="Netherrack" +general.1431="Soul Sand" +general.1432="Glowstone" +general.1433="Portal" +general.1434="Jack-O-Lantern" +general.1435="Cake (Block)" +general.1436="Redstone Repeater (Block Off)" +general.1437="Redstone Repeater (Block On)" +general.1438="Stained Glass" +general.1439="Wooden Trapdoor" +general.1440="Stone Monster Egg" +general.1441="Cobblestone Monster Egg" +general.1442="Stone Brick Monster Egg" +general.1443="Mossy Stone Brick Monster Egg" +general.1444="Cracked Stone Brick Monster Egg" +general.1445="Chiseled Stone Brick Monster Egg" +general.1446="Stone Bricks" +general.1447="Mossy Stone Bricks" +general.1448="Cracked Stone Bricks" +general.1449="Chiseled Stone Bricks" +general.1450="Brown Mushroom (Block)" +general.1451="Red Mushroom (Block)" +general.1452="Iron Bars" +general.1453="Glass Pane" +general.1454="Melon (Block)" +general.1455="Pumpkin Vine" +general.1456="Melon Vine" +general.1457="Vines" +general.1458="Fence Gate" +general.1459="Brick Stairs" +general.1460="Stone Brick Stairs" +general.1461="Mycelium" +general.1462="Lily Pad" +general.1463="Nether Brick" +general.1464="Nether Brick Fence" +general.1465="Nether Brick Stairs" +general.1466="Nether Wart" +general.1467="Enchantment Table" +general.1468="Brewing Stand (Block)" +general.1469="Cauldron (Block)" +general.1470="End Portal" +general.1471="End Portal Frame" +general.1472="End Stone" +general.1473="Dragon Egg" +general.1474="Redstone Lamp (Inactive)" +general.1475="Redstone Lamp (Active)" +general.1476="Double Wood Slab" +general.1477="Oak Wood Slab" +general.1478="Spruce Wood Slab" +general.1479="Birch Slab" +general.1480="Jungle Slab" +general.1481="Acacia Wood Slab" +general.1482="Dark Oak Wood Slab" +general.1483="Cocoa Plant" +general.1484="Sandstone Stairs" +general.1485="Emerald Ore" +general.1486="Ender Chest" +general.1487="Tripwire Hook" +general.1488="Tripwire" +general.1489="Emerald Block" +general.1490="Spruce Wood Stairs" +general.1491="Birch Wood Stairs" +general.1492="Jungle Wood Stairs" +general.1493="Command Block" +general.1494="Beacon Block" +general.1495="Cobblestone Wall" +general.1496="Mossy Cobblestone Wall" +general.1497="Flower Pot" +general.1498="Carrots" +general.1499="Potatoes" +general.1500="Head" +general.1501="Anvil" +general.1502="Slightly Damaged Anvil" +general.1503="Very Damaged Anvil" +general.1504="Trapped Chest" +general.1505="Weighted Pressure Plate (Light)" +general.1506="Weighted Pressure Plate (Heavy)" +general.1507="Redstone Comparator (inactive)" +general.1508="Redstone Comparator (active)" +general.1509="Daylight Sensor" +general.1510="Redstone Block" +general.1511="Nether Quartz Ore" +general.1512="Hopper" +general.1513="Quartz Block" +general.1514="Chiseled Quartz Block" +general.1515="Pillar Quartz Block" +general.1516="Quartz Stairs" +general.1517="Activator Rail" +general.1518="Dropper" +general.1519="Stained Clay" +general.1520="Stained Glass Pane" +general.1521="Acacia Leaves" +general.1522="Dark Oak Leaves" +general.1523="Acacia Wood" +general.1524="Dark Oak Wood" +general.1525="Acacia Wood Stairs" +general.1526="Dark Oak Wood Stairs" +general.1527="Slime Block" +general.1528="Barrier" +general.1529="Iron Trapdoor" +general.1530="Prismarine" +general.1531="Prismarine Bricks" +general.1532="Dark Prismarine" +general.1533="Sea Lantern" +general.1534="Hay Block" +general.1535="Carpet" +general.1536="Hardened Clay" +general.1537="Block of Coal" +general.1538="Packed Ice" +general.1539="Sunflower" +general.1540="Lilac" +general.1541="Double Tallgrass" +general.1542="Large Fern" +general.1543="Rose Bush" +general.1544="Peony" +general.1545="Red Sandstone" +general.1546="Chiseled Red Sandstone" +general.1547="Smooth Red Sandstone" +general.1548="Red Sandstone Stairs" +general.1549="Red Sandstone Slab" +general.1550="Spruce Fence Gate" +general.1551="Birch Fence Gate" +general.1552="Jungle Fence Gate" +general.1553="Dark Oak Fence Gate" +general.1554="Acacia Fence Gate" +general.1555="Spruce Fence" +general.1556="Birch Fence" +general.1557="Jungle Fence" +general.1558="Dark Oak Fence" +general.1559="Acacia Fence" +general.1560="Iron Shovel" +general.1561="Iron Pickaxe" +general.1562="Iron Axe" +general.1563="Flint and Steel" +general.1564="Apple" +general.1565="Bow" +general.1566="Arrow" +general.1567="Coal" +general.1568="Charcoal" +general.1569="Iron Ingot" +general.1570="Gold Ingot" +general.1571="Iron Sword" +general.1572="Wooden Sword" +general.1573="Wooden Shovel" +general.1574="Wooden Pickaxe" +general.1575="Wooden Axe" +general.1576="Stone Sword" +general.1577="Stone Shovel" +general.1578="Stone Pickaxe" +general.1579="Stone Axe" +general.1580="Diamond Sword" +general.1581="Diamond Shovel" +general.1582="Diamond Pickaxe" +general.1583="Diamond Axe" +general.1584="Stick" +general.1585="Bowl" +general.1586="Mushroom Stew" +general.1587="Gold Sword" +general.1588="Gold Shovel" +general.1589="Gold Pickaxe" +general.1590="Gold Axe" +general.1591="String" +general.1592="Feather" +general.1593="Gunpowder" +general.1594="Wooden Hoe" +general.1595="Stone Hoe" +general.1596="Iron Hoe" +general.1597="Diamond Hoe" +general.1598="Gold Hoe" +general.1599="Seeds" +general.1600="Wheat" +general.1601="Bread" +general.1602="Leather Helmet" +general.1603="Leather Chestplate" +general.1604="Leather Leggings" +general.1605="Leather Boots" +general.1606="Chainmail Helmet" +general.1607="Chainmail Chestplate" +general.1608="Chainmail Leggings" +general.1609="Chainmail Boots" +general.1610="Iron Helmet" +general.1611="Iron Chestplate" +general.1612="Iron Leggings" +general.1613="Iron Boots" +general.1614="Diamond Helmet" +general.1615="Diamond Chestplate" +general.1616="Diamond Leggings" +general.1617="Diamond Boots" +general.1618="Gold Helmet" +general.1619="Gold Chestplate" +general.1620="Gold Leggings" +general.1621="Gold Boots" +general.1622="Flint" +general.1623="Raw Porkchop" +general.1624="Cooked Porkchop" +general.1625="Painting" +general.1626="Golden Apple" +general.1627="Golden Apple (Enchanted)" +general.1628="Sign" +general.1629="Wooden Door" +general.1630="Bucket" +general.1631="Water Bucket" +general.1632="Lava Bucket" +general.1633="Minecart" +general.1634="Saddle" +general.1635="Iron Door" +general.1636="Redstone" +general.1637="Snowball" +general.1638="Boat" +general.1639="Leather" +general.1640="Milk Bucket" +general.1641="Clay" +general.1642="Sugar Cane" +general.1643="Paper" +general.1644="Book" +general.1645="Slime Ball" +general.1646="Storage Minecart" +general.1647="Powered Minecart" +general.1648="Egg" +general.1649="Compass" +general.1650="Fishing Rod" +general.1651="Watch" +general.1652="Glowstone Dust" +general.1653="Raw Fish" +general.1654="Raw Salmon" +general.1655="Clownfish" +general.1656="Pufferfish" +general.1657="Cooked Fish" +general.1658="Cooked Salmon" +general.1659="Ink Sack" +general.1660="Rose Red" +general.1661="Cactus Green" +general.1662="Cocoa Bean" +general.1663="Lapis Lazuli" +general.1664="Purple Dye" +general.1665="Cyan Dye" +general.1666="Light Gray Dye" +general.1667="Gray Dye" +general.1668="Pink Dye" +general.1669="Lime Dye" +general.1670="Dandelion Yellow" +general.1671="Light Blue Dye" +general.1672="Magenta Dye" +general.1673="Orange Dye" +general.1674="Bone Meal" +general.1675="Bone" +general.1676="Sugar" +general.1677="Cake" +general.1678="Redstone Repeater" +general.1679="Cookie" +general.1680="Map" +general.1681="Shears" +general.1682="Melon" +general.1683="Pumpkin Seeds" +general.1684="Melon Seeds" +general.1685="Raw Beef" +general.1686="Steak" +general.1687="Raw Chicken" +general.1688="Roast Chicken" +general.1689="Rotten Flesh" +general.1690="Ender Pearl" +general.1691="Blaze Rod" +general.1692="Ghast Tear" +general.1693="Gold Nugget" +general.1694="Water Bottle" +general.1695="Awkward Potion" +general.1696="Thick Potion" +general.1697="Mundane Potion" +general.1698="Regeneration Potion (0:45)" +general.1699="Swiftness Potion (3:00)" +general.1700="Fire Resistance Potion (3:00)" +general.1701="Poison Potion (0:45)" +general.1702="Healing Potion" +general.1703="Weakness Potion (1:30)" +general.1704="Strength Potion (3:00)" +general.1705="Slowness Potion (1:30)" +general.1706="Potion of Leaping (3:00)" +general.1707="Harming Potion" +general.1708="Regeneration Potion II (0:22)" +general.1709="Swiftness Potion II (1:30)" +general.1710="Poison Potion II (0:22)" +general.1711="Healing Potion II" +general.1712="Night Vision Potion (3:00)" +general.1713="Strength Potion II (1:30)" +general.1714="Potion of Leaping (1:30)" +general.1715="Harming Potion II" +general.1716="Water Breathing Potion (3:00)" +general.1717="Invisibility Potion (3:00)" +general.1718="Regeneration Potion (2:00)" +general.1719="Swiftness Potion (8:00)" +general.1720="Fire Resistance Potion (8:00)" +general.1721="Poison Potion (2:00)" +general.1722="Night Vision Potion (8:00)" +general.1723="Weakness Potion (4:00)" +general.1724="Strength Potion (8:00)" +general.1725="Slowness Potion (4:00)" +general.1726="Water Breathing Potion (8:00)" +general.1727="Invisibility Potion (8:00)" +general.1728="Fire Resistance Splash (2:15)" +general.1729="Regeneration Splash (0:33)" +general.1730="Swiftness Splash (2:15)" +general.1731="Poison Splash (0:33)" +general.1732="Healing Splash" +general.1733="Weakness Splash (1:07)" +general.1734="Strength Splash (2:15)" +general.1735="Slowness Splash (1:07)" +general.1736="Harming Splash" +general.1737="Swiftness Splash II (1:07)" +general.1738="Poison Splash II (0:16)" +general.1739="Healing Splash II" +general.1740="Night Vision Splash (2:15)" +general.1741="Strength Splash II (1:07)" +general.1742="Harming Splash II" +general.1743="Water Breathing Splash (2:15)" +general.1744="Invisibility Splash (2:15)" +general.1745="Regeneration Splash (1:30)" +general.1746="Swiftness Splash (6:00)" +general.1747="Fire Resistance Splash (6:00)" +general.1748="Poison Splash (1:30)" +general.1749="Night Vision Splash (6:00)" +general.1750="Weakness Splash (3:00)" +general.1751="Strength Splash (6:00)" +general.1752="Slowness Splash (3:00)" +general.1753="Water Breathing Splash (6:00)" +general.1754="Invisibility Splash (6:00)" +general.1755="Regeneration Splash II (0:16)" +general.1756="Glass Bottle" +general.1757="Spider Eye" +general.1758="Fermented Spider Eye" +general.1759="Blaze Powder" +general.1760="Magma Cream" +general.1761="Brewing Stand" +general.1762="Cauldron" +general.1763="Eye of Ender" +general.1764="Glistering Melon" +general.1765="Spawn Egg" +general.1766="Spawn Creeper" +general.1767="Spawn Skeleton" +general.1768="Spawn Spider" +general.1769="Spawn Zombie" +general.1770="Spawn Slime" +general.1771="Spawn Ghast" +general.1772="Spawn Pigman" +general.1773="Spawn Enderman" +general.1774="Spawn Cave Spider" +general.1775="Spawn Silverfish" +general.1776="Spawn Blaze" +general.1777="Spawn Magma Cube" +general.1778="Spawn Bat" +general.1779="Spawn Witch" +general.1780="Spawn Endermite" +general.1781="Spawn Guardian" +general.1782="Spawn Pig" +general.1783="Spawn Sheep" +general.1784="Spawn Cow" +general.1785="Spawn Chicken" +general.1786="Spawn Squid" +general.1787="Spawn Wolf" +general.1788="Spawn Mooshroom" +general.1789="Spawn Ocelot" +general.1790="Spawn Horse" +general.1791="Spawn Rabbit" +general.1792="Spawn Villager" +general.1793="Bottle o' Enchanting" +general.1794="Fire Charge" +general.1795="Book and Quill" +general.1796="Written Book" +general.1797="Emerald" +general.1798="Item Frame" +general.1799="Carrot" +general.1800="Potato" +general.1801="Baked Potato" +general.1802="Poisonous Potato" +general.1803="Empty Map" +general.1804="Golden Carrot" +general.1805="Skull Item" +general.1806="Skeleton Skull" +general.1807="Wither Skeleton Skull" +general.1808="Zombie Head" +general.1809="Creeper Head" +general.1810="Carrot on a Stick" +general.1811="Nether Star" +general.1812="Pumpkin Pie" +general.1813="Firework Rocket" +general.1814="Firework Star" +general.1815="Enchanted Book" +general.1816="Redstone Comparator" +general.1817="Nether Quartz" +general.1818="Minecart with TNT" +general.1819="Minecart with Hopper" +general.1820="Prismarine Shard" +general.1821="Prismarine Crystals" +general.1822="Raw Rabbit" +general.1823="Cooked Rabbit" +general.1824="Rabbit Stew" +general.1825="Rabbit Foot" +general.1826="Rabbit Hide" +general.1827="Iron Horse Armor" +general.1828="Gold Horse Armor" +general.1829="Diamond Horse Armor" +general.1830="Lead" +general.1831="Name Tag" +general.1832="Minecart with Command Block" +general.1833="Raw Mutton" +general.1834="Cooked Mutton" +general.1835="Spruce Door" +general.1836="Birch Door" +general.1837="Jungle Door" +general.1838="Acacia Door" +general.1839="Dark Oak Door" +general.1840="Music Disk (13)" +general.1841="Music Disk (Cat)" +general.1842="Music Disk (Blocks)" +general.1843="Music Disk (Chirp)" +general.1844="Music Disk (Far)" +general.1845="Music Disk (Mall)" +general.1846="Music Disk (Mellohi)" +general.1847="Music Disk (Stal)" +general.1848="Music Disk (Strad)" +general.1849="Music Disk (Ward)" +general.1850="Music Disk (11)" +general.1851="Music Disk (wait)" +general.1852="MOD" +general.1853="HELPER" +general.1854="MVP+" +general.1855="MVP" +general.1856="VIP+" +general.1857="VIP" +general.1858="%%playerCount%% Players" +general.1859="Choose who to send this bundle to!" +general.1860="Orange" +general.1861="Magenta" +general.1862="Light Blue" +general.1863="Lime" +general.1864="Pink" +general.1865="Gray" +general.1866="Silver" +general.1867="Cyan" +general.1868="Purple" +general.1869="Brown" +general.1870="Player Options: %%player%%" +general.1871="Click here to put name in chat for copy!" +general.1872="Click here to open social menu!" +general.1873="Click here to open userinfo!" +general.1874="Name Copy" +general.1875="Social Menu" +general.1876="UserInfo" +general.1877="Ready?" +general.1878="GO!" +general.1879="Waiting for more players..." +general.1880="Playing %%game%% on %%color%%MC.HYPIXEL.NET" +general.1881="This feature allows you to create a public party that anybody can join, allowing you to easily play games with your viewers!" +general.1882="Public parties are currently in BETA" +general.1883="You must enter a number between 2 and 100!" +general.1884="Select the maximum number of players for your party:" +general.1885="Click to set player cap to %%count%% players" +general.1886="Custom" +general.1887="Click to enter a custom player cap" +general.1888="Your viewers can join the party with %%command%%" +general.1889="/party join %%player%%" +general.1890="Turn chat ON" +general.1891="Turn chat OFF" +general.1892="Change max players" +general.1893="Close party" +general.1894="Drain party" +general.1895="Disband party" +general.1896="You can also use all party commands - see /party help" +general.1897="Wood Sword" +general.1898="Weakness" +general.1899="Invisibility" +general.1900="Confusion" +general.1901="Blindness" +general.1902="Fire Resistance" +general.1903="Poison" +general.1904="Absorption" +general.1905="Saturation" +general.1906="Hunger" +general.1907="CLICK TO PLAY" +general.1908="Click to get the link!" +general.1909="Bug reports are throttled! You may submit a new one for this server in %%seconds%% seconds." +general.1910="Generating bug report..." +general.1911="Oops! Something went wrong while creating your bug report! Please try again later." +general.1912="Your bug report form has been created!\n" +general.1913="Click [HERE] to fill it in once you're ready." +general.1914="Complete your bug report on our website!" +general.1915="Click to toggle!" +general.1916="Lifetime" +general.1917="Monthly" +general.1918="Weekly" +general.1919="Mushroom Cow" +general.1920="Blood effect enabled!" +general.1921="Blood effect disabled!" +general.1922="Claim your reward in the lobby!" +general.1923="You are now Hypixel Level %%level%%!" +general.1924="LEVEL UP!" +general.1925="%%multipier%%x Coin Multiplier Unlocked!" +general.1926="LEVEL UP" +general.1927="+%%amount%% Souls" +general.1928="Pig" +general.1929="Iron Golem" +general.1930=" year" +general.1931=" month" +general.1932=" week" +general.1933=" weeks" +general.1934=" day" +general.1935=" hour" +general.1936=" minute" +general.1937=" second" +general.1938="Housing Themes" +general.1939="Morphs" +general.1940="Gadgets" +general.1941="Hats" +general.1942="Pets" +general.1943="Suit Pieces" +general.1944="Gestures" +general.1945="Emotes" +general.1946="Cloaks" +general.1947="Common" +general.1948="Rare" +general.1949="Epic" +general.1950="Legendary" +general.1951="d " +general.1952="h " +general.1953="m " +general.1954="s" +general.1955="Skull King" +general.1956="Depth Strider" +general.1957="Hold up! You can't use %%name%% as your nickname!" +general.1958="TNT Wizard Challenge" +general.1959="Missing arguments! Usage: %%usage%%" +general.1960="Cat" +general.1961="Chicken" +general.1962="Cow" +general.1963="Horse" +general.1964="Rabbit" +general.1965="Sheep" +general.1966="Villager" +general.1967="Wolf" +general.1968="Holiday Exclusive" +general.1969="Power" +general.1970="Regen" +general.1971="Splash Potion" +general.1972="Splash Potions" +general.1973="Double Jumps" +general.1974="Double Jump" +general.1975="Coin" +general.1976="Showing %%name%% positions!" +general.1977="Minimap" +general.1978="Use this Map to navigate in the world." +general.1979="This player can't be mounted right now!" +general.1980="You can't use /me while muted." +general.1981="You skipped too many checkpoints!" +general.1982="An error occurred saving your results, please report this to a staff member: %%time%%" +general.1983="As murderer, kill the detective within 15 seconds of receiving your weapon" +general.1984="Have the murderer swing his sword at you while you are invincible" +general.1985="???" +general.1986="Secret Achievement" +general.1987="Win %s game as murderer" +general.1988="Win %s game as innocent or detective without dying" +general.1989="Total Kills: " +general.1990="Total Wins: " +general.1991="Coins: " +general.1992="%%counter%%. %%value%%" +general.1993="Shop" +general.1994="My Cosmetics" +general.1995="Click to browse!" +general.1996="Projectile Trail" +general.1997="Projectile Trails" +general.1998="Victory Dance" +general.1999="Victory Dances" +general.2000="Final Kill Effect" +general.2001="Final Kill Effects" +general.2002="Glyph" +general.2003="Glyphs" +general.2004="Spray" +general.2005="Sprays" +general.2006="Last Word" +general.2007="Last Words" +general.2008="Knife Skin" +general.2009="Knife Skins" +general.2010="Kill Notes" +general.2011="Kill Note" +general.2012="Not enough space to perform that %%category%%!" +general.2013="Cool Dance" +general.2014="Clapping" +general.2015="Good Job!" +general.2016="Nice One" +general.2017="GGWP!" +general.2018="Congratulate your opponents on a good game with this clapping gesture!" +general.2019="Selecting this option disables your %%category%%." +general.2020="Gesture" +general.2021="Mind Blown" +general.2022="Mind...BLOWN!" +general.2023="Blow other players' minds with this impressive gesture!" +general.2024="Selects the %%name%% %%category%%." +general.2025="Heart" +general.2026="Angry Face" +general.2027="Creeper Scream" +general.2028="Cry Face" +general.2029="No 1" +general.2030="RIP" +general.2031="Skull" +general.2032="Smiley Face" +general.2033="Shock Face" +general.2034="Thumbs Down" +general.2035="Thumbs Up" +general.2036="Winky Face" +general.2037="Spectrum" +general.2038="Hi" +general.2039="Scream Face" +general.2040="Storm" +general.2041="Sword" +general.2042="Yes" +general.2043="Burn" +general.2044="Daisy" +general.2045="No" +general.2046="Bronze Shield" +general.2047="Silver Shield" +general.2048="Gold Shield" +general.2049="Star" +general.2050="Select the particle images that displays above your head when activated." +general.2051="Blood Explosion" +general.2052="Burning Shoes" +general.2053="Killing an enemy will set your feet on fire." +general.2054="Camp Fire" +general.2055="Killing an enemy will place down a campfire." +general.2056="Cookie Fountain" +general.2057="Killing an enemy will let cookies sprinkle out of you." +general.2058="Experience Orb" +general.2059="Killing an enemy will make it rain experience on top of his corpse." +general.2060="Final Smash" +general.2061="Firework" +general.2062="Killing an enemy will launch fireworks." +general.2063="Head Rocket" +general.2064="Heart Aura" +general.2065="Killing an enemy will spawn lots of love." +general.2066="Select the effect that triggers when you kill the murderer or the last innocent." +general.2067="Lightning Strike" +general.2068="Killing an enemy will wake up Thor." +general.2069="Piñata" +general.2070="Rekt" +general.2071="%%killer%% has #rekt %%deadedededed%% here" +general.2072="Killing an enemy will drop a hologram remembering your victory." +general.2073="Smiley" +general.2074="Killing an enemy will show your smiley in the air." +general.2075="Squid Missile" +general.2076="Killing an enemy will spawn a fellow companion." +general.2077="Killing an enemy will summon a vortex!" +general.2078="Tornado" +general.2079="Change your projectile particle trail effect." +general.2080="Magic" +general.2081="Notes" +general.2082="Green Star" +general.2083="Ender" +general.2084="Potion" +general.2085="Blue Dust" +general.2086="Purple Dust" +general.2087="Angry Villager" +general.2088="Random" +general.2089="Hypixel Logo" +general.2090="Bed Breaker" +general.2091="Bed Shield" +general.2092="GG WP" +general.2093="I Love You" +general.2094="Sorry" +general.2095="Thanks" +general.2096="Bye Bye" +general.2097="Golem Riding" +general.2098="Invisibility Potion" +general.2099="Leaping Potion" +general.2100="TNT Drop" +general.2101="VIP" +general.2102="VIP+" +general.2103="MVP" +general.2104="MVP+" +general.2105="Select the spray that you can use in-game to mark your territory." +general.2106="Anvil Rain" +general.2107="Special Fireworks" +general.2108="Dragon Rider" +general.2109="%%name%% the Dragon Rider" +general.2110="Fireworks" +general.2111="Guardians" +general.2112="Meteor Shower" +general.2113="Choose the way that you celebrate when you win a game." +general.2114="Wither Rider" +general.2115="%%name%% the Wither Rider" +general.2116="%%name%%'s Last Words:" +general.2117="Currently Selected:" +general.2118="Unlocked:" +general.2119="Click to view!" +general.2120="(Page %%number%%)" +general.2121="Go to page %%number%%" +general.2122="Previous Page" +general.2123="Next Page" +general.2124="COMMON" +general.2125="RARE" +general.2126="EPIC" +general.2127="Lowest rarity first" +general.2128="Highest rarity first" +general.2129="Sorts by rarity: %%name%%" +general.2130="Z to A" +general.2131="A to Z" +general.2132="Sorts by name from %%name%%." +general.2133="Next sort: %%next%%" +general.2134="Left click to use!" +general.2135="Owned items first: %%color%%%%option%%" +general.2136="Right click to toggle!" +general.2137="Sorted by: %%method%%" +general.2138="Right-Click to preview!" +general.2139="Requires Network Level %%level%%" +general.2140="Unlocked with %%rank%%!" +general.2141="Unlocked on the store!" +general.2142="SELECTED!" +general.2143="Click to select!" +general.2144="Hardcore" +general.2145="Assassins" +general.2146="You skipped a checkpoint!" +general.2147="Teleported you to the start of the parkour!" +general.2148="You teleported" +general.2149="Speed" +general.2150="Resistance" +general.2151="Haste" +general.2152="Strength" +general.2153="Regeneration" +general.2154="Unknown" +general.2155="Auto Queue" +general.2156="Toggles whether or not you will auto queue after a game ends." +general.2157="Silver Wool" +general.2158="Purple Stained Clay" +general.2159="Magenta Stained Clay" +general.2160="Pink Stained Clay" +general.2161="Red Stained Clay" +general.2162="Orange Stained Clay" +general.2163="Yellow Stained Clay" +general.2164="Lime Stained Clay" +general.2165="Green Stained Clay" +general.2166="Cyan Stained Clay" +general.2167="Light Blue Stained Clay" +general.2168="Blue Stained Clay" +general.2169="Brown Stained Clay" +general.2170="Black Stained Clay" +general.2171="Gray Stained Clay" +general.2172="Silver Stained Clay" +general.2173="White Stained Clay" +general.2174="Purple Stained Glass Pane" +general.2175="Magenta Stained Glass Pane" +general.2176="Pink Stained Glass Pane" +general.2177="Red Stained Glass Pane" +general.2178="Orange Stained Glass Pane" +general.2179="Yellow Stained Glass Pane" +general.2180="Lime Stained Glass Pane" +general.2181="Green Stained Glass Pane" +general.2182="Cyan Stained Glass Pane" +general.2183="Light Blue Stained Glass Pane" +general.2184="Blue Stained Glass Pane" +general.2185="Brown Stained Glass Pane" +general.2186="Black Stained Glass Pane" +general.2187="Gray Stained Glass Pane" +general.2188="Silver Stained Glass Pane" +general.2189="White Stained Glass Pane" +general.2190="Purple Stained Glass" +general.2191="Magenta Stained Glass" +general.2192="Pink Stained Glass" +general.2193="Red Stained Glass" +general.2194="Orange Stained Glass" +general.2195="Yellow Stained Glass" +general.2196="Lime Stained Glass" +general.2197="Green Stained Glass" +general.2198="Cyan Stained Glass" +general.2199="Light Blue Stained Glass" +general.2200="Blue Stained Glass" +general.2201="Brown Stained Glass" +general.2202="Black Stained Glass" +general.2203="Gray Stained Glass" +general.2204="Silver Stained Glass" +general.2205="White Stained Glass" +general.2206="Purple Carpet" +general.2207="Magenta Carpet" +general.2208="Pink Carpet" +general.2209="Red Carpet" +general.2210="Orange Carpet" +general.2211="Yellow Carpet" +general.2212="Lime Carpet" +general.2213="Green Carpet" +general.2214="Cyan Carpet" +general.2215="Light Blue Carpet" +general.2216="Blue Carpet" +general.2217="Brown Carpet" +general.2218="Black Carpet" +general.2219="Gray Carpet" +general.2220="Silver Carpet" +general.2221="White Carpet" +general.2222="Cocoa Bean [Brown Dye]" +general.2223="Get the most kills in Assassins mode." +general.2224="Select from a set of gestures you can use in-game by typing out /gesture to taunt other players." +general.2225="Map Selector (%%mode%%)" +general.2226="Purchase " +general.2227="Return to previous menu." +general.2228="Purchase %%name%% for %%cost%% coins" +general.2229="Confirm your purchase" +general.2230="Close" +general.2231="Shop" +general.2232="You purchased %%item%%!" +general.2233="Click to equip!" +general.2234="Something went wrong when processing. Please try switching lobbies" +general.2235="Anvils will rain from the sky." +general.2236="Write your name in the sky!" +general.2237="Ride a Dragon capable of destroying the map." +general.2238="Celebrate with a splendid show fireworks show!" +general.2239="Perform a Guardian summoning ritual." +general.2240="A meteor shower will rain down from the sky." +general.2241="Ride a Wither straight from the end - click to shoot Wither Skulls." +general.2242="Exiting Spectator mode" +general.2243="Spectating %%player%%" +general.2244="LEFT CLICK for menu SNEAK to exit" +general.2245="You will now by default use Third Person spectating!" +general.2246="You will now by default use First Person spectating!" +general.2247="Disable First Person" +general.2248="Enable First Person" +general.2249="Click to enable first person spectating when using the compass!" +general.2250="Click to disable first person spectating when using the compass!" +general.2251="You can also right-click a player to spectate them in first person." +general.2252="Right-click to report!" +general.2253="You are not allowed to join this server." +general.2254="The player you were previously spectating is no longer alive, so you're now spectating %%player%%." +general.2255="Close" +general.2256="%%playerCount%% Player" +general.2257="Play again?" +general.2258="Left-click to spectate!" +general.2259=" %%rank%% ends on %%currentEnd%%" +general.2260="Tag Selection" +general.2261="Pie" +general.2262="You've received the following items:" +general.2263="and %%count%% more" +general.2264="Click to view all the items in your purchase" +general.2265="If you have any problems, %%url%%contact support%%url%%." +general.2266="Click to contact support" +general.2267="All items:" +general.2268="You have already redeemed this for this month!" +general.2269="Your purchase has been processed!" +general.2270="You must purchase %%rank%% to use this!" +general.2271="You cannot use this here." +general.2272="You selected %%value%%!" +general.2273="You don't own that item!" +general.2274="Playing" +general.2275="RELEASED!" +general.2276="NEW PTL GAME!" +general.2277="Currently unavailable!" +general.2278="Unavailable for purchase!" +general.2279="Requirements not matched!" +general.2280="Bring 66 pumpkins back to any Shopkeeper. Pumpkins will drop from Player kills during Halloween" +general.2281="On sale for a limited time!" +general.2282="+ONE TIME REWARD: %%reward%%" +general.2283="+%%reward%%" +general.2284="Happy Pumpkin Island Topper" +general.2285="You cannot do the parkour while wearing a Suit" +general.2286="It seemed to me you got stuck outside the world border, so I teleported you to spawn!" +general.2287="That feature is disabled in this lobby." +general.2288="%%game%% Shop" +general.2289="You selected %%item%%!" +general.2290="https://store.hypixel.net" +general.2291="UPDATED!" +general.2292="Spawn tons more of yourself and have them twerk." +general.2293="The fear doesn't actually creep in until you're alone in the dark and think of this victory dance." +general.2294="Ghast Rider" +general.2295="Twerk Apocalypse" +general.2296="Cold Snap" +general.2297="Yeehaw" +general.2298="Night Shift" +general.2299="Terror" +general.2300="Rainbow Dolly" +general.2301="Spawn Dolly the sheep. When you hit Dolly, she clones herself." +general.2302="Set it to day, set it to night, repeat, like a god." +general.2303="Ride a horse like it's 1876." +general.2304="Chill an area around you to absolute zero." +general.2305="You have %%amount%% unclaimed achievement rewards!" +general.2306="Oh no!" +general.2307="Achievement not found!" +general.2308="No menu found for this achievement!" +general.2309="Unlocked with the %%count%% points Achievement Reward!" +general.2310="This can be unlocked through Achievement Rewards!" +general.2311="Re-Center" +general.2312="This player's profile is unavailable!" +general.2313="DONE!" +general.2314="You didn't enter a search query!" +general.2315="No Sort" +general.2316="Unlocked First" +general.2317="Locked First" +general.2318="Completion sort: %%option%%" +general.2319="Right click to cycle!" +general.2320="Click to open the Achievement Rewards menu" +general.2321="You have %%amount%% unclaimed achievement rewards!" +general.2322="You have %%amount%% unclaimed achievement reward!" +general.2323="Cloaks can be equipped in the Collectibles menu on your hotbar." +general.2324="Assorted cosmetics can be equipped in the Collectibles menu on your hotbar." +general.2325="Special" +general.2326="Banners can be equipped in the Collectibles menu on your hotbar." +general.2327="Awesome" +general.2328="Major" +general.2329="Minor" +general.2330="%%reward%% %%what%%" +general.2331="Achievement Reward" +general.2332="Hats can be equipped in the Collectibles menu on your hotbar." +general.2333="+%%name%%" +general.2334="Player: %%name%%" +general.2335="Hypixel Achievements Completion" +general.2336="Something went wrong while claiming your reward!" +general.2337="Starter Tier" +general.2338="Gold Tier" +general.2339="Lapis Tier" +general.2340="Redstone Tier" +general.2341="Emerald Tier" +general.2342="Diamond Tier" +general.2343="You don't have enough points to claim this reward!" +general.2344="Claimed reward for %%points%% achievement points!" +general.2345="You already claimed this reward!" +general.2346="Achievement Rewards" +general.2347="Unlock exclusive rewards for achievement hunting efforts" +general.2348="Required Points: %%points%%" +general.2349="Reward: " +general.2350="Rewards: " +general.2351="You have already claimed this reward!" +general.2352="You can't claim this yet!" +general.2353="Click to recenter the menu around your last available reward" +general.2354="Scroll by 1" +general.2355="Go to end" +general.2356="Go to start" +general.2357="Scroll Right" +general.2358="Scroll Left" +general.2359="Left Click: %%action%%" +general.2360="Right Click: %%action%%" +general.2361="%s+%s%d%s Hypixel Experience" +general.2362="Click to open %%holder%% achievements!" +general.2363="Points: %%points%%" +general.2364="Progress: %%progress%%" +general.2365="Achievement unlocked!" +general.2366="Achievement locked!" +general.2367="Tier unlocked!" +general.2368="Tier locked!" +general.2369="Go to Tiered Achievements" +general.2370="Click to view %%title%% Tiered Achievements" +general.2371="Challenge Achievements" +general.2372="Tiered Achievements" +general.2373="Go to Challenge Achievements" +general.2374="Click to view %%title%% Challenge Achievements" +general.2375="Unlocked achievements first: %%option%%" +general.2376="Sorts by name from A to Z" +general.2377="Most completed tiers" +general.2378="Sorts by most completed tiers." +general.2379="Highest Points" +general.2380="Sorts by achievement points reward from highest to lowest." +general.2381="Lowest Points" +general.2382="Sorts by achievement points reward from lowest to highest." +general.2383="Least completed tiers" +general.2384="Sorts by least completed tiers." +general.2385="Sorts by name from Z to A" +general.2386="Classic Games" +general.2387="Total Completion" +general.2388="Click to view achievements!" +general.2389="Classic Achievements" +general.2390="Challenge Achievement" +general.2391="Tiered Achievement" +general.2392="Search results: " +general.2393="Couldn't find any matching achievement!" +general.2394="Click for more %%name%% achievements!" +general.2395="Enter your search query!" +general.2396="Search" +general.2397="Search for an achievement by name, description or points value." +general.2398="%%title%% Challenge Achievements" +general.2399="%%title%% Tiered Achievements" +general.2400="Unlocked: %%count%%/%%total%% (%%percent%%)" +general.2401="Points: %%count%%/%%total%% (%%percent%%)" +general.2402="%%title%% Achievements" +general.2403="Challenge achievements may be completed a single time." +general.2404="Tiered achievements are completed over multiple tiers." +general.2405="Banners" +general.2406="Achievements" +general.2407="Achievement Rewards" +general.2408="+1 Totem Slot (%%height%% total)" +general.2409="%%part%% Totem Part" +general.2410="Customize your Achievement Totem with new parts in the achievement rewards menu." +general.2411="+Legendary Achievement Totem Companion" +general.2412="The Achievement Totem is a special companion which can be customized in the achievement rewards menu." +general.2413="You haven't unlocked this totem slot yet!" +general.2414="Selected: %%type%%" +general.2415="Click to pick a part!" +general.2416="This slot is unlocked with the %%required%% points achievement reward!" +general.2417="Totem Customizer" +general.2418="Customize your Achievements Totem!" +general.2419="With %%required%% points you may unlock the Achievements Totem companion." +general.2420="Check back then to customize its looks!" +general.2421="You haven't unlocked the Achievements Totem yet!" +general.2422="Totem Part: %%slot%%" +general.2423="You haven't unlocked this part yet!" +general.2424="You selected the %%what%% part for the %%slot%%!" +general.2425="Part locked!" +general.2426="Required points: %%points%%" +general.2427="Rarity: %%name%%" +general.2428="Birdy Head" +general.2429="Arrow Body" +general.2430="Snaky Body" +general.2431="Weirdo Body" +general.2432="First Slot" +general.2433="Second Slot" +general.2434="Third Slot" +general.2435="Fourth Slot" +general.2436="Fifth Slot" +general.2437="Sixth Slot" +general.2438="Seventh Slot" +general.2439="Make your way to the stars with this special achievements totem. You can customize this companion in the Achievement Rewards menu!" +general.2440="Achievements Totem" +general.2441="Click to untrack!" +general.2442="Click to track!" +general.2443="Achievements Tracking" +general.2444="You aren't tracking any achievements." +general.2445="Browse through tiered achievements and click the ones you want to track." +general.2446="There's nothing here!" +general.2447="Left click to untrack!" +general.2448="Right click to view %%holder%% menu!" +general.2449="You need at least %%rank%% to use the achievements tracking feature!" +general.2450="Achievements Tracking %%rank%%" +general.2451="Track achievements to access them quickly in this menu and get instant feedback of your progress" +general.2452="%%achievement%% Progress: %%progress%%" +general.2453="Tracking messages" +general.2454="Enabled: %%yesNo%%" +general.2455="Shows your progress every time you complete an action toward an achievement" +general.2456="Scroll a lot" +general.2457="Claim the %%required%% points reward to unlock the Achievements Totem companion." +general.2458="Totem Color: %%slot%%" +general.2459="You haven't unlocked this color yet!" +general.2460="You selected the %%what%% color for the %%slot%%!" +general.2461="Part: %%type%%" +general.2462="Color: %%color%%" +general.2463="Left click to pick a part!" +general.2464="Right click to pick a color!" +general.2465="Dark" +general.2466="None!" +general.2467="Chiseled Body" +general.2468="Corner Body" +general.2469="Cube Body" +general.2470="Grizzly Body" +general.2471="Lock Body" +general.2472="Reactor Body" +general.2473="Happy Head" +general.2474="Pong Body" +general.2475="Window Body" +general.2476="Bad Morning Head" +general.2477="Sad Head" +general.2478="Connection Body" +general.2479="Kitty Head" +general.2480="Retro Head" +general.2481="A Body" +general.2482="Retro Body" +general.2483="B Body" +general.2484="Overgrown Head" +general.2485="Festive Body" +general.2486="Daisy Body" +general.2487="Rosa Body" +general.2488="Grassy Body" +general.2489="Steampunk Head" +general.2490="Tubular Body" +general.2491="Furnace Body" +general.2492="Core Body" +general.2493="Overgrown" +general.2494="Steampunk" +general.2495="Retro" +general.2496="Style: %%color%%" +general.2497="Right click to pick a style!" +general.2498="Totem Style: %%slot%%" +general.2499="Totem Style" +general.2500="You haven't unlocked this style yet!" +general.2501="You selected the %%what%% style for the %%slot%%!" +general.2502="Style not unlocked yet!" +general.2503="%%style%% Totem Style" +general.2504="Totem styles allow you to change the color and theme of your totem. Each new style will be available for all of your totem parts." +general.2505="You need at least %%rank%% to use the tracking feature!" +general.2506="You cannot message this player." +general.2507="Current State: %%color%%%%state%%" +general.2508="Click to change to %%color%%%%state%%!" +general.2509="%%setting%% is now set to %%color%%%%state%%!" +general.2510="Max" +general.2511="High" +general.2512="Medium" +general.2513="Low" +general.2514="Staff and friends can message you." +general.2515="Staff, friends, and guild members can message you." +general.2516="Staff, friends, guild members, and party members can message you." +general.2517="Anyone can message you." +general.2518="Staff and friends can send you party invites." +general.2519="Staff, friends, and guild members can send you party invites." +general.2520="Anyone can send you party invites." +general.2521="Staff and friends can send you guild invites." +general.2522="Staff, friends, and party members can send you guild invites." +general.2523="Anyone can send you guild invites." +general.2524="Only staff can send you friend requests." +general.2525="Staff and guild members can send you friend requests." +general.2526="Staff, guild members, and party members can send you friend requests." +general.2527="Anyone can send you friend requests." +general.2528="Profanity Level" +general.2529="Change how strong the profanity filter should censor chat." +general.2530="Private Message Privacy" +general.2531="Party Invite Privacy" +general.2532="Guild Invite Privacy" +general.2533="Friend Request Privacy" +general.2534="Change who can send you party invites." +general.2535="Change who can send you guild invites." +general.2536="Change who can send you friend requests." +general.2537="Strong Filter" +general.2538="Weak Filter" +general.2539="Off" +general.2540="There was an issue processing your request. Please try again later!" +general.2541="You" +general.2542="Merry Christmas! Gifts have appeared around the map!" +general.2543="There is a 1 second cooldown reward claims!" +general.2544="This part won't be displayed." +general.2545="Special Daily: Skywars North Pole" +general.2546="COMMON Gift" +general.2547="RARE Gift" +general.2548="EPIC Gift" +general.2549="LEGENDARY Gift" +general.2550="Find 30 chests scattered throughout the maps" +general.2551="Real Santa" +general.2552="Find all lobby presents in every lobby." +general.2553="Christmas 2017" +general.2554="Hey it's not Christmas anymore (or yet)!" +general.2555="Hypixel Presents" +general.2556="Find the presents scattered across the lobbies!" +general.2557="Presents will reward you with coins and experience." +general.2558="Status:" +general.2559="Main Lobby" +general.2560="Find all presents to earn the Real Santa achievement!" +general.2561="Seasonal" +general.2562="Seasonal Achievements" +general.2563="Joe the Penguin Animated Hat" +general.2564="Sammy the Cookie Animated Hat" +general.2565="Comet the Reindeer Animated Hat" +general.2566="+%%amount%% %%name%%" +general.2567="The Advent Proof Gadget" +general.2568="Advent Calendar" +general.2569="Merry Christmas" +general.2570="Speak to the Christmas Guide in the Main Lobby" +general.2571="The Hunt Begins" +general.2572="Find two lobby presents" +general.2573="Bring items back to every Christmas character in a single Bed Wars game" +general.2574="Christmas Quester" +general.2575="Complete 5 Christmas Quests" +general.2576="Use /booster to consume your personal boosters, which will temporarily boost the amount of coins you earn" +general.2577="+%%amount%% Daily Reward Token" +general.2578="Use Reward Tokens at the Delivery Man in any lobby to claim extra daily rewards" +general.2579="Advent Calendar 2017" +general.2580="HAPPY HOLIDAYS FROM HYPIXEL" +general.2581="Click to open the Advent Calendar menu" +general.2582="You may claim today's Advent Calendar reward!\nClick here to claim!" +general.2583="Hypixel Advent Calendar" +general.2584="Hypixel Advent Calendar %%year%%" +general.2585="Advent Calendar %%year%%" +general.2586="Days until Christmas: IT'S HAPPENING!" +general.2587="Days until Christmas: %%remaining%%" +general.2588="Hey it's not the time for presents anymore (or yet)!" +general.2589="Festive Guide" +general.2590="HAPPY HOLIDAYS" +general.2591="The Holiday Man" +general.2592="The Spooky Man" +general.2593="The Holiday Man" +general.2594="The Spooky Man" +general.2595="You found %%coins%% Coins in that present!" +general.2596="You found %%xp%% Hypixel Experience in that present!" +general.2597="CLICK HERE to learn more about the presents hunt!" +general.2598="Also try: /presents" +general.2599="The Delivery Man" +general.2600="You found all presents in this lobby!" +general.2601="You found a Main Lobby present! %%count%%" +general.2602="You found a present! %%count%%" +general.2603="Holiday Event" +general.2604="You found %%coins%% %%gametype%% Coins in that present!" +general.2605="You have already found this present!" +general.2606="Unlocked with the %%count%% points Achievement Reward!" +general.2607="Could not check your guild, please try again later!" +general.2608="Ride a Wither straight from the nether - click to shoot Wither Skulls." +general.2609="There was an error! Try that again!" +general.2610="+%%amount%% Tokens" +general.2611="To %%menu%%" +general.2612="Use a random %%cosmetic%%!" +general.2613="Leaving queue!" +general.2614="Use this feature to easily find a specific cosmetic item." +general.2615="Finish a game in the top 3." +general.2616="Top 3 Challenge" +general.2617="Guesser Challenge" +general.2618="Guess 5 themes correctly in Guess The Build mode." +general.2619="Unlock the "Master Builder Hat"" +general.2620="Your %%rank%% rank" +general.2621="Your %%rank%% Rank will expire in %%time%%." +general.2622="To keep %%rank%% and all your features, buy more days on the store." +general.2623="Your %%rank%% Rank Addon will expire in %%time%%. After this, your rank will be downgraded back to %%old%%." +general.2624="To keep %%rank%% and all your features, buy more days on the store:" +general.2625="VISIT STORE" +general.2626="Expires in: %%time%%" +general.2627="%%player%% cannot be a Guild Master as they have not bought a rank" +general.2628="Social Media Rewards" +general.2629="Click to view all available Social Media Rewards!" +general.2630="We've noticed that you're still nicknamed, whilst you're nicknamed as a non-MVP+ player, your particle pack won't appear!" +general.2631="Achievement Points Cloak" +general.2632="Guilds" +general.2633="Parties" +general.2634="Parkour challenge started! Use /parkour reset to restart or /parkour checkpoint to teleport to the last checkpoint!" +general.2635="You finished this part of the parkour in %%time%% (personal best: %%pb%%)." +general.2636="You finished this part of the parkour in %%time%% and beat your personal best of %%pb%%!" +general.2637="You finished this part of the parkour in %%time%%." +general.2638="Achieve a Win Streak of %s" +general.2639="Classic Games Achievements" +general.2640="Derperino" +general.2641="Sniff" +general.2642="Squeak" +general.2643="Easter Egg" +general.2644="Easter Eggs" +general.2645="Bunny Explosion" +general.2646="Killing an enemy will spawn easter bunnies around them." +general.2647="Chicken Tower" +general.2648="Killing an enemy will spawn chicken that will stack up to a tower." +general.2649="Easter Egg Theft" +general.2650="Killing an enemy will make them drop easter eggs." +general.2651="Peep!" +general.2652="Egg Delivery" +general.2653="Chocolate Feast" +general.2654="Easter Creeper" +general.2655="The Great Egg Hunt" +general.2656="Wrong Eggs" +general.2657="Easter Bunny" +general.2658="Easter Bunnies" +general.2659="Spawns a bunch of easter bunnies laying eggs." +general.2660="Basket" +general.2661="Quick paced 1v1, 2v2 and 4v4 Duels!" +general.2662="∙ UHC Duels" +general.2663="∙ SkyWars Duels" +general.2664="∙ Mega Walls Duels" +general.2665="∙ Combo Duels" +general.2666="∙ NoDebuff Duels" +general.2667="∙ Classic Duels" +general.2668="∙ Bow Duels" +general.2669="Unlock: %%item%%" +general.2670="Cost: %%coins%%" +general.2671="Potion of Strength +20% (%%seconds%%s)" +general.2672="Splash Potion of Fire Resistance" +general.2673="Splash Potion of Speed" +general.2674="Splash Potion of Speed II" +general.2675="Splash Potion of Regeneration" +general.2676="Potion of Regeneration (16s)" +general.2677="Champion's Diamond Sword" +general.2678="Splash Potion of Heal" +general.2679="White Leather Helmet" +general.2680="White Leather Boots" +general.2681="Fire Aspect" +general.2682="Fire Protection" +general.2683="Potion of Regeneration" +general.2684="Splash Potion of Poison and Slow" +general.2685="Splash Potion of Blindness" +general.2686="Potion of Increase Damage" +general.2687="Completing quests and challenges\nwill reward you with %%coins%%, %%exp%% and more!" +general.2688="Best Overall Win Streak" +general.2689="Score" +general.2690="Pro Mode Wins" +general.2691="Guess The Build Wins" +general.2692="Correct Guesses" +general.2693="Total Votes" +general.2694="Win Bonus" +general.2695="All Modes" +general.2696="Queueing you to the server %%player%% is on ..." +general.2697="∙ OP Duels" +general.2698="Achievement Points: %%points%%" +general.2699="Top Hypixel Guilds" +general.2700="Guild Experience" +general.2701="%%time%% %%suffix%%" +general.2702="Get 5 FK's or FA's in a period of 7 seconds as Herobrine" +general.2703="Get 200 total FK's or FA's from behind as Enderman" +general.2704="Get 25 FK's or FA's from over 50 blocks as Skeleton" +general.2705="Effect 5 allies with a single refreshing sip during deathmatch as Cow" +general.2706="EMP" +general.2707="Affect 6 enemies with a single A-23 Protocol" +general.2708="Siphon 8000 energy from killing enemies" +general.2709="Hold 12 looted potions in your inventory as Renegade" +general.2710="Deal 50,000 wither damage total as Dreadlord" +general.2711="Get 3 Final Kills in 6 seconds as Dreadlord" +general.2712="Get 10 total FK's or FA's with your nest spiders as Spider" +general.2713="Craft an iron sword and get 7 FK's with that sword without dying as Spider" +general.2714="+%%amount%% Mega Walls Mythic Favor" +general.2715="Get 15 total FK's while under 5 HP as Werewolf" +general.2716="%%points%% Achievement Points" +general.2717="Reward:" +general.2718="Win a game as Phoenix with yourself and a teammate who you've resurrected, still alive" +general.2719="Kill 500 players while both you and them are in water" +general.2720="You placed %%block%% for %%name%%!" +general.2721="%%builder%% placed %%block%% for you!" +general.2722="Did not find that player!" +general.2723="a Rose" +general.2724="some explosive" +general.2725="spiky stuff" +general.2726="a cake" +general.2727="something green" +general.2728="Pick a Mode" +general.2729="You cannot invite yourself to Duel!" +general.2730="Can't find a player by the name of '%%target%%'" +general.2731="Click to invite %%player%% to %%name%%!" +general.2732="Play %%name%%" +general.2733="%%count%% currently playing!" +general.2734="Play %%name%%" +general.2735="%%name%% has %%mode%% requests disabled!" +general.2736="Spawn the mystery mob" +general.2737="Play Duels" +general.2738="DUELS %%mode%%" +general.2739="This Duels mode will not count towards %%mode%% stats, achievements or quests." +general.2740="Click to play %%name%%!" +general.2741="NEW" +general.2742="RETURNING MAP!" +general.2743="Katniss Everdeen Style" +general.2744="Not enough players joined so the game did not start. Please try again later." +general.2745="Not enough players joined! Start cancelled." +general.2746="Minimum player count of %%amount%% players is required for the game to start." +general.2747="Unable to meet minimum player requirements, Please try to queue again later." +general.2748="Minimum player count hasn't been met. Sending message to lobbies." +general.2749="Minimum player count hasn't been met. Sending message to lobbies and increasing timer." +general.2750="Loading..." +general.2751="Failed to load" +general.2752="Limit Size" +general.2753="Click to filter Guilds by how many members they have" +general.2754="No Limit" +general.2755="Shows all Guilds, regardless of how many members they have." +general.2756="%%amount%% Players" +general.2757="Shows only Guilds with %%amount%% players." +general.2758="We're already refreshing the guild listing!" +general.2759="Apply Filters" +general.2760="Sort Results" +general.2761="Choose how you want the results to be sorted." +general.2762="Sort by Members" +general.2763="Shows Guilds with most players first" +general.2764="Shows Guilds with fewest players first" +general.2765="Sort by Guild Level" +general.2766="Shows Guilds with the highest level first" +general.2767="Shows Guilds with the lowest level first" +general.2768="Sort Randomly" +general.2769="Shows Guilds in no apparent order" +general.2770="Choose Games" +general.2771="Click to filter Guilds by the games they play.\nWe'll only show you guilds that play all the games you select." +general.2772="SELECTED" +general.2773="Click to select" +general.2774="Save and Go Back" +general.2775="Default Rank" +general.2776="This rank is already the default rank! To change this, select another rank to be the default rank." +general.2777="Default Rank" +general.2778="Set this to the default rank" +general.2779="You can't create any more ranks" +general.2780="You can only have up to %%amount%% custom guild ranks!" +general.2781="Create a new rank" +general.2782="Click to create a new rank" +general.2783="You can't add any more ranks!" +general.2784="There was an error opening the permissions menu! (%%error%%)" +general.2785="You don't have a guild!" +general.2786="Enter your new" +general.2787="rank's name here!" +general.2788="The rank's name must be at least 2 characters!" +general.2789="Guild Master" +general.2790="GUILDMASTER" +general.2791="You can't call a new rank this!" +general.2792="The rank's name must only contain numbers, letters or spaces!" +general.2793="You've already got a rank with this name!" +general.2794="Created rank %%name%%!" +general.2795="Modify Guild Name" +general.2796="Change the guild's name" +general.2797="Modify Guild MOTD" +general.2798="Change the guild's message of the day" +general.2799="Modify Guild Tag" +general.2800="Change the guild's tag" +general.2801="Change ranks" +general.2802="Promote or demote members (up to their own rank)" +general.2803="Guild Finder options" +general.2804="Change how the guild is shown in the Guild Finder, if at all" +general.2805="Officer Chat" +general.2806="Send and receive messages in the officer chat" +general.2807="Kick Members" +general.2808="Kick members from the guild" +general.2809="Mute Members" +general.2810="Mute guild members" +general.2811="Invite members" +general.2812="Invite members to the guild" +general.2813="You can't modify the %%rank%% rank!" +general.2814="Click to modify the permissions of %%rank%%" +general.2815="Click to disable" +general.2816="Click to enable" +general.2817="Current Priority: %%priority%%" +general.2818="LEFT CLICK to increase priority" +general.2819="RIGHT CLICK to decrease priority" +general.2820="Change Priority" +general.2821="This rank is already the highest priority!" +general.2822="This rank is already the lowest priority!" +general.2823="To guild ranks" +general.2824="You have no default ranks!" +general.2825="Set an existing rank to default before you can delete this one!" +general.2826="Delete Rank" +general.2827="You cannot delete this rank as it's the default rank! Set another rank as the default to delete this rank." +general.2828="Delete this guild rank" +general.2829="The rank's tag must be less than 5 characters!" +general.2830="The rank's tag must only contain numbers, letters or spaces!" +general.2831="You've already got a rank with this tag!" +general.2832="You set the tag empty, so we've removed the tag from this Guild rank." +general.2833="ranks tag here!" +general.2834="Modify Tag" +general.2835="Modify this ranks tag. Currently: %%tag%%" +general.2836="Go back a page" +general.2837="Go forward a page" +general.2838="Is that all you got?!" +general.2839="Zombies Winner" +general.2840="Zombies Speed Runner" +general.2841="Master Seeker" +general.2842="Party Pooper" +general.2843="Attempting to send you the resource pack..." +general.2844="Resource Pack" +general.2845="This game uses a resource pack for cool textures and models, but it can take some time to load it." +general.2846="Click to load!" +general.2847="Load the resource pack" +general.2848="Need help? Click here!" +general.2849="Open the resource pack guide" +general.2850="Coins just earned DOUBLED as a Guild Level Reward!" +general.2851="Rank: %%rank%%" +general.2852="Daily Exp: %%exp%%" +general.2853="Click to configure!" +general.2854="Your guild has not unlocked this!" +general.2855="Guild Tag Color" +general.2856="Guild Permissions" +general.2857="Only the guild master can use this!" +general.2858="Click to edit!" +general.2859="Modify your guild's ranks & their permissions" +general.2860="Only the guild master may use this!" +general.2861="Whether or not players can find the guild in Guild Finder and request to join." +general.2862="Click to toggle!" +general.2863="Select Guild Games" +general.2864="Changes the Guild's description as shown in the Guild Finder." +general.2865="Click here to use /guild settings description to change the Description!" +general.2866="Personal Settings" +general.2867="Personal Guild Settings" +general.2868="Guild Online Only" +general.2869="Only show online members when using /guild list" +general.2870="Guild Notifications" +general.2871="Receive messages when your fellow guild members log in or out" +general.2872="enabled" +general.2873="disabled" +general.2874="No quest active" +general.2875="There currently isn't a Guild Quest active." +general.2876="Not in a guild" +general.2877="You're not in a guild so you can't participate in Guild Quests." +general.2878="To complete the quest, Guild Members need to complete Challenges in any game." +general.2879="Tier %%tier%%: " +general.2880="Reward: %%amount%% Guild Experience" +general.2881="Weekly Guild Quest" +general.2882="Guild Leveling Rewards" +general.2883="Tier %%tier%% Guild Cloak" +general.2884="Guild Members have the ability to use the Tier %%tier%% Guild Cloak in lobbies." +general.2885="Unlocks at Level %%level%%" +general.2886="%%chance%%% Double Coins" +general.2887="Whenever a Guild Member plays a game, they have a %%chance%%% chance of getting Double Coins every time they gain coins." +general.2888="%%chance%%% Double Exp" +general.2889="Whenever a Guild Member plays a game, they have a %%chance%%% chance of getting Double Exp for the entire game." +general.2890="Tier %%tier%% Forum Icon" +general.2891="All Guild Members receive the Tier %%tier%% Forum Icon on the Hypixel Forums." +general.2892="The Guild Tag's maximum length is increased to 7 characters." +general.2893="Guild Tag Length" +general.2894="Guild Members can have a %%color%% Guild Tag displayed next to their username in lobbies." +general.2895="Guilds that already had a Guild Tag set before the Guild Update unlock this automatically." +general.2896="%%color%% Guild Tag" +general.2897="%%a%% and %%b%% Particle Packs" +general.2898="Guild Members have the ability to use the %%a%% and %%b%% Particle Packs in lobbies." +general.2899="Crits" +general.2900="Flame" +general.2901="Cloud" +general.2902="Sphere" +general.2903="Ring" +general.2904="Guild Leveling" +general.2905="Guild Level: %%level%%" +general.2906="Exp until next level: %%exp%% (%%percent%%%%%gray%%)" +general.2907="Guild Achievements" +general.2908="Achievements completed: %%achieved%%/%%total%%" +general.2909="Error" +general.2910="Progress: %%progress%%/%%required%%" +general.2911="Reach Guild level %%var%%" +general.2912="Experience Kings" +general.2913="Get %%var%% Guild Exp in one day" +general.2914="Winners" +general.2915="Win %%var%% games as a Guild in a day" +general.2916="Click to join the Discord!" +general.2917="If your Guild has a Discord server, you can add link it here for members to be able to join it easily." +general.2918="Click to set!" +general.2919="Guild Discord" +general.2920="Your Guild Master didn't set a Discord server." +general.2921="Your Guild has a Discord server that Guild Members can join." +general.2922="Click to view Invite Link" +general.2923="Right-click to modify" +general.2924="Preview: %%preview%%" +general.2925="Click to pick this color!" +general.2926="Guild Achievements" +general.2927="Reversed" +general.2928="Normal" +general.2929="Click to toggle!" +general.2930="No data found." +general.2931="You are not in a guild." +general.2932="Guild does not exist anymore." +general.2933="Guild" +general.2934="Level" +general.2935="Experience" +general.2936="Top Hypixel Guilds" +general.2937="If your Guild has a Discord server, you can add its link it here for members to be able to join it easily." +general.2938="CLICK FOR STATS" +general.2939="Parkour challenge cancelled!" +general.2940="Parkour challenge started!\nUse /parkour checkpoint to teleport to the last checkpoint or /parkour cancel to cancel!" +general.2941="Deal 300k damage and heal 300k health in 1 game" +general.2942="Revive 6 players with a single undying army" +general.2943="Always open the book." +general.2944="Don't show again!" +general.2945="The resource pack will now download automatically." +general.2946="The resource pack will not be downloaded automatically." +general.2947="Click here" +general.2948="Open the resource pack book!" +general.2949="%%playerCount%% in Queue" +general.2950="Open this book before\nloading the resource pack" +general.2951="Load the resource pack\nwithout opening this book" +general.2952="Starting in %%time%% if" +general.2953="%%amount%% more players join" +general.2954="Starting in %%time%% to" +general.2955="allow time for" +general.2956="additional players" +general.2957="%%amount%% more players are required for the game to start." +general.2958="%%amount%% more player is required for the game to start." +general.2959="Click to Play" +general.2960="Random Map" +general.2961="Available Servers" +general.2962="Times Joined" +general.2963="Right click to toggle favorite!" +general.2964="30 points for kills/assists on the enemy flag carrier" +general.2965="15 points for kills/assists near allied flag carrier" +general.2966="100 points for capturing a flag" +general.2967="30 points for capturing a domination point" +general.2968="5 points for TDM kills/assists" +general.2969="Grandmaster" +general.2970="Resets in: %%time%%" +general.2971="The guild is earning exp at %%rate%%%%%gray%% rate!" +general.2972="Click to view leveling rewards!" +general.2973="%%days%% days" +general.2974="%%hours%% hours" +general.2975="%%minutes%% minutes" +general.2976="Today's exp < %%val%% → %%percent%%%" +general.2977="Today's exp >= %%val%% → %%percent%%%" +general.2978="Today's exp: %%exp%%" +general.2979="Rename Rank" +general.2980="Something might have gone wrong, please check!" +general.2981="Rename the %%rank%% rank." +general.2982="Click to modify the %%rank%% rank" +general.2983="Toggle Tag" +general.2984="Click to toggle the Guild Master tag off." +general.2985="Click to toggle the Guild Master tag on." +general.2986="Toggle Tag" +general.2987="Return to the Main Lobby." +general.2988="The rank's tag must be less than %%length%% characters!" +general.2989="Unlocked with 10,000 Achievement Points" +general.2990="Gold Achievement Menu" +general.2991="Disable Gold Achievement Menu" +general.2992="Enable Gold Achievement Menu" +general.2993="Changes achievement unlocks within the menu to gold." +general.2994="Gold Achievement Menu" +general.2995="Dragon" +general.2996="Tiki" +general.2997="Egyptian" +general.2998="Body A" +general.2999="Body B" +general.3000="Body C" +general.3001="Body D" +general.3002="Bridge" +general.3003="Bridge Doubles" +general.3004="Bridge Teams" +general.3005="Your skin has now been reset." +general.3006="You will now show up as an Alex." +general.3007="You will now show up as a Steve." +general.3008="You can't shout as a spectator." +general.3009="Click to view Store link!" +general.3010="There was an error while loading your latest tournament position" +general.3011="Unlocked in Tournament Hall!" +general.3012="Unlocked in Tournament Hall!" +general.3013="Bridge Duel" +general.3014="Bridge Duels" +general.3015="Play %%mode%%!" +general.3016="Click to play!" +general.3017="%%playing%% currently playing" +general.3018="You can only vote while in-game" +general.3019="Privacy Settings" +general.3020="Privacy Settings" +general.3021="Chat Settings" +general.3022="Chat Settings" +general.3023="Requires %%rank%%" +general.3024="%%time%% %%suffix%%" +general.3025="Ingame Store" +general.3026="Golden kit item names" +general.3027="Golden kit name" +general.3028="Random for %%time%%" +general.3029="%%name%%" +general.3030="Click to change the color to %%color%%" +general.3031="Selected: %%color%%" +general.3032="%%name%%" +general.3033="NEW DAILY MISSION: %%mission%%." +general.3034="MVP+ Rank Color" +general.3035="Toggle Prefix Color" +general.3036="Note: Statuses do not show when nicked!" +general.3037="%%season%% Battle Pass" +general.3038="Alternative Game Menu Layout" +general.3039="aqua" +general.3040="Aqua" +general.3041="Autotip" +general.3042="blue" +general.3043="dark green" +general.3044="dark purple" +general.3045="dark red" +general.3046="Donkey" +general.3047="Duel Invite Privacy" +general.3048="Earn over 100 rewards by completing missions and leveling up your Battle Pass." +general.3049="Every hit for 20 seconds after activation applies Wither III for 3 seconds." +general.3050="Gain Speed II for 15 seconds and 1.5❤!" +general.3051="gold" +general.3052="green" +general.3053="Guild Chat Visibility" +general.3054="Guild Message Sounds" +general.3055="Guild Profanity Level" +general.3056="Lobby Join Message (Self)" +general.3057="Party Message Sounds" +general.3058="Party Profanity Level" +general.3059="PM Profanity Level" +general.3060="Prestige Taunt" +general.3061="Private Message Sounds" +general.3062="Public Profanity Level" +general.3063="Rank Color" +general.3064="red" +general.3065="Requires %%rank%% to enable!" +general.3066="Set a status to be displayed above your head in lobbies." +general.3067="Show off your prestige status." +general.3068="Staff and friends can send you Duel requests." +general.3069="Status" +general.3070="Teleport to the nearest player and remove half their health." +general.3071="Toggle hearing a ding when you receive a new Guild Message." +general.3072="Toggle hearing a ding when you receive a new Party Message." +general.3073="Toggle hearing a ding when you receive a new Private Message." +general.3074="Toggle whether your join message is sent when you join a lobby." +general.3075="Toggles ability to see guild chat." +general.3076="Toggles whether or not you are informed about new updates." +general.3077="Toggles whether you automatically tip all active boosters." +general.3078="Toggles whether you would like to use the old Game Menu (compass) layout." +general.3079="Tron Blue Trail" +general.3080="Unlock unique Kill Counters to show off your progress." +general.3081="Update Notification" +general.3082="(Double Coins + EXP Weekend)" +general.3083="Dining Chair" +general.3084="High-Backed Dining Chair" +general.3085="Stool" +general.3086="Yellow Armchair" +general.3087="Green Armchair" +general.3088="White Armchair" +general.3089="White Office Chair" +general.3090="Black Office Chair" +general.3091="Red Sofa" +general.3092="Black Sofa" +general.3093="Pink Sofa" +general.3094="Dining Table" +general.3095="Coffee Table" +general.3096="Long Table" +general.3097="Desk with Computer" +general.3098="Fridge-Freezer" +general.3099="Cooker" +general.3100="Washing Machine" +general.3101="Locker" +general.3102="Fire Pit" +general.3103="Standing Lamp" +general.3104="Flatscreen TV" +general.3105="Basketball Hoop" +general.3106="Small Fish Tank" +general.3107="Toilet" +general.3108="Sink" +general.3109="Bath" +general.3110="Shower Cubicle" +general.3111="Whale Statue" +general.3112="Dog Statue" +general.3113="Knight Statue" +general.3114="All" +general.3115="Fire a huge Pumpkin Laser that destroys everything in it's path! Watch out for the recoil." +general.3116="Killing an enemy rips their soul of their body, leaving them lingering a few more seconds in the common world." +general.3117="Killing an enemy drops a hologram showing your total number of final kills." +general.3118="When you destroy a bed, display your selected Glyph above it." +general.3119="Moving you to %%session%%" +general.3120="Click to view the Hypixel website" +general.3121="The blood keeps pouring from arrows after hitting" +general.3122="Unlocked in the Halloween Bundle!" +general.3123="Hytale Trailer" +general.3124="Have %%var%% guild members online at the same time!" +general.3125="Family" +general.3126="Hit an enemy with Shadow Burst from over 35 blocks away" +general.3127="Staff, friends, and guild members can send you Duel requests." +general.3128="Anyone can send you a Duel request." +general.3129="All Games" +general.3130="Overall" +general.3131="Double Up!" +general.3132="Infection V2" +general.3133="Coming Soon" +general.3134="More rewards are coming soon!" +general.3135="More rewards are coming soon!" +general.3136="+%%amount%% Hypixel Experience" +general.3137="Hytale Trailer" +general.3138="Today's voting link is" +general.3139="CLICK TO CLAIM!" +general.3140="Click this link and then click YES when the prompt appears to visit our website!" +general.3141="Nicknames allow you to play with a different username to not get recognized." +general.3142="Click here to proceed" +general.3143="Check out the trailer for the new standalone game from Hypixel Studios!" +general.3144="1st Place - %%player%%" +general.3145="2nd Place - %%player%%" +general.3146="Party Games" +general.3147="Cost: %%cost%%" +general.3148="Click here to access the Hypixel Store: https://store.hypixel.net" +general.3149="Favor of the Angel" +general.3150="Icon" +general.3151="This command is currently disabled!" +general.3152="FIRST LOOK TRAILER" +general.3153="All rules still apply. You can still be reported and all name history is stored." +general.3154="➤ I understand, set up my nickname" +general.3155="Teleport to Last Checkpoint" +general.3156="Reset" +general.3157="You reached Checkpoint #%%checkpoint%% after %%current%%." +general.3158="Click this link and then click YES when the\nprompt appears to visit our website!" +general.3159="➤ Reuse '%%name%%'" +general.3160="Click here to reuse '%%name%%'" +general.3161="➤ Reuse %%skin%%" +general.3162="Click here to reuse your previous skin" +general.3163="%%gametype%% Network Boosters are not available." +general.3164="You don't have any %%gametype%% boosters!" +general.3165="You can buy Network Boosters at store.hypixel.net." +general.3166="Click for details!" +general.3167="Unused Booster" +general.3168="This booster has not yet been used." +general.3169="Click to activate!" +general.3170=" HYTALE TRAILER" +general.3171="Hypixel has been working on its own Standalone game for the past few years." +general.3172="Watch the trailer on the Hytale website!" +general.3173="Click to visit the website!\n(brace yourself)" +general.3174=" WATCH TRAILER" +general.3175="This is a special lobby open for limited times during tournament events." +general.3176="Stay alert for tournament announcements! Everyone can participate, earn tributes and unlock some of the most prestigious rewards on Hypixel." +general.3177="Upcoming: %%mode%%" +general.3178="Date: %%month%% %%day%%" +general.3179="Date: %%month%% %%start%%-%%end%%" +general.3180="LIVE! %%mode%%" +general.3181="Try it out!" +general.3182="Last tournament: %%mode%%" +general.3183="Happened in %%month%% %%year%%" +general.3184="Lobby open!" +general.3185="Lobby Closed" +general.3186="Tournament Hall" +general.3187="Special Events" +general.3188="Click to connect" +general.3189="WATCH TRAILER" +general.3190="NEW MODE" +general.3191="NEW UPDATE" +general.3192="Everything in this lobby is currently\n" +general.3193="in development, and may be removed\n" +general.3194="at any time." +general.3195="[WATCHDOG ANNOUNCEMENT]" +general.3196="Watchdog has banned %%ban_count%% players in the last 7 days." +general.3197="Staff have banned an additional %%staff_ban_count%% in the last 7 days." +general.3198="Blacklisted modifications are a bannable offense!" +general.3199="Collect fun cosmetic items!" +general.3200="The blood keeps pouring" +general.3201="from arrows after hitting" +general.3202="Unlocked in Halloween Bundle!" +general.3203="This kill message shouts your" +general.3204="number of final kills." +general.3205="Guild Description" +general.3206="There are no servers running that mode right now! Try again in a moment!" +general.3207="Snow Globe" +general.3208="Killing an enemy will spawn a musical snow globe that will play 1 of 6 Festive jingles." +general.3209="Turn all the lights off!" +general.3210="RIGHT-CLICK" +general.3211="3x COINS" +general.3212="Currently Enabled" +general.3213="Currently Disabled" +general.3214="Wear all 4 pieces of the Fusion Armor" +general.3215="Kit Selector (Right Click)" +general.3216="Parkour challenge started!" +general.3217="Player Tracker (Right Click)" +general.3218="An error occurred, please report this to a staff member (%%server%%)" +general.3219="Channel: %%channel%%" +general.3220="Click to change this channel!" +general.3221="This housing channel is still loading!" +general.3222="Couldn't scroll the menu, refreshed it instead!" +general.3223="Page (%%current%%/%%total%%)" +general.3224="Click to scroll!" +general.3225="Scroll right" +general.3226="Scroll left" +general.3227="Most guests" +general.3228="Social" +general.3229="Weekly cookies" +general.3230="Recommended" +general.3231="Revisit" +general.3232="New houses" +general.3233="Staff+YT" +general.3234="Roleplay (RP)" +general.3235="Building" +general.3236="Chatting" +general.3237="Game" +general.3238="Competition" +general.3239="Event" +general.3240="Own language" +general.3241=""%%tag%%" Tag" +general.3242="View houses tagged with "%%tag%%" by their owner." +general.3243="View houses sorted by how many online guests they have" +general.3244="View houses of your party members, friends and guildmates" +general.3245="View houses of your friends" +general.3246="View houses of members of your guild" +general.3247="View houses which earned the most cookies the past week" +general.3248="View houses similar to those you recently visited" +general.3249="View houses you recently visited" +general.3250="View new houses of players who recently joined Player Housing" +general.3251="View houses owned by staff members and youtubers" +general.3252="View houses owned by MVP++ players\n\nPurchase MVP++ on store.hypixel.net!" +general.3253="View a completely random selection of houses" +general.3254="View houses owned by players sharing your language.\n\nPick your language in "My Profile" in any lobby." +general.3255="View houses owned by players speaking %%lang%%" +general.3256="There was an error while talking to the housing backend!" +general.3257="Language: %%lang%%" +general.3258="No houses!" +general.3259="Couldn't find any house for this channel :(" +general.3260="Every Hypixel player owns a house which they can build up to match their dreams." +general.3261="Reset ALL channels" +general.3262="This will reset all of your selected housing channels to their default value!" +general.3263="Click to reset!" +general.3264="Channel selection" +general.3265="More language channels..." +general.3266="There are channels for each language on Hypixel." +general.3267="Click to view them!" +general.3268="Click to use this channel!" +general.3269="Specific Language Channels" +general.3270="Language: %%lang%%" +general.3271="Reset housing channels selection!" +general.3272="This is a default channel!" +general.3273="Keep up with Hypixel news + get free %%reward%% by following us!" +general.3274="Click to follow:" +general.3275="You can claim these rewards at any time in the Delivery Man" +general.3276="You've already claimed this reward!" +general.3277="Click to claim reward!" +general.3278="Pit" +general.3279="Team Pride" +general.3280="Flower" +general.3281="Bloody" +general.3282="Poop" +general.3283="Disc Jockey" +general.3284="Fiery Wind" +general.3285="Crayon" +general.3286="You haven't unlocked this Achievement yet!" +general.3287="Daredevil" +general.3288="Show the world who the boss is by riding this blazing boneless stallion." +general.3289="Selecting this option sets your %%category%% to default." +general.3290="Cage" +general.3291="Temple" +general.3292="Witch Hut" +general.3293="Sailboat" +general.3294="Mushroom" +general.3295="UFO" +general.3296="Cheeseburger" +general.3297="Cages" +general.3298="Beach Ball" +general.3299="Bee" +general.3300="The Bridger" +general.3301="Diamond Steve" +general.3302="Celebration Popper" +general.3303="Endermite" +general.3304="Confetti" +general.3305="Silverfish" +general.3306="Requires: %%rank%%" +general.3307="Map Feedback Survey" +general.3308="Click here to answer "" +general.3309=""." +general.3310="You can only do that in lobbies!" +general.3311="The offer to provide feedback for that map has expired." +general.3312="Error: Unknown GameType %%gameType%%!" +general.3313="You recently played the map %%mapname%% and we would like to hear what you thought of it." +general.3314="[Give Feedback]" +general.3315="Thank you for your feedback!" +general.3316="Were you able to find your way around the map?" +general.3317="What do you think about the map's size?" +general.3318="How would you rate the speed of this map's gameplay?" +general.3319="How would you rate of the look of the map?" +general.3320="How would you rate this map overall?" +general.3321="How would you rate the balance of your spawn?" +general.3322="Were the emerald spawns easy to find?" +general.3323="Were the emerald spawns easy to reach?" +general.3324="Do you think the diamond islands were located fairly?" +general.3325="How would you rate the balance of this map overall?" +general.3326="How far was the middle island from your spawn island?" +general.3327="Was your spawn island easy to navigate?" +general.3328="Was the middle island easy to navigate?" +general.3329="Were the unique elements on this map fun?" +general.3330="Was there enough hiding spots on this map?" +general.3331="Were you happy with the amount of gold you found on this map?" +general.3332="Very Big" +general.3333="Slightly Big" +general.3334="Just Right" +general.3335="Slightly Small" +general.3336="Very Small" +general.3337="Very Fast" +general.3338="Slightly Fast" +general.3339="Slightly Slow" +general.3340="Very Slow" +general.3341="Excellent" +general.3342="Good" +general.3343="Bad" +general.3344="Very Bad" +general.3345="Attack Biased" +general.3346="Balanced" +general.3347="Defence Biased" +general.3348="Too Simple" +general.3349="Too Messy" +general.3350="Unbalanced" +general.3351="Very Unbalanced" +general.3352="Too Far" +general.3353="Too Close" +general.3354="Very Fun" +general.3355="Fun" +general.3356="Average" +general.3357="Not That Fun" +general.3358="Not Fun At All" +general.3359="Too Many" +general.3360="Not Enough" +general.3361="Too Much" +general.3362="EASTER SPECIAL!" +general.3363="You already answered that question." +general.3364="Unlocked in Battle Pass: %%season%%!" +general.3365="Filtered Cosmetics" +general.3366="Other cosmetics" +general.3367="(%%number%%)" +general.3368="Other Cosmetics" +general.3369="Items are for sale!" +general.3370="Event is LIVE!" +general.3371="Items not for sale" +general.3372="Items always for sale!" +general.3373="Some special items are only unlocked in very special ways. Find them here!" +general.3374="Click to view cosmetics!" +general.3375="Currently Selected: %%option%%" +general.3376="Click to enable!" +general.3377="Click to disable!" +general.3378="Private Game Settings" +general.3379="You must wait 5s between uses!" +general.3380="You enabled your glowing effect! (Visible to players with Minecraft 1.9 or later)" +general.3381="You disabled your glowing effect!" +general.3382="Gives your in-game character an outline in the color of your rank." +general.3383="Note: The glowing effect will only be visible to players using Minecraft 1.9 or later!" +general.3384="Click to disable!" +general.3385="Click to enable!" +general.3386="Unlocked in Any Season Battle Pass!" +general.3387="Glow" +general.3388="You must unlock %%achievement%% to use this cosmetic!" +general.3389="Effect List" +general.3390="This mission is unlocked when purchasing the Battle Pass!" +general.3391="You have already found this Dragon Egg!" +general.3392="You have found a secret Dragon Egg!" +general.3393="Right Click to jump to the start." +general.3394="Complete Missions to earn experience towards your Battle Pass!" +general.3395="Missions are currently disabled!" +general.3396="Level up your Battle Pass by playing games and completing missions." +general.3397="Earn over 100 rewards by playing and completing missions." +general.3398="You can purchase the Battle Pass anytime during the season!" +general.3399="What is the Battle Pass?" +general.3400="Missions" +general.3401="Right Click to jump to the end." +general.3402="Starts %%time%%!" +general.3403="Week %%week%% Missions" +general.3404="Unlocks %%time%%!" +general.3405="Completed:" +general.3406="Free Weekly Mission" +general.3407="Free Daily Mission" +general.3408="Free Mission" +general.3409="Weekly Mission" +general.3410="Daily Mission" +general.3411="Mission" +general.3412="Completed" +general.3413="Completed Daily Missions are auto-removed on the next day." +general.3414="Unlocked by purchasing the Battle Pass!" +general.3415="+%%amount%% Battle Pass EXP" +general.3416="Click to Replace!" +general.3417="You have already replaced a Daily mission today!" +general.3418="Season 1" +general.3419="Season 2" +general.3420="Season 3" +general.3421="Season 4" +general.3422="Tier" +general.3423="Battle Pass Inventory" +general.3424="Some rewards earned will be placed into the Battle Pass Inventory." +general.3425="These rewards can then be claimed at anytime." +general.3426="Click to view missions!" +general.3427="Daily Missions" +general.3428="Inventory" +general.3429="EARNED!" +general.3430="Free Battle Pass" +general.3431="Paid Battle Pass" +general.3432="Tier: %%tier%%" +general.3433="Max Tier Reached!" +general.3434="EXP: %%exp%%/%%max%%" +general.3435="%%boost%%% Personal EXP Boost" +general.3436="%%boost%%% Party EXP Boost" +general.3437="Ends %%time%%!" +general.3438="Battle Pass Tier %%start%% - %%end%%" +general.3439="Promised Fulfilled" +general.3440="[Coop or you] Unlock the final Talisman Bag upgrade" +general.3441="Toggles the quality of particles." +general.3442="Auto-Tip" +general.3443="Offer Map Feedback" +general.3444="Toggle whether you will be offered map feedback surveys" +general.3445="Unlocked by %%percent%% of %%game%% players!" +general.3446="These rewards can then be claimed at anytime during the season." +general.3447="UNCLAIMED REWARDS!" +general.3448="Purchased Battle Pass" +general.3449="Requires Purchased Battle Pass!" +general.3450="You were kicked from your guild with reason '%%reason%%'" +general.3451="You were kicked from the guild by %%player%% for reason '%%reason%%'." +general.3452="Looking to 1v1" +general.3453="Looking to Team Up" +general.3454="Looking to Chat" +general.3455="Just Chillin'" +general.3456="Looking for a Guild" +general.3457="Do Not Disturb" +general.3458="AFK" +general.3459="Grinding Wins" +general.3460="Grinding Kills" +general.3461="Completed Quests" +general.3462="First Joined" +general.3463="Season 1 Tier" +general.3464="Bed Wars Level" +general.3465="Bed Wars Final Kills" +general.3466="Bed Wars Void Kills" +general.3467="Bed Wars Beds Broken" +general.3468="Bed Wars Winstreak" +general.3469="Bed Wars Kills" +general.3470="Bed Wars Wins" +general.3471="Bed Wars Coins" +general.3472="SkyWars Level" +general.3473="SkyWars Blocks Placed" +general.3474="SkyWars Blocks Broken" +general.3475="SkyWars Arrows Hit" +general.3476="SkyWars Arrows Shot" +general.3477="SkyWars Melee Kills" +general.3478="SkyWars Eggs Thrown" +general.3479="SkyWars Pearls Thrown" +general.3480="SkyWars Mob Kills" +general.3481="SkyWars Tokens" +general.3482="SkyWars Kills" +general.3483="SkyWars Wins" +general.3484="SkyWars Coins" +general.3485="Blitz Kills" +general.3486="Blitz Wins" +general.3487="Blitz Coins" +general.3488="Duels Best Winstreak" +general.3489="Duels Bow Hits" +general.3490="Duels Bow Shots" +general.3491="Duels Melee Hits" +general.3492="Duels Melee Swings" +general.3493="Duels Wins" +general.3494="Duels Kills" +general.3495="Duels Coins" +general.3496="Build Battle Score" +general.3497="Build Battle Wins" +general.3498="Build Battle Coins" +general.3499="Murder Mystery Gold Picked Up" +general.3500="Murder Mystery Knife Kills" +general.3501="Murder Mystery Kills" +general.3502="Murder Mystery Wins" +general.3503="Murder Mystery Coins" +general.3504="UHC Heads Eaten" +general.3505="UHC Score" +general.3506="UHC Kills" +general.3507="UHC Wins" +general.3508="UHC Coins" +general.3509="Smash Heroes Level" +general.3510="Smash Heroes Kills" +general.3511="Smash Heroes Wins" +general.3512="Smash Heroes Coins" +general.3513="Football Wins" +general.3514="Hole in the Wall Wins" +general.3515="Bounty Hunters Wins" +general.3516="Pixel Painters Wins" +general.3517="Dragon Wars Wins" +general.3518="Ender Spleef Wins" +general.3519="Galaxy Wars Wins" +general.3520="Throw Out Wins" +general.3521="Farm Hunt Wins" +general.3522="Party Games Wins" +general.3523="Hide and Seek Wins" +general.3524="Hypixel Says Wins" +general.3525="Mini Walls Wins" +general.3526="Blocking Dead Wins" +general.3527="Zombies Kills" +general.3528="TNT Games Wins" +general.3529="TNT Games Coins" +general.3530="Wizards Wins" +general.3531="Speed UHC Wins" +general.3532="Speed UHC Kills" +general.3533="Speed UHC Coins" +general.3534="Mega Walls Wins" +general.3535="Mega Walls Kills" +general.3536="Mega Walls Final Kills" +general.3537="Mega Walls Coins" +general.3538="Cops and Crims Bombs Planted" +general.3539="Cops and Crims Bombs Defused" +general.3540="Cops and Crims Shots Fired" +general.3541="Cops and Crims Headshot Kills" +general.3542="Cops and Crims Wins" +general.3543="Cops and Crims Kills" +general.3544="Cops and Crims Coins" +general.3545="Warlords Wins" +general.3546="Warlords Kills" +general.3547="Warlords Coins" +general.3548="Quakecraft Shots Fired" +general.3549="Quakecraft Wins" +general.3550="Quakecraft Kills" +general.3551="Quakecraft Coins" +general.3552="The Walls Wins" +general.3553="The Walls Kills" +general.3554="The Walls Coins" +general.3555="Paintball Shots Fired" +general.3556="Paintball Wins" +general.3557="Paintball Kills" +general.3558="Paintball Coins" +general.3559="VampireZ Wins" +general.3560="VampireZ Human Kills" +general.3561="VampireZ Vampire Kills" +general.3562="VampireZ Coins" +general.3563="Arena Brawl Wins" +general.3564="Arena Brawl Kills" +general.3565="Arena Brawl Coins" +general.3566="Turbo Kart Racers Wins" +general.3567="Turbo Kart Racers Coins" +general.3568="Reset Status" +general.3569="Your Status has been reset." +general.3570="Toggle Self Display" +general.3571="When displayed on yourself a status may be slightly delayed due to latency. This is not the case when you are seen by other players." +general.3572="This feature is currently disabled!" +general.3573="%%game%% Statuses" +general.3574="General Statuses" +general.3575="General Stat Statuses" +general.3576="Preview:" +general.3577="Selected!" +general.3578="Set your status to %%status%%" +general.3579="Unlocked in the %%season%% Battle Pass" +general.3580="You don't have any Network Boosters available! You can purchase them at http://store.hypixel.net/" +general.3581="\n%%purchaser%% activated +%%multiplier%%X coins for this game! Gain XP and coins by " +general.3582="\n%%purchaser%% and 1 other player activated +%%multiplier%%X coins for this game! Gain XP and coins by " +general.3583="\n%%purchaser%% and %%count%% others activated +%%multiplier%%X coins for this game! Gain XP and coins by " +general.3584="CLICK" +general.3585="%%prefix%%A player has been removed from your game for hacking or abuse. Thanks for reporting it!" +general.3586="Halloween Guide" +general.3587="Halloween" +general.3588="Christmas" +general.3589="Easter" +general.3590="Click here to join a %%game%% game!" +general.3591="CLICK HERE" +general.3592="Hype up yourself and those around you! It's so close! (or so far?)" +general.3593="Until %%year%%" +general.3594="%%magic%%; %%minutes%% minutes %%magic%%;" +general.3595="%%magic%%; %%hours%% hours %%magic%%;" +general.3596="%%magic%%; %%days%% days %%magic%%;" +general.3597="Advent Reward" +general.3598="First day claimable any day!" +general.3599="Reward claimed!" +general.3600="Oops! Reward missed!" +general.3601="Reward still a mystery!" +general.3602="You claimed the Advent Calendar reward for December %%day_ordinal%%!" +general.3603="Happy Holidays!" +general.3604="You can only claim today's reward!" +general.3605="Merry" +general.3606="Wingman" +general.3607="Snowball Rain" +general.3608="Twisted" +general.3609="Tombstone" +general.3610="Bubbling Cauldron" +general.3611="Potion Bottle" +general.3612="Surprise Snowball" +general.3613="Sleep Well" +general.3614="Snowball Spammer" +general.3615="Snowman Rampage" +general.3616="Abominable Snowman" +general.3617="It's spooky-time! This Victory Dance releases the souls of a bunch of poor players you killed in past games to celebrate your victory." +general.3618="Gift Explosion" +general.3619="Make your enemies burst into holiday gift!" +general.3620="Holiday Tree" +general.3621="Killing an enemy will place down a holiday tree." +general.3622="Campfire" +general.3623="Ghost" +general.3624="Gingerbread Man" +general.3625="Grinch" +general.3626="Clown" +general.3627="Sleigh" +general.3628="Skeleton Thumbs Up" +general.3629="Robin" +general.3630="Penguin" +general.3631="Gravestone" +general.3632="Candy Corn" +general.3633="Candy Basket" +general.3634="Bell" +general.3635="Stocking" +general.3636="Reindeer" +general.3637="Mr. Giftman" +general.3638="Healthy Treat" +general.3639="Cut down on those sweets with this red, sparkly, healthy treat!" +general.3640="Rudolph's Nose" +general.3641="How'd you even get this?" +general.3642="Exclusive Rudolph's Nose Knife Skin" +general.3643="SPECIAL HOLIDAY QUESTS" +general.3644="SPECIAL HOLIDAY QUESTS" +general.3645="SPECIAL HOLIDAY QUESTS" +general.3646="FREE REWARDS!!" +general.3647="FREE REWARDS!!" +general.3648="FREE REWARDS!!" +general.3649="Exclusive Candy Cane Hat" +general.3650="Exclusive Santa Suit" +general.3651="Advent Calendar Reward" +general.3652="Give in %s presents in BedWars" +general.3653="0.7.5 UPDATE!" +general.3654="Present" +general.3655="Unlocked in a Holiday Bundle!" +general.3656="Lunar New Year" +general.3657="Scurry" +general.3658="Dragon Roar" +general.3659="Sparkle" +general.3660="Mouse" +general.3661="Moon" +general.3662="Cluck Stack" +general.3663="Stellar" +general.3664="Cheesy" +general.3665="Lantern" +general.3666="Rat Costume" +general.3667="Rats 2020" +general.3668="Open Shop Menu" +general.3669="Click here to open the SkyWars shop" +general.3670="◼ Special Quest" +general.3671="◼ Themed Maps" +general.3672="Check it out? " +general.3673="[YES]" +general.3674="Raining Pigs" +general.3675="The sky will rain with pigs." +general.3676="Puppy Party" +general.3677="Spawn a hoard of wolves." +general.3678="Floating Lanterns" +general.3679="Spawn floating lanterns to brighten up the night." +general.3680="Chinese Dragon" +general.3681="Spawn a chinese dragon." +general.3682="Twin Dragon" +general.3683="Cheese" +general.3684="Rat" +general.3685="Luna" +general.3686="Howl" +general.3687="Spirit" +general.3688="Killing an enemy will spawn the Spirit kill effect." +general.3689="Fire Breath" +general.3690="Killing an enemy will spawn a fire breath effect." +general.3691="Honourable" +general.3692="Pig Peace" +general.3693="Sweet Dreams" +general.3694="Smug Pig" +general.3695="Year of the Pig" +general.3696="Earth Pig" +general.3697="Dogs of Wisdom" +general.3698="Year of the Dog" +general.3699="Peaceful" +general.3700="%%prefix%% Requires completing a %%event%% Quest!" +general.3701="You have already completed this quest this season!" +general.3702="You have claimed this reward, but you have %%amount%% token!\n\nYou can use tokens to draw now, or come back in %%time%%!" +general.3703="You have claimed this reward, but you have %%amount%% tokens!\n\nYou can use tokens to draw now, or come back in %%time%%!" +general.3704="Swarm" +general.3705="Raining Eggs" +general.3706="Hatching Eggs" +general.3707="Bunny GG" +general.3708="Easter Basket" +general.3709="Egg Hunt" +general.3710="Egg Surprise" +general.3711="Golden Egg" +general.3712="Rabbit Costume" +general.3713="The Wrong Eggs" +general.3714="Squeal" +general.3715="Bunny Costume" +general.3716="Rabbit in a Suit" +general.3717="Eggy" +general.3718="Buzz" +general.3719="Bunny Guy" +general.3720="Big Smile" +general.3721="Chick" +general.3722="Party" +general.3723="This is Fine" +general.3724="Eggsplosion" +general.3725="Lady Bug" +general.3726="Prickly" +general.3727="Painted Egg" +general.3728="Creeper Egg" +general.3729="Easter Simulator" +general.3730="∙ Easter Simulator" +general.3731="HINT" +general.3732="You have already unlocked everything!" +general.3733="We are currently showing you a limited set of games that we think are great for beginners! This will unlock all of our games and features, and there's a lot! This will be done automatically soon when we think you're ready, or you can do it now." +general.3734="Unlock Everything" +general.3735="Successfully unlocked all games!" +general.3736="Lobby Settings" +general.3737="Lobby Settings" +general.3738="Staff/YT Settings" +general.3739="Staff/YT Settings" +general.3740="Current: %%option%%" +general.3741="This will generate a random name for you." +general.3742="This will let you input a custom name." +general.3743="Previous Name: %%name%%" +general.3744="Change the name of your nick." +general.3745="Click to cycle!" +general.3746="Nick Name" +general.3747="Change the rank that will be shown with your nick." +general.3748="Nick Rank" +general.3749="This will use your normal skin." +general.3750="This will use the Steve or Alex skin." +general.3751="This will pick a random skin for you." +general.3752="This will reuse your last nick's skin." +general.3753="Change your skin that will be shown with your nick." +general.3754="Nick Skin" +general.3755="LEAD" +general.3756="INFO" +general.3757="View the Hypixel Store from right here in-game!" +general.3758="Your Hypixel Gold: %%amount%%" +general.3759="Buy %s amount of Items in Bed Wars" +general.3760="%%player%% remotely punched %%staff%% into the sky!" +general.3761="Toggles the ping sound and text highlight when you're mentioned in chat." +general.3762="NICKED (in games only)" +general.3763="Private Game Settings (Right Click)" +general.3764="Game Specific" +general.3765="All the Cows" +general.3766="Gotta love some cows." +general.3767="Health Buff" +general.3768="Buff All Players Health" +general.3769="Normal Health" +general.3770="Double Health" +general.3771="Triple Health" +general.3772="Low Gravity" +general.3773="Experience low gravity... also known as jump boost." +general.3774="One Hit, One Kill" +general.3775="Select which items should instantly kill enemies." +general.3776="No Speed" +general.3777="Speed I" +general.3778="Speed II" +general.3779="Speed III" +general.3780="CLASS" +general.3781="NOTE: For the best experience using this language, we recommend going into your Minecraft language settings and turning Force Unicode Font on." +general.3782="Lunar Dust" +general.3783="Haunted" +general.3784="Veggy SpringLazor™" +general.3785="Strike terror into the hearts of your enemies as the Abominable Snowman joins your side!" +general.3786="Raining Easter Eggs" +general.3787="It's raining Easter Eggs!" +general.3788="Hatching eggs are falling from the sky!" +general.3789="Fake Vampire" +general.3790="GG WPumpkin" +general.3791="Perfect Sword Throw" +general.3792="Scared" +general.3793="Skeleton Says Hi" +general.3794="Candles" +general.3795="Dragon Head" +general.3796="Rabbit Ears" +general.3797="Tulips" +general.3798="Wither" +general.3799="Chinese Firecracker" +general.3800="Earth" +general.3801="Click to Open!" +general.3802="Chicken Apocalypse" +general.3803="Tons of chickens, lots of eggs, its the end of the world unless you like chicken." +general.3804="Blizzard" +general.3805="You can't do that while already in a menu!" +general.3806="Snow Storm" +general.3807="Currently unacquirable!" +general.3808="Christmas Tree" +general.3809="Careful Santa" +general.3810="Snowball Fight" +general.3811="Candy King" +general.3812="Mob Party" +general.3813="%%count%% Total Players" +general.3814="➤ A %%name%% game is starting in 15 seconds! %%click%% to join!" +general.3815="Unlocked at Level %%level%%" +general.3816="Fish" +general.3817="Treasure" +general.3818="Junk" +general.3819="Your recent report has been reviewed and handled. Thank you! :)" +general.3820="Thanks for reporting, this helps to improve our system and the community! :)" +general.3821="Thanks for reporting, this helps to improve our system and the community!" +general.3822="Pumpkin Popper" +general.3823="Shattered" +general.3824="FaBOOlous" +general.3825="Found U" +general.3826="Garlic" +general.3827="Watcher" +general.3828="Witch Please" +general.3829="Jack o' Lantern" +general.3830="Candy" +general.3831="%%player%% has already been invited to Duel! Wait for them to accept!" +general.3832="Click to invite %%player%% to %%name%%!" +general.3833="Frankenstein" +general.3834="Enemy" +general.3835="Balancing" +general.3836="Axe" +general.3837="Smite" +general.3838="Pickaxe" +general.3839="Guns" +general.3840="Square" +general.3841="Circle" +general.3842="Visit our website to choose 1 of 3 random Reward Cards including coins, dust, experience, cosmetics + more!" +general.3843="\nYour game was boosted by %%purchaser%%'s +%%amount%%X coins Network Booster! Gain XP and coins by" +general.3844="\nYour game was boosted by +%%amount%%X coins Network Booster by %%purchaser%% and 1 other player! Gain XP and coins by" +general.3845="\nYour game was boosted by +%%amount%%X coins Network Booster by %%purchaser%% and %%count%% others! Gain XP and coins by" +general.3846="Rarity" +general.3847="Next Sort: %%next%%" +general.3848="Left click to cycle!" +general.3849="Order Sort: %%option%%" +general.3850="Sorted By: %%method%%" +general.3851="Find Hats in Collectibles on your hotbar." +general.3852="Find Gadgets in Collectibles on your hotbar." +general.3853="Total" +general.3854="gift" +general.3855="gifts" +general.3856="Snowflake" +general.3857="Fireplace" +general.3858="Angry Turkey" +general.3859="Puppy Surprise" +general.3860="Santa Slips" +general.3861="Sniper Snowball" +general.3862="Tinsel" +general.3863="Snowed In" +general.3864="Wrapped Up" +general.3865="Celebratory" +general.3866="Mistletoe" +general.3867="Snowglobe" +general.3868="Countries" +general.3869="Happy New Year!" +general.3870="Happy New Year!" +general.3871="Cities" +general.3872="2019 Advent Calendar" +general.3873="2020 Advent Calendar" +general.3874="%%year%% Advent Calendar: %%amount%%" +general.3875="%%year%% Advent Calendar: %%amount%%" +general.3876="Available to %%rank%%:" +general.3877="Available through Rank Gifting:" +general.3878="%%player%% sled into the lobby!" +general.3879="%%seconds%% seconds until it's %%year%% in" +general.3880="Unlock by claiming %%count%% Ranks Gifted Reward!" +general.3881="%%puncher%% punched %%punched%% into the sky!" +general.3882="%%puncher%% punched their friend %%punched%% into the sky!" +general.3883="This can be unlocked through Rank Gifting Rewards!" +general.3884="Punch Message" +general.3885="Select the %%name%% message for when you punch a staff or friend." +general.3886="Right-click to preview!" +general.3887="You do not have access to lobby punching!" +general.3888="Preview: " +general.3889="Click here to go back to the Punch Messages menu!" +general.3890="Set your Punch Message to %%message%%" +general.3891="Customize the message when you use your punch ability!" +general.3892="Punching in lobbies is only available to MVP+ players or those who own the Punching Friends item from the Tournament Hall." +general.3893="Punch Messages" +general.3894="Punch Messages" +general.3895="Currently Selected: %%message%%" +general.3896="NONE" +general.3897="Reset Punch Message" +general.3898="Your Punch Message has been reset." +general.3899="Players may also unlock the ability to punch their friends in lobbies as a reward in the Tournament Hall during active tournaments." +general.3900="Punching Players" +general.3901="This setting is locked for your rank!" +general.3902="This setting is locked!" +general.3903="Requires %%count%% Ranks Gifted Reward!" +general.3904="Customize Appearances" +general.3905="Customize Appearances" +general.3906="%%puncher%% lovingly punched %%punched%% into the sky!" +general.3907="%%puncher%% lovingly punched their friend %%punched%% into the sky!" +general.3908="Requires MVP+ or Punch Friends from the Tournament Hall. Find Punch Messages in your Profile." +general.3909="Unlocked in the %%year%% Advent Calendar" +general.3910="%%prefix%%%%color%%%%from%%%%color%% gifted %%days%% Days %%color%%of MVP++ %%color%%to %%target%%%%color%%!%%suffix%%" +general.3911="%%prefix%%%%color%%%%from%%%%color%% gifted the %%rank%%%%color%% rank to %%target%%%%color%%!%%suffix%%" +general.3912="%%color%%They have gifted %%gifted%%%%color%% ranks so far!" +general.3913="th" +general.3914="st" +general.3915="nd" +general.3916="rd" +general.3917="Second day claimable any day!" +general.3918="%%puncher%% booped %%punched%% into the sky!" +general.3919="%%puncher%% booped their friend %%punched%% into the sky!" +general.3920="%%puncher%% gloriously punched %%punched%% into the sky!" +general.3921="%%puncher%% gloriously punched their friend %%punched%% into the sky!" +general.3922="Loving Punch Message" +general.3923="Boop Punch Message" +general.3924="Snowball Punch Message" +general.3925="Glorious Punch Message" +general.3926="A kind stranger" +general.3927="Not today! ... also not tomorrow." +general.3928="Why hello there." +general.3929="Gotta catch 'em all!" +general.3930="%%puncher%% snowballed %%punched%% into the sky!" +general.3931="%%puncher%% snowballed their friend %%punched%% into the sky!" +general.3932="This game has been recorded. Click here to watch the Replay!" +general.3933="Click to watch or use /replay to show all your recent games." +general.3934="This game has been recorded. Buy %%rank%% to get access to the Replay System." +general.3935="Click to open the store under https://store.hypixel.net" +general.3936="\nInput password\nabove\n" +general.3937="You are AFK. Move around to return from AFK." +general.3938="Unlocked by %%percent%% of players!" +general.3939="Use random %%cosmetic%%!" +general.3940="Clone" +general.3941="Aqua Wool" +general.3942="You cannot punch players while they're doing parkour!" +general.3943="%%player%% joined the lobby!" +general.3944="Auto Deny Gifts" +general.3945="When enabled any gift requests will be auto denied." +general.3946="Lobby Dark Mode" +general.3947="Toggles whether lobbies will appear nighttime for you." +general.3948="Online Status" +general.3949="When disabled it blocks external tools using the PublicAPI from accessing your online status and what game you are playing." +general.recent_games="Recent Games" +general.3951="When disabled it blocks external tools using the PublicAPI from accessing your recently played games." +general.3952="API Settings" +general.3953="5 hours!" +general.3954="You have toggled the item off!" +general.3955="You have toggled the item on!" +general.3956="Daily" +general.3957="Jack O' Lantern" +general.3958="+%%amount%% Pit Gold" +general.3959="Kill 25 Players" +general.3960="Unleash the swarm!" +general.3961="Rainbow Present" +general.3962="Unlocked at level %%level%%" +general.3963="Unlocked in a Halloween Bundle!" +general.3964="Hunter" +general.3965="Apprentice" +general.3966="Kills" +general.3967="Murderer Kills" +general.3968="Murderer Wins" +general.3969="Capture the Wool Wins" +general.3970="Hide and Seek: Hider Wins" +general.3971="Hide and Seek: Seeker Wins" +general.3972="Zombies: Wins" +general.3973="Zombies: Best Round" +general.3974="Assists" +general.3975="Win Streak" +general.3976="Your recent report was reviewed and handled. Thank you! :)" +general.3977="%%player%% has chosen to accept your gift of %%item%%!" +general.3978="%%player%% has chosen to decline your gift. Sorry!" +general.3979="You have not been charged any gold." +general.3980="%%player%% took too long to accept your gift and it expired!" +general.3981="Boxing" +general.3982="Legacy Unlocked: %%count%%" +general.3983="Legacy Points: %%count%%" +general.3984="Legacy" +general.3985="Due to events and games that are no longer available, these achievements cannot be earned anymore." +general.3986="Points from these achievements still count towards achievement rewards, but do not count towards leaderboards." +general.3987="Points: %%count%%" +general.3988="Unlocked: %%count%%" +general.3989="Sort by the default layout." +general.3990="Killing a player will cause Pumpkins to explode from their body" +general.3991="Shatter your enemies to dust!" +general.3992="School's out! Grab a cup of hot chocolate! You're snowed in!" +general.3993="Available on the store:" +general.3994="Gold" +general.3995="Diamond" +general.3996="You haven't completed this Achievement yet!" +general.3997="You've already started the %%name%% quest!" +general.3998="The game is starting in %%time%% seconds!" +general.3999="Year Of The Rat" +general.4000="Map Selections" +general.4001="You don't have any Network Boosters available! You can purchase them at https://store.hypixel.net/" +general.4002="Iron" +general.4003="Master" +general.4004="Legend" +general.4005="Hole in the Wall" +general.4006="Browse your unlocked %%gamename%% cosmetics, or buy them directly with coins." +general.4007="Ride a ghast from hell the nether" +general.4008="Players: " +general.4009="Click for translation!" +general.4010="Daily rewards for visiting our website including: %%coins%%, %%exp%%, %%souls%%, Unique Cosmetics and more!" +general.4011="Toy Stick" +general.4012="Visit a Player's House" +general.4013="Unlocked as a Rank Gifting reward!" +general.4014="Rocket" +general.4015="Let There Be Leather" +general.4016="Ox Costume" +general.4017="Curled Ox" +general.4018="Angry Cow" +general.4019="Year of the Ox" +general.4020="Sad Moo" +general.4021="Doused Lantern" +general.4022="Cow Rocket" +general.4023="Beef Everywhere" +general.4024="To The Moon" +general.4025="Ox'd" +general.4026="Sacred Cattle" +general.4027="Ox" +general.4028="You have finished setting up your nickname!" +general.4029="When you go into a game, you will be nicked as %%nick%%. You will not be nicked in lobbies." +general.4030="GG" +general.4031="Carried" +general.4032="Leather Cap" +general.4033="Leather Tunic" +general.4034="Leather Pants" +general.4035="Splash Potion of Poison" +general.4036="Splash Potion of Swiftness" +general.4037="Splash Potion of Healing" +general.4038="Splash Potion of Swiftness II" +general.4039="Engineer" +general.4040="Farmer" +general.4041="Knight" +general.4042="Potion of Strength" +general.4043="Splash Potion of Harming" +general.4044="Splash Potion of Weakness" +general.4045="Aqua Affinity" +general.4046="Respiration" +general.4047="Splash Potion of Resistance" +general.4048="Chain Boots" +general.4049="Magnolia" +general.4050="They're only around for a short time but they're beautiful!" +general.4051="Rain on my Parade" +general.4052="Who doesn't love a good rain shower?" +general.4053="Whoa, that's a full rainbow all the way!" +general.4054="Rainy" +general.4055="Chicken Rider" +general.4056="Cute Bunny" +general.4057="Egg Gunner" +general.4058="Egg Hit" +general.4059="Egg Time" +general.4060="Rabbits in a Basket" +general.4061="Easter Bell" +general.4062="Hypixel Veteran Status" +general.4063="New Hypixel Player" +general.4064="%%color%%%%years%%-Year Hypixel Veteran" +general.4065="Unlocked from the Hypixel Anniversary Quest" +general.4066="A player has been removed from your game.\nUse /report to continue helping out the server!." +general.4067="A player has been removed from your lobby.\nUse /report to continue helping out the server!." +general.4068="%%color%%1-Year Hypixel Veteran" +general.4069="Deleted rank %%name%%!" +general.4070="There was a problem deleting the rank: %%message%%" +general.4071="The Guild backend is currently unavailable. Try again shortly." +general.4072="There was a problem creating the rank. Please try again later." +general.4073="There was a problem deleting the rank. Please try again later." +general.4074="There was a problem setting the default rank. Please try again later." +general.4075="There was a problem renaming the rank. Please try again later." +general.4076="There was a problem changing the rank permission. Please try again later." +general.4077="There was a problem changing the rank tag. Please try again later." +general.4078="There was a problem changing the rank's tag: %%message%%" +general.4079="Hold on, not that fast." +general.4080="Processing your request ..." +general.4081="%%name%% is now the default rank!" +general.4082="There was a problem setting the default rank: %%message%%" +general.4083="The rank %%oldRankName%% is now called %%newRankName%%!" +general.4084="There was a problem setting the rank's name: %%message%%" +general.4085="Gave the %%permission%% permission to the %%rankName%% rank!" +general.4086="Revoked the %%permission%% permission from the %%rankName%% rank!" +general.4087="There was a problem changing the rank's permission: %%message%%" +general.4088="Successfully removed the tag!" +general.4089="Successfully changed the tag to %%tag%%!" +general.4090="Killing an enemy will make them explode in blood." +general.4091="Killing an enemy will smash them out of the world." +general.4092="Killing an enemy will launch their head up in the skies." +general.4093="Killing an enemy will make them explode like a Piñata." +general.4094="Killing an enemy will make them disappear into TNT." +general.4095="Veterancy" +general.4096="How long they've been in the guild" +general.4097="Customize the following visual options for your player!" +general.4098="∙ MVP+ Rank Color" +general.4099="∙ Punch Messages" +general.4100="∙ Glow" +general.4101="∙ Status" +general.4102="No achievements to view!" +general.4103="There are no achievements to view with your current settings." +general.4104="%%gameType%% Seasonal Achievements" +general.4105="View challenge achievements for %%gameType%% that are exclusive to seasonal events." +general.4106="These achievements do not count towards total game completion." +general.4107="Seasonal Challenge Achievements" +general.4108="+%%amount%% %%multiplier%%x Personal Coin Booster (%%length%%)" +general.4109="Missing language! Valid languages: %%values%%" +general.4110="Invalid language '%%text%%'! Valid languages: %%values%%" +general.4111="Celebrate by gloating and showing off to other players whenever you win!" +general.4112="A selection of various effects to choose from that will trigger whenever you kill an enemy!" +general.4113="Click to craft for %%cost%% Mystery Dust!" +general.4114="Holiday Quest Exclusive" +general.4115="The nick you entered was flagged as inappropriate and blocked by our system! Please see https://hypixel.net/rules for more information." +general.4116="This nickname is inappropriate!" +general.4117="You do not have the required rank to use this!" +general.4118="UNLOCKED!" +general.4119="This cosmetic does not need selecting, it's already active!" +general.4120="ONLINE:" +general.4121="Couldn't find players, sorry!" +general.4122="Potion of Invisibility" +general.4123="Potion of Swiftness" +general.4124="This cosmetic doesn't need to be selected!" +general.4125="Pumpkin Rocket" +general.4126="Potion Rain" +general.4127="Trick or Treat" +general.4128="Infection" +general.4129="Pumpkin Patch" +general.4130="This item is not currently available!" +general.4131="%%puncher%% spooked %%punched%% into the sky!" +general.4132="%%puncher%% spooked their friend %%punched%% into the sky!" +general.4133="Unlocked in the Main Lobby Witch's Cauldron!" +general.4134="Unlocked in the Halloween Main Lobby Witch's Cauldron!" +general.4135="%%color%%Available to %%rank%% %%color%%during %%festival%%!" +general.4136="Boo!" +general.4137="Trick or Treat!" +general.4138="Legendary Fisher" +general.4139="Unlocked from Main Lobby Fishing Rewards" +general.4140="Main Lobby Special Fish Caught" +general.4141="Main Lobby Treasure Caught" +general.4142="Distinguished Ghost" +general.4143="Pumpkinz" +general.4144="Spooky Skelington" +general.4145="Sweets" +general.4146="Enabled Snow Particles! You can disable them at any time with /letitsnow!" +general.4147="Something went wrong giving vanity package, please report this at http://hypixel.net/bugs!" +general.4148="Disabled Snow Particles! You can re-enable them at any time with /letitsnow!" +general.4149="%%amount%%x %%item%% DUPLICATE" +general.4150="%%amount%%x %%item%%" +general.4151="%%player%% found an %%item%% in a %%name%%!" +general.4152="%%player%% found a %%item%% in a %%name%%!" +general.4153="YOU GOT LUCKY!\nYou will receive DOUBLE EXP this game!" +general.4154="This is a Guild Leveling reward. Your guild is level %%level%% which gives you a %%chance%%% chance of Double EXP." +general.4155="Snow Angel" +general.4156="Menorah" +general.4157="Snow Jerry" +general.4158="Candy Cane Sniper" +general.4159="To Build a Snowman" +general.4160="Festive Music" +general.4161="Festive" +general.4162="Dreidel" +general.4163="Holly" +general.4164="Wreath" +general.4165="Gold Present" +general.4166="Red and Green Present" +general.4167="Gold and White Present" +general.4168="Nutcracker" +general.4169="Hanukkah" +general.4170="Santa Hat" +general.4171="The Hypixel Store is not available here! Try in a lobby!" +general.4172="HAPPY HOLIDAYS FROM HYPIXEL" +general.4173="Spooky Punch Message" +general.4174="Fished Punch Message" +general.4175="%%puncher%% fished %%punched%% into the sky!" +general.4176="%%puncher%% fished their friend %%punched%% into the sky!" +general.4177="Unlocked through Seasonal Fishing Rewards!" +general.4178="Unlocked through Main Lobby Seasonal Fishing Rewards!" +general.4179="Staff and best friends can message you." +general.4180="Staff and best friends can send you party invites." +general.4181="Staff and best friends can send you guild invites." +general.4182="Staff and best friends can send you Duel requests." +general.4183="Options:" +general.4184="Settings & Visibility" +general.4185="Allows you to edit and control various personal settings." +general.4186="Social Settings" +general.4187="Game Settings" +general.4188="Tiger" +general.4189="Roar" +general.4190="Gold Tiger" +general.4191="Bright Tiger" +general.4192="Good Fortune" +general.4193="Lion Dancer" +general.4194="Sleeps and Treats" +general.4195="Year of the Tiger" +general.4196="Sniper" +general.4197="Do you want to play games?" +general.4198=" - Click the NPCs in front of the spawn area." +general.4199="Click this to teleport to the spawn area." +general.4200=" - Use your compass to open the games overview." +general.4201="Click this to open the games overview." +general.4202=" - Use commands like $ or $." +general.4203="Click this to go to the Bed Wars lobby." +general.4204="Click this to play SkyBlock." +general.4205="We autmatically changed your language to %%language%%." +general.4206="Click here to change it back to %%language%%." +general.4207="Click to change your language." +general.4208="Zero" +general.4209="One" +general.4210="Two" +general.4211="Three" +general.4212="Four" +general.4213="Five" +general.4214="Six" +general.4215="Seven" +general.4216="Eight" +general.4217="Nine" +general.4218="%%playing%% Playing" +general.4219="Code Breaker Punch Message" +general.4220="%%puncher%% %%magic%%H code broke %%magic%%H %%punched%% into the sky!" +general.4221="%%puncher%% %%magic%%H code broke %%magic%%H their friend %%punched%% into the sky!" +general.4222="Easter Achievement" +general.4223="Summer Achievement" +general.4224="Halloween Achievement" +general.4225="Holiday Achievement" +general.4226="Gift a Rank" +general.4227="Gift a rank to %%player%%." +general.4228="Click to gift!" +general.4229="You can't gift ranks to this player!" +general.4230="That player is not in your lobby!" +general.4231="Generating a unique random name. Please wait..." +general.4232="Processing request. Please wait..." +general.4233="Type /rankcolor to change the color and view all options." +general.4234="%%player%% spooked into the lobby!" +general.4235="To unlock unlimited map selection uses you can purchase MVP+ at https://store.hypixel.net" +general.4236="%s+%s%s Mystery Dust" +general.4237="To equip a banner, go to Collectibles > Banners" +general.4238="#%%number%%" +general.4239="+Ability to change the color of the '+' in %%rank%%" +general.4240="You do not have the rank required for this bonus! Purchase ranks at https://store.hypixel.net" +general.4241="Survey Available!" +general.4242="Click here or do /resource to open the resource pack book." +general.4243="This cannot be undone." +general.4244="You can purchase VIP on the store at https://store.hypixel.net" +general.4245="You can find the store at https://store.hypixel.net" +general.4246="%%player%% slid into the lobby!" +general.4247="Hot Potato Gadget" +general.4248="Anniversary Trampoline Gadget" +general.4249="Hypixel Click Effect" +general.4250="You can't send gifts to yourself!" +general.4251="ok" +general.4252="Hang on, it's the wrong time of year!" +general.4253="General Stats" +general.4254="Changed your prefix color to %%color%%!" +general.4255="Only available during Easter and special events" +general.4256="You are playing on MC.HYPIXEL.NET" +general.4257="Ranks, Boosters & MORE! STORE.HYPIXEL.NET" +general.4258="Extreme" +general.4259="Account Status" +general.4260="Check your punishment history and see where you stand." +general.4261="Account Status" +general.4262="A system to help the Hypixel Staff team catch cheaters with the use of the Replay System.\n\nReview cheaters reported by players to help determine if the report is legitimate!" +general.4263="Guild Rank" +general.4264="AP" +general.4265="Punching staff members ([GM] and [ADMIN]) is a feature available to all MVP%%color%%+ players." +general.4266="Play Another Random Game (Right Click)" +general.4267="Right-click to play another random game!" +general.4268="Right click NPCs" +general.4269="to join games and start playing." +general.4270="You can use /friend add" +general.4271="to add a player as a friend." +general.4272="Use /party invite" +general.4273="to play with other players!" +general.4274="Visit our website!" +general.4275="www.hypixel.net - news, discussion and more!" +general.4276="That's it!" +general.4277="Have fun on the server!" +general.4278="Achievement Guide" +general.4279="Online" +general.4280="Away" +general.4281="Busy" +general.4282="Appear Offline" +general.4283="Appearing Offline" +general.4284="Activate your personal and network boosters for extra coins." +general.4285="Gives a bonus coin multiplier in all games for a short amount of time." +general.4286="Gives EVERYONE a bonus coin multiplier in a specific game, or in all games!" +general.4287="Bunnies that run around and explode!" +general.4288="Celebrate with a splendid fireworks show!" +general.4289="Build snowmen around you that explode when spawned!" +general.4290="ACTIVATE BOOSTER" +general.4291="You can activate your %%game%% Network Booster in two ways:" +general.4292="QUEUE BOOSTER" +general.4293="Click to view information about queuing your booster." +general.4294="STACK BOOSTER" +general.4295="Click to view information about stacking your booster." +general.4296="Once your booster activates, you will be able to get coins and Hypixel Exp from tips from other players." +general.4297="Queuing your booster will give all players in %%game%% +2X coins." +general.4298="Estimated wait time: " +general.4299="Click to queue your booster." +general.4300="You can also " +general.4301="Stack Booster >" +general.4302="Stack your booster to activate it faster! Adds 0.1X to the current multiplier up to a max of +3X (10 stacked boosters)." +general.4303="Click to stack your booster." +general.4304="Queue Booster >" +general.4305="The rank's name can be at most 16 characters!" +general.4306="You already have that word/phrase on your filter list!" +general.4307="You can not filter a word/phrase longer than 32 characters!" +general.4308="You don't have that word/phrase on your filter list!" +general.4309="AWAY" +general.4310="BUSY" +general.4311="APPEARING OFFLINE" +general.4312="Duration: %%duration%%" +general.4313="Mode: %%value%%" +general.4314="Map: %%value%%" +general.4315="Server: %%value%%" +general.4316="Players: %%value%%" +general.4317="Started %%time%% ago" +general.4318="Game in progress" +general.4319="Click to view replay!" +general.4320="Replay expired!" +general.4321="Replay requires higher rank!" +general.4322="Attempting to load replay..." +general.4323="Unable to view this replay right now! Please try again in a moment!" +general.4324="Unable to do that right now! Try again in a moment." +general.4325="Sending you to %%house%%" +general.4326="House: %%house%%" +general.4327="Click to join!" +general.4328="MATCH DRAW!" +general.4329="MATCH WON!" +general.4330="MATCH LOST!" +general.4331="%%player1%% VS %%player2%%" +general.4332="VS" +general.4333="Nobody" +general.4334="(Unknown Game)" +general.4335="Daily %%mode%% Winstreak: " +general.4336="Overall Winstreak: " +general.4337="(Party Game)" +general.4338="(Duel Command)" +general.4339="(Private Game)" +general.4340="(Normal Game)" +general.4341="(Tournament)" +general.4342="(Ranked)" +general.4343="(Championship)" +general.4344="Hoops" +general.4345="Edit your inventory layout for %%key%%." +general.4346="Edit Layout - %%key%%" +general.4347="Hotbar" +general.4348="Save Layout" +general.4349="Save your inventory layout for %%key%%." +general.4350="Click to save!" +general.4351="You saved your %%key%% inventory layout!" +general.4352="Reset Layout" +general.4353="Reset your inventory layout for %%key%%." +general.4354="You reset your %%key%% inventory layout!" +general.4355="LEGENDARY" +general.4356="We have added a way for you to help us translate Hypixel into even more languages!" +general.4357="+%%amount%% Wool" +general.4358="+%%amount%% Wool Wars Experience" +general.4359="%%game%% Quests" +general.4360="Unlocked in the Event Shop!" +general.4361="You are now %%color%%Event Level %%accentColor%%%%level%%!" +general.4362="You earned %%silver%% Event Silver!" +general.4363="Shock Wave" +general.4364="Stormy" +general.4365="Heawave Creator" +general.4366="Rumoured to once have belonged to Helios this stick holds much mystical powers." +general.4367="Game Cosmetic" +general.4368="Wool Wars Cosmetic" +general.4369="Bed Wars Cosmetic" +general.4370="Murder Mystery Cosmetic" +general.4371="Duels Cosmetic" +general.4372="SkyWars Cosmetic" +general.4373="Lobby Punch Message" +general.4374="Lobby Status" +general.4375="Lobby Cosmetic" +general.4376="Added: %%color%%%%festival%% %%year%%" +general.4377="Cost: %%cost%% Event Silver" +general.4378="Purchased!" +general.4379="Not enough Silver!" +general.4380="Click to purchase!" +general.4381="Event Shop" +general.4382="You purchased the %%cosmetic%%!" +general.4383="You don't have enough Silver to purchase that!" +general.4384="Level up during events by playing games and completing quests." +general.4385="Summer View Barrier" +general.4386="Heat Wave Kill Messages" +general.4387="Burnt Up Bed Destroy" +general.4388="Parasol Island Topper" +general.4389="Surfboard Island Topper" +general.4390="Wave Island Topper" +general.4391="Ice Cream Cage" +general.4392="Sand Castle Cage" +general.4393="Frisbee Knife Skin" +general.4394="On Fire Aura" +general.4395="Relaxed Cosmetic Title" +general.4396="Summer Event Level Status" +general.4397="%%accentColor%%Event Level %%color%%%%level%% %%levelBar%% %%accentColor%%%%percent%%" +general.4398="MAX" +general.4399="Currently Active: %%festival%%" +general.4400="%%festival%% %%year%%" +general.4401="Event Silver: %%silver%%" +general.4402="Click to view shop!" +general.4403="Event Shop" +general.4404="No event active!" +general.4405="DEFAULT" +general.4406="Rank Bonuses from %%prefix%%" +general.4407="%%color%%%%multiplier%%x EXP Boost" +general.4408="%%silver%% Silver per Level" +general.4409="%%color%%Level Progress" +general.4410="Click to open the Hypixel Store!" +general.4411="Rank Benefit Information" +general.4412="%%color%%%%highlight%%%%multiplier%%%%highlight%%x EXP Boost" +general.4413="%%highlight%%%%silver%% %%highlight%%Silver per Level" +general.4414=" %%underline%%CLICK TO OPEN" +general.4415="HYPIXEL" +general.4416="STORE" +general.4417="You can buy Ranks at our store!" +general.4418="Supported Games:" +general.4419="Use this Punch Message with MVP+ or the Punch Friends perk to punch staff into the sky!" +general.4420="Brag about your Event Level to everyone in the lobby with this Status!" +general.4421="Show off whenever you a destroy an opponent's bed in Bed Wars with this Bed Destroy." +general.4422="Make your island look splendid with this Island Topper in Bed Wars!" +general.4423="Unique particles when you move around in Duels!" +general.4424="Show off your prestige with this title in Duels." +general.4425="Show off your style as Murderer with this frisbee that changes color each game!" +general.4426="Enter the game in style with this SkyWars Cage!" +general.4427="Check out this lobby cosmetic in your Collectibles menu!" +general.4428="Unlock this Barrier in Wool Wars and show it off before rounds start!" +general.4429="Unlock this set of Kill Messages in Wool Wars to use when you kill players!" +general.4430="%%puncher%% launched %%punched%% into the sun!" +general.4431="Solar Punch Message" +general.4432="Purchase this cosmetic in the Event Shop during active Events!" +general.4433="+%%amount%% Event Experience" +general.4434="Unlock this Kill Effect to use in multiple games!" +general.4435="Unlock this Projectile Trail to use in multiple games!" +general.4436="Unlock this Victory Dance to use in multiple games!" +general.4437="Unable to meet minimum player requirements. Please try to queue again later." +general.4438="You cannot view this player's stats." +general.4439="This command is not supported here." +general.4440="%%days%%d" +general.4441="%%hours%%h" +general.4442="%%minutes%%m" +general.4443="<10m" +general.4444="RECOMMENDED!" +general.4445="Click here to nick yourself with a random skin and hide your identity better." +general.4446="NOT RECOMMENDED!" +general.4447="Click here to nick yourself with your own skin. This allows other players to find out your real identity." +general.4448="Due to how skins work in Minecraft, using your real skin may allow players to find out your real identity. " +general.4449="We recommend choosing a random skin." +general.4450="You will now have your Minecraft character's skin even when nicked! Due to how skins work in Minecraft, using your real skin may allow players to find out your real identity." +general.4451=" %%underline%%➤ We recommend choosing a random skin." +general.4452="RECOMMENDED!\nClick here to nick yourself with a random skin and hide your identity better." +general.4453="Pixel Party: Highest Round" +general.4454="Pixel Party: Wins" +general.4455="Pixel Party Wins" +general.4456="Pixel Party Highest Round" +general.4457="Pixel Party Rounds Completed" +general.4458="Light Gray" +general.4459="There is a 1 second cooldown for reward claims!" +general.4460="%s+%s%s%s Hypixel Experience" +general.4461="Send a shock wave through your opponent's body." +general.4462="The player you were previously spectating is no longer alive." +general.4463="∙ Various Arcade Games" +general.4464="Required Rank: %%rank%%" +general.4465="You don't have the required rank!" +general.4466="SkyBlock Cosmetic" +general.4467="Purranormal Black Cat Skin" +general.4468="ZomBee Bee Skin" +general.4469="Hide and Squeak Rat Skin" +general.4470="Halloween Event Level Status" +general.4471="Demon Island Topper" +general.4472="Zombie Hand Island Topper" +general.4473="Chocolate Bar Island Topper" +general.4474="Jack O' Lantern Cage" +general.4475="Skull Cage" +general.4476="Candy Corn Suit" +general.4477="Clownfish Pet" +general.4478="Acid Rain Cloak" +general.4479="Bone Wings Cloak" +general.4480="Flammable Grappling Hook Gadget" +general.4481="Pumpkin Bomber Victory Dance" +general.4482="Pumpkin Volley Projectile Trail" +general.4483="Candy Basket Projectile Trail" +general.4484="Afterlife Kill Effect" +general.4485="Jack O' Twister Kill Effect" +general.4486="The Event Shop is currently disabled, check back later!" +general.4487="Ending soon!" +general.4488="Ends in %%days%% days!" +general.4489="Show your style with this fancy suit for Build Battle!" +general.4490="Collect your %%color%%%%item%% in your SkyBlock Jerry Deliveries!" +general.4491="COMMON" +general.4492="UNCOMMON" +general.4493="RARE" +general.4494="EPIC" +general.4495="LEGENDARY" +general.4496="MYTHIC" +general.4497="Give your SkyBlock Pet a new outfit with this event-themed Pet Skin!" +general.4498="You may need to change lobbies for Silver gains to be applied." +general.4499="Something isn't right, there's no event active!" +general.4500="Daily EXP: %%color%%%%daily%%/%%accentColor%%%%cap%%" +general.4501="Anyone can send you friend requests." +general.4502="Reset Custom Slots" +general.4503="Reset ALL custom slots." +general.4504="Your custom slots have been reset!" +general.4505="Custom Slot" +general.4506="This slot may be changed to a shortcut for your favorite game or mode!" +general.4507="You may change this slot at any time using Right Click." +general.4508="+Ability to change the color of the '+' in %%rank%%" +general.4509="Prototype Game" +general.4510="Survive increasingly difficult maps by landing in the water and be the first to finish!" +general.4511="ACHIEVED" +general.4512="Melee Hits" +general.4513="Melee Swings" +general.4514="Bow Hits" +general.4515="Bow Shots" +general.4516="Damage Dealt" +general.4517="Health Regenerated" +general.4518="Gun Game Wins" +general.4519="Gun Game Kills" +general.4520="Chaos Wins" +general.4521="Games Played" +general.4522="Deaths" +general.4523="Fire Spiral" +general.4524="Unlocked in a Summer Bundle!" +general.4525="%%game%% Icons" +general.4526="Stand on the correct color or fall to your death!" +general.4527="Pick which map you want to play from a list of available games." +general.4528="Earn Event Silver when you gain an Event Level. Silver can be used to purchase event-themed cosmetics!" +general.4529="This achievement is legacy and cannot be obtained anymore." +general.4530="Combat tracking disabled!" +general.4531="Combat tracking enabled!" +general.4532="Opening settings..." +general.4533="Currently processing, please try again shortly!" +general.4534="Busy busy busy busy busy ..." +general.4535="Hold on, I can't do everything at once!" +general.4536="I am worried with you doing this ..." +general.4537="Try harder." +general.4538="Progress: %%random%%" +general.4539="Try doing this %%random%% more times, it might work!" +general.4540="Hello World!" +general.4541="Is there anybody out there?" +general.4542="You have successfully hacked the mainframe using algorithms!" +general.4543="%%game%% does not support this feature yet!" +general.4544="This game has already started!" +general.4545="Make every player a one-hit-kill!" +general.4546="Gotta go fast!" +general.4547="Buff every player's health!" +general.4548="This language is currently being worked on!" +general.4549="View your recently played games." +general.4550="The Hypixel Replay System allows players to watch back their recently played games." +general.4551="Replays are currently supported in the following games:" +general.4552="Hypixel Replays" +general.4553="Show Replays Only" +general.4554="Show All" +general.4555="Toggle whether all your recently played games should be displayed or only games with replays attached." +general.4556="Hey .. you! Don't do that >:(" +general.4557="YOU HAVE BEEN GRANTED THE VEGGY SPRINGLAZOR™ !!!" +general.4558="Outstanding" +general.4559="Legendary Hypixel Sword Banner" +general.4560="Legendary Portal Banner" +general.4561="The Delivery Man" +general.4562="The map selector is disabled during the tournament!" +general.4563="Guild Level Reward" +general.4564="Current Streak: %%streak%%" +general.4565="Survey" +general.4566="There isn't a survey available right now!" +general.4567="You have already completed this survey!" +general.4568="There is no survey available right now! Please check back soon!" +general.4569="You have already completed this survey!" +general.4570="There is no survey available right now! Please check back soon!" +general.4571="You have already completed this survey!" +general.4572="Provide your feedback and complete this survey!" +general.4573="Complete this survey and earn 5,000 XP and 3,000 Arcade Coins!" +general.4574="Complete this survey and earn 5,000 XP!" +general.4575="Complete this survey and earn awesome rewards!" +general.4576="Survey" +general.4577="Click to complete this survey!" +general.4578="Available Games" +general.4579="Spring Hero Skin for Shaman" +general.4580="Jazz Hands Skin for Skeleton" +general.4581="Space Armor Skin for Skeleton" +general.4582="Trick Skin for Skeleton" +general.4583="Spookster Skin for Skeleton" +general.4584="Red Ted Skin for Skeleton" +general.4585="Toon Skin for Zombie" +general.4586="Jumbo Skin for Zombie" +general.4587="Taco Skin for Zombie" +general.4588="Yawn Skin for Zombie" +general.4589="Gorilla Skin for Zombie" +general.4590="Johnny Skin for Creeper" +general.4591="Bomberdude Skin for Creeper" +general.4592="Destructo Skin for Creeper" +general.4593="Kreeft Skin for Creeper" +general.4594="Cricket Skin for Creeper" +general.4595="Dash Skin for Enderman" +general.4596="Seeker Skin for Enderman" +general.4597="Gamer Skin for Enderman" +general.4598="Shadow Skin for Enderman" +general.4599="Hoops Skin for Enderman" +general.4600="Thunders Skin for Herobrine" +general.4601="Larry Skin for Herobrine" +general.4602="Sunny Skin for Herobrine" +general.4603="Boxer Skin for Herobrine" +general.4604="Odin Skin for Herobrine" +general.4605="Lethal Skin for Spider" +general.4606="Vinny Skin for Spider" +general.4607="Flutter Skin for Spider" +general.4608="Frog Skin for Spider" +general.4609="Shade Skin for Spider" +general.4610="Guardian Skin for Squid" +general.4611="Doctor Squish Skin for Squid" +general.4612="K'Tulu Skin for Squid" +general.4613="Grumps Skin for Squid" +general.4614="Sea Warrior Skin for Squid" +general.4615="Doomboy Skin for Dreadlord" +general.4616="Crowe Skin for Dreadlord" +general.4617="Rushlord Skin for Dreadlord" +general.4618="Breadlord Skin for Dreadlord" +general.4619="Sweets Skin for Dreadlord" +general.4620="Totem Skin for Shaman" +general.4621="Doggo Skin for Shaman" +general.4622="Brian the Disco Bear Skin for Shaman" +general.4623="Wolf Skin for Shaman" +general.4624="Nikolaos Skin for Shaman" +general.4625="Drufus Skin for Arcanist" +general.4626="Steele Skin for Arcanist" +general.4627="Chester Skin for Arcanist" +general.4628="Byron Boy Skin for Arcanist" +general.4629="Emperor Skin for Shaman" +general.4630="Ogre Skin for Golem" +general.4631="Bryce Skin for Golem" +general.4632="Flint Skin for Golem" +general.4633="Victor Skin for Golem" +general.4634="Gray Skin for Golem" +general.4635="Mango Skin for Blaze" +general.4636="Proto Skin for Blaze" +general.4637="Scorch Skin for Blaze" +general.4638="Chaze Skin for Blaze" +general.4639="Ghaze Skin for Blaze" +general.4640="Super Pig Skin for Pigman" +general.4641="King Pig Skin for Pigman" +general.4642="Kai Skin for Pigman" +general.4643="Picasso Skin for Pigman" +general.4644="Bandit Skin for Pigman" +general.4645="Captain Bones Skin for Pirate" +general.4646="Jameson Skin for Pirate" +general.4647="Guy Skin for Pirate" +general.4648="Parrot Frank Skin for Pirate" +general.4649="Fjodor Skin for Pirate" +general.4650="Edge Skin for Hunter" +general.4651="Tucson Skin for Hunter" +general.4652="Huppie Moon Skin for Hunter" +general.4653="Sheep Skin for Hunter" +general.4654="Cake Hunter Skin for Hunter" +general.4655="Kuba the Caveman Skin for Hunter" +general.4656="Sailor Sid Skin for Phoenix" +general.4657="Owl Skin for Phoenix" +general.4658="Ember Skin for Phoenix" +general.4659="Fringe Skin for Phoenix" +general.4660="Falcon X Skin for Phoenix" +general.4661="Crunch Skin for Werewolf" +general.4662="Bloo Skin for Werewolf" +general.4663="Duster Skin for Werewolf" +general.4664="Jake Skin for Werewolf" +general.4665="Cruze Skin for Werewolf" +general.4666="Truck Skin for Moleman" +general.4667="Mineman Tyler Skin for Moleman" +general.4668="Jolly Skin for Moleman" +general.4669="Brick Skin for Moleman" +general.4670="Graen Skin for Moleman" +general.4671="Cow Suit Skin for Cow" +general.4672="Iron Cow Skin for Cow" +general.4673="Skelly Moo Skin for Cow" +general.4674="Fungu Madness Skin for Cow" +general.4675="One Serious Bull Skin for Cow" +general.4676="Gus Skin for Snowman" +general.4677="Frozen Skin for Snowman" +general.4678="Abominable Skin for Snowman" +general.4679="Ice Bug Skin for Snowman" +general.4680="Dobu Skin for Snowman" +general.4681="Atomic Skin for Automaton" +general.4682="Fender Skin for Automaton" +general.4683="Vacuum Skin for Automaton" +general.4684="Failed Experiment Skin for Automaton" +general.4685="Crank Skin for Automaton" +general.4686="Hitguy Skin for Assassin" +general.4687="Torny Skin for Assassin" +general.4688="Connor Skin for Assassin" +general.4689="Blu Skin for Assassin" +general.4690="Okamoto Skin for Assassin" +general.4691="Bedrock Skin for Renegade" +general.4692="Traitor Skin for Renegade" +general.4693="Ara Skin for Renegade" +general.4694="Hood Skin for Renegade" +general.4695="Morde Skin for Renegade" +general.4696="Shelly Skin for Shark" +general.4697="Treasure Skin for Shark" +general.4698="Devourer Skin for Shark" +general.4699="Wata Skin for Shark" +general.4700="Bblurgbl Skin for Shark" +general.4701="Santabrine Skin for Herobrine" +general.4702="Purchase Event Experience" +general.4703="Falling behind? Purchase Event Experience to boost your level!" +general.4704="Level: %%color%%%%level%%/%%accentColor%%%%maxLevel%%" +general.4705="Buying a rank will retroactively give any Silver you would've earned from your new rank." +general.4706="%%player%% has enabled private game modifiers!" +general.4707=" - %%name%%: %%value%%" +general.4708=" - %%name%%" +general.4709="Souls" +general.4710="Creator Rank - %%rank %%prefix%%" +general.4711="Staff Rank - %%rank %%prefix%%" +general.4712="ADMINISTRATOR" +general.4713="Administrators (or Admins) are staff members that run and maintain the Hypixel Server." +general.4714="You can help them out by reporting bugs on the forums! %%url%%" +general.4715="GAME MASTER" +general.4716="Game Masters (or GMs) are staff members that moderate the Hypixel Server." +general.4717="You can help them out by using the reporting system! %%command%%" +general.4718="YOUTUBER" +general.4719="YouTubers are streamers and video makers that create Hypixel related content." +general.4720="You can find out more about the requirement for YOUTUBE rank by visiting %%url%%" +general.4721="For more information, visit %%url%%" +general.4722="Unknown!" +general.4723="View statuses for %%game%%" +general.4724="Easter Simulator Wins" +general.4725="Easter Simulator Eggs Found" +general.4726="Scuba Simulator Wins" +general.4727="Scuba Simulator Items Found" +general.4728="Scuba Simulator Total Points" +general.4729="Halloween Simulator Wins" +general.4730="Halloween Simulator Candy Found" +general.4731="Grinch Simulator Wins" +general.4732="Grinch Simulator Gifts Stolen" +general.4733="Most messages that are considered inappropriate will be filtered" +general.4734="You will see messages that are considered inappropriate" +general.4735="On" +general.4736="That player is no longer alive, sorry!" +general.4737="Categories" +general.4738="In-Game Map Selector" +general.4739="Toggles whether the "Play Again?" paper opens the Map Selector at the end of games that support it. When disabled it will queue you for a random map automatically." +general.4740="Change your Online Status." +general.4741="SMP Invite Privacy" +general.4742="Change who can send you SMP invites." +general.4743="When disabled external tools will be unable to know if you are online and your server location using the Public API." +general.4744="When disabled external tools will be unable to access your recently played games using the Public API." +general.4745="Winstreaks" +general.4746="When disabled external tools will be unable to view your winstreak information for supported games." +general.4747="Build Battle Cosmetic" +general.4748="Pumpkin Volley" +general.4749="Pumpkin Bomber" +general.4750="Afterlife" +general.4751="Jack O' Twister" +general.4752="Your best time: %%time%%" +general.4753="Never resets." +general.4754="Holidays Event Level Status" +general.4755="Winter Twister" +general.4756="Ice Bomber" +general.4757="Twirling Snowflakes" +general.4758="Shattered Ice Bed Destroy" +general.4759="Crackling Ice" +general.4760="Present Rain" +general.4761="Penguin Cage" +general.4762="Snowman Cage" +general.4763="Green Ornament Cage" +general.4764="Red Ornament Cage" +general.4765="Chimney Island Topper" +general.4766="Gingerbread House Island Topper" +general.4767="Stocking Island Topper" +general.4768="Big Present Island Topper" +general.4769="Pudding Island Topper" +general.4770="Cozy Backdrop" +general.4771="Frozen Dragon Wings Cloak" +general.4772="Comets Cloak" +general.4773="Sled Gadget" +general.4774="Enhance your festive builds with Build Battle Backdrops!" +general.4775="YOU" +general.4776="Holidays" +general.4777="No data found for your guild." +general.4778="No data found for you." +general.4779="Loading ..." +general.4780="Click to change settings!" +general.4781="%%filter%% Only" +general.4782="Loading leaderboard ..." +general.4783="No data for this\nleaderboard." +general.4784="Loading your data ..." +general.4785="Apply changes" +general.4786="Click to apply the changes!" +general.4787="Discard changes" +general.4788="Close the menu without applying changes!" +general.4789="Block alignment is showing correctly only for Vanilla Minecraft font sizes." +general.4790="This setting will save across lobbies." +general.4791="Leaderboard data is cached and does not update immediately." +general.4792="Select the %%name%%!" +general.4793="%%underline%%Leaderboard Settings" +general.4794="Discarded your leaderboard setting changes." +general.4795="Applied your leaderboard setting changes!" +general.4796="Your settings are unchanged." +general.4797="Global leaderboards\nare temporarily disabled." +general.4798="Best friends leaderboards\nare temporarily disabled." +general.4799="Your friends list is empty.\nType /f <name> to add a player\nto your friends list." +general.4800="Your best friends list\nis empty.\nType /f best <name> to mark a\nfriend as your best friend." +general.4801="This feature only works if\nyou have %%limit%% or less best friends." +general.4802="Friends leaderboards\nare temporarily disabled." +general.4803="This feature only works if\nyou have %%limit%% or less friends." +general.4804="Guild leaderboards\nare temporarily disabled." +general.4805="You are not in a guild." +general.4806="This feature only works if\nyour guild has %%limit%% or less\nguild members." +general.4807="Center" +general.4808="Block" +general.4809="Time" +general.4810="Text Alignment" +general.4811="Best Friends" +general.4812="Guild Members" +general.4813="View" +general.4814="Players" +general.4815="Mode" +general.4816="Top 10" +general.4817="Players Around You" +general.4818="You receive messages for all your friends logging in or out." +general.4819="You receive messages for only your best friends logging in or out." +general.4820="You receive no messages for your friends logging in or out." +general.4821="Best" +general.4822="This setting will save across the network." +general.4823="Left/Right Click to change!" +general.4824="Example: "Your Network Booster for TNT Games was queued. It will activate in about 1 hours 12 minutes."" +general.4825="Only available in game lobbies!" +general.4826="Most Earned" +general.4827="Least Earned" +general.4828="Sorts by achievements earned percentage least to most." +general.4829="Sorts by achievements earned percentage most to least." +general.4830="Kills as Murderer" +general.4831="Final Kills" +general.4832="Salt" +general.4833="Insane" +general.4834="Current" +general.4835="Spleef Wins" +general.4836="Overall Defusal" +general.4837="Overall Deathmatch" +general.4838="Deathmatch Wins" +general.4839="Teams Wins" +general.4840="DOM Wins" +general.4841="EXP" +general.4842="Rabbit Meteors" +general.4843="Right-click with a wand to spawn giant pumpkins that will destroy the map." +general.4844="Spawn a horde of wolves." +general.4845="Unlocked by completing a %%event%% quest!" +general.4846="Become the storm by riding the Winter Twister!" +general.4847="Fire a huge Pumpkin Laser that destroys everything in its path! Watch out for the recoil." +general.4848="Rabbits fall from the sky and explode around you!" +general.4849="It's time to make a blizzard" +general.4850="Holiday Fireworks" +general.4851="Lantern Spiral" +general.4852="Petal Gust" +general.4853="Frozen in Time" +general.4854="Rising Dragon" +general.4855="Spring Ribbons" +general.4856="A fiery dragon rises from the ashes of your battles." +general.4857="Freeze your victim in time." +general.4858="Watch your victims' souls go up into the afterlife." +general.4859="Create a gust of petals around your foe!" +general.4860="Killing an enemy will launch a cow over the moon." +general.4861="Create a fabulous display of lanterns spiraling into the sky." +general.4862="Smash ice upon your enemies." +general.4863="Spawn a present and get some gifts with every kill!" +general.4864="Send your victims into a twist." +general.4865="Launches holiday-colored fireworks into the sky!" +general.4866="Launch pumpkins into the sky from where your victim died!" +general.4867="Killing an enemy will cause their soul to separate from their body and fly around!" +general.4868="Explosion of beef!" +general.4869="Hardcore survival games focused on vanilla PvP with crafting, perks, kits and more." +general.4870="Friend Notifications" +general.4871="Friends can send you SMP invites." +general.4872="Nobody can send you SMP invites." +general.4873="Anyone can send you SMP invites." +general.4874="Click here to join a game of %%game%%!" +general.4875="Unlocked in the Tournament Hall!" +general.4876="➤ Use a random skin." +general.4877="➤ I still want to use my own skin." +general.4878="There was an error running your command :(" +general.4879="No data." +general.4880="in %%days%% days" +general.4881="You have no data yet." +general.4882="You have no data yet." +general.4883="Anniversary Knight Gadget" +general.4884="Sapling Cage" +general.4885="Cow Island Topper" +general.4886="Rain Cloud Island Topper" +general.4887="Sprout Island Topper" +general.4888="Enhance your kills in style with this TNT Death Effect!" +general.4889="Double Jump in style with this TNT Games Double Jump Effect!" +general.4890="Blitz Cosmetic" +general.4891="Unlock this particle aura to make you stand out in Blitz!" +general.4892="Enhance your kills in style with this Blitz Finisher!" +general.4893="Taunt your enemies in style with this Blitz Taunt!" +general.4894="Unlock this Victory Dance to use in Blitz!" +general.4895="Quake Cosmetic" +general.4896="Kill players in style with this Quakecraft beam!" +general.4897="Mega Walls Cosmetic" +general.4898="Unlock this set of Kill Messages to use in Mega Walls!" +general.4899="Eggs Double Jump Effect" +general.4900="Eggsplosion Death Effect" +general.4901="Rabbit Gift" +general.4902="Easter Beam" +general.4903="Leaping Bunnies Victory Dance" +general.4904="Killer Bunny Taunt" +general.4905="Colorful Chicken Rain Victory Dance" +general.4906="Bunny Kill Messages" +general.4907="Dragon Egg Aura" +general.4908="Easter Event Level Status" +general.4909="Unlocked in the Tournament Hall!" +general.4910="Bingo Sweat" +general.4911="Bingo Sweat" +general.4912="10 years of Hypixel" +general.4913="Happy 10th Anniversary!" +general.4914="Unlocked during the 10th Anniversary Event" +general.4915="%%year%% %%festival%% Event Level" +general.4916="Unlocked during the %%year%% %%festival%% Event" +general.4917="Regular text statuses." +general.4918="Statuses that show general server statistics." +general.4919="Statuses that show stats for %%game%%." +general.4920="Statuses obtained through special means." +general.4921="Statuses during various Seasonal Events." +general.4922="∙ All Classic Games (except Arena Brawl)" +general.4923="∙ Mega Walls" +general.4924="➤ A game of %%name%% is starting in 30 seconds! %%click%% to join!" +general.4925="This humble baton sold at "Sticks R Us" is actually a magic wand. Also, it blows up things." +general.4926="Bunny Lantern" +general.4927="Chickens" +general.4928="Lucky Rabbit" +general.4929="Rabbit Celebration" +general.4930="Year of the Rabbit" +general.4931="Year of the Rat" +general.4932="BBQ" +general.4933="Oink" +general.4934="Triumph" +general.4935="#1" +general.4936="Cute Ghost" +general.4937="Cute Pumpkin" +general.4938="Egg Basket" +general.4939="Breaking a bed will spawn a bunch of baby pigs." +general.4940="Guild Master: %%name%%" +general.4941="Guild Members: %%count%%" +general.4942="Guild Level: %%level%%" +general.4943="Guild Description: \n%%description%%" +general.4944="Games:\n%%games%%" +general.4945="Click to request to join!" +general.4946="You're already in this guild!" +general.4947="To request to join, you must first leave your current guild!" +general.4948="Click to change!" +general.4949="Sort the Results" +general.4950="Most Guild Members first." +general.4951="Fewest Guild Members first." +general.4952="Highest Guild Level first." +general.4953="Lowest Guild Level first." +general.4954="Sort in no apparent order." +general.4955="Ring of Fire" +general.4956="Find the fire within and send it forth." +general.4957="Flame Rings" +general.4958="Water Spout Bed Destroy" +general.4959="Farming Implement Knife Skin" +general.4960="2023 Summer Event Level Status" +general.4961="Hypixel Knight Emblem Bundle" +general.4962="Hypixel Knight (Red)" +general.4963="Hypixel Knight (Blue)" +general.4964="Thunder Kill Sound" +general.4965="Tidal Wave Gadget" +general.4966="Summer Furniture Bundle #1" +general.4967="Flamingo Float" +general.4968="Lifeguard Chair" +general.4969="Fisherman's Cooler" +general.4970="Greenhouse Planter" +general.4971="Fancy Beach Chair" +general.4972="Summer Skull Pack" +general.4973="Tropical Sands Backdrop" +general.4974="Sunny Shore Theme" +general.4975="Pineapple Cage" +general.4976="Milkshake Cage" +general.4977="Crab Island Topper" +general.4978="Sand Castle Island Topper" +general.4979="Watermelon Island Topper" +general.4980="Show off your style as Murderer with this Knife Skin!" +general.4981="Expand the environment of your houses with this incredible theme!" +general.4982="Purchase this bundle to unlock several different cosmetics!" +general.4983="Included:" +general.4984="Eliminate your enemies with style by changing the sound they hear!" +general.4985="Decorate and detail your houses with this selection of skulls!" +general.4986="Sorts by rarity" +general.4987="Category" +general.4988="Sorted by cosmetic game type" +general.4989="Total EXP: %%color%%%%amount%%/%%accentColor%%%%maxAmount%% (%%percent%%)" +general.4990="Cost: %%silver%% Event Silver" +general.4991="Unknown Year" +general.4992="Add some pizzazz to your starting area in Duels with an Emblem!" +general.4993="Page %%number%%" +general.4994="Cost: %%cost%% Event Silver" +general.4995="%%cost%% Event Silver %%discount%%% Off!" +general.4996="Tournament Position" +general.4997="Haunted Mansion Theme" +general.4998="Vampire Suit" +general.4999="Costume Suit" +general.5000="Magma Boss Suit" +general.5001="Headless Horseman Suit" +general.5002="Lonely Lighthouse Theme" +general.5003="Cathedral Theme" +general.5004="Pumpkin Suit Suit" +general.5005="Skeleton Samurai Suit" +general.5006="2023 Halloween Event Level Status" +general.5007="2022 Halloween Event Level Status" +general.5008="Eyeball Island Topper" +general.5009="Spooky Hypixel Island Topper" +general.5010="Candy Basket Cage" +general.5011="Haunted Fortress Cage" +general.5012="Dynamite Endermite Skin" +general.5013="Hero Skin" +general.5014="Bat Person Helmet" +general.5015="Halloween Spray/Kill Note Pack #1" +general.5016="Spooky Game Over" +general.5017="Monster Under the Bed" +general.5018="Party Crasher" +general.5019="Pumpkin Farm" +general.5020="Black Cat Glyph" +general.5021="Cauldron Glyph" +general.5022="Grave Glyph" +general.5023="Reanimated Painting" +general.5024="Skeleton Chair" +general.5025="Pumpkin Candy Handout" +general.5026="Mimic Chest" +general.5027="Pirate Cutout" +general.5028="Skeletal Remains" +general.5029="Cursed Flames" +general.5030="Howling Wind" +general.5031="Graveyard Rave" +general.5032="Blood Bats" +general.5033="Spider's Silk" +general.5034="Wisp Whirlwind" +general.5035="Dracula's Flight" +general.5036="Grab this amazing deal on the lawn accessory of the year!" +general.5037="Unlock this Spray/Kill Note to show off in multiple games!" +general.5038="%%spray%% Spray/Kill Note" +general.5039="Change how your armor looks with this Item Skin!" +general.5040="Applied To: %%item%%" +general.5041="Confirm Purchase" +general.5042="Swap between each year of event-themed cosmetics." +general.5043="Showing year: %%year%%" +general.5044="Epic Salmon Pet" +general.5045="Legendary Baby Skeleton Horse Pet" +general.5046="Spooky Bingo Sweat" +general.5047="Legendary Blaze Cloak" +general.5048="Participate in various bingo cards as part of the %%festival%% event! Complete objectives across the server to earn rewards!" +general.5049="Click to view cards!" +general.5050="%%festival%% Bingo" +general.5051="Bingo is currently disabled, please check back later!" +general.5052="Bingo Card: %%card%%" +general.5053="Complete objectives across the network in bingo-style to earn rewards!" +general.5054="%%color%%%%progress%%% completed" +general.5055="Click to view card!" +general.5056="%%gameType%% Task" +general.5057="%%color%%%%festival%% Task" +general.5058="Difficulty: %%color%%%%difficulty%%" +general.5059="You have completed this task!" +general.5060="You haven't completed this task yet!" +general.5061="%%magic%%H Completed the "%%objective%%" Objective for the %%color%%%%card%% Bingo Card! %%magic%%H" +general.5062="Unlocked" +general.5063="Locked" +general.5064="Complete all tasks in this given sequence to unlock the following rewards!" +general.5065="Claimed!" +general.5066="Click to claim!" +general.5067="%%sequence%% Reward" +general.5068="You need to complete all tasks in this sequence to unlock this reward!" +general.5069="Row One" +general.5070="Row Two" +general.5071="Row Three" +general.5072="Row Four" +general.5073="Row Five" +general.5074="Column One" +general.5075="Column Two" +general.5076="Column Three" +general.5077="Column Four" +general.5078="Column Five" +general.5079="Diagonal One" +general.5080="Diagonal Two" +general.5081="Completed every task on this card to unlock the following rewards!" +general.5082="Blackout Reward" +general.5083="You need to complete every task on this card to unlock this reward!" +general.5084="+%%amount%% Coins in All Minigames" +general.5085="+%%amount%% Classic Games Tokens" +general.5086="Bingo doesn't seem to exist, please report this at https://hypixel.net/bugs!" +general.5087="Unlocked during %%event%% Bingo" +general.5088="Spooky Bingo Sweat" +general.5089="Right-click to show items!" +general.5090="Pixel Party" +general.5091="Capture the Wool" +general.5092="Halloween Simulator" +general.5093="Bring all enemy wools to your base, but make sure your own wool is protected!" +general.5094="Capture The Wool" +general.5095="Capture the Wool" +general.5096="Dropper" +general.5097="Halloween Simulator" +general.5098="Pixel Party" +general.5099="Hide And Seek" +general.5100="Mystery Dust is randomly given while playing games." +general.5101="Unlock free rewards every day throughout the holidays." +general.5102=""December %%day%%%%day_ordinal%%"" +general.5103="TNT Games Cosmetic" +general.5104="Icicle" +general.5105="Holiday Spray/Kill Note Bundle #1" +general.5106="2023 Holidays Event Level Status" +general.5107="Snowball Spirit Pet Skin" +general.5108="Spirit Pet" +general.5109="North Star Skin" +general.5110="Backpacks" +general.5111="Change how your backpacks look with this Item Skin!" +general.5112="Black Gift Skin" +general.5113="Blue Gift Skin" +general.5114="Green Gift Skin" +general.5115="Purple Gift Skin" +general.5116="Gold Gift Skin" +general.5117="White Gift Skin" +general.5118="Frosted Wall Color" +general.5119="Snow Party Pants" +general.5120="Pinecone Island Topper" +general.5121="Snowy Cabin Island Topper" +general.5122="Bundled Snowman Shopkeeper Skin" +general.5123="Frosted Weapon Name Pack" +general.5124="Firnvale Theme" +general.5125="Bear Furniture Bundle" +general.5126="Bear Bench" +general.5127="Bear Bookshelf" +general.5128="Bear Chair" +general.5129="Bear Side Table" +general.5130="Bear Bed" +general.5131="Snowflake Final Kill Effect" +general.5132="Snowman Final Kill Effect" +general.5133="Gingerbread Jerry" +general.5134="Season's Greetings" +general.5135="Silent Night" +general.5136="Ugly Bed Wars Sweater" +general.5137="Snow Hat" +general.5138="North Star Balloon" +general.5139="Hot Cocoa Cage" +general.5140="Snow Globe Cage" +general.5141="Chilled Double Jump Effect" +general.5142="Thick Ice Hat" +general.5143="Arcade Games Cosmetic" +general.5144="Housing Cosmetic" +general.5145="Mode: %%mode%%" +general.5146="Make sure you look your best wile everything explodes!" +general.5147="Dress yourself up to destroy your enemies in Quakecraft" +general.5148="Display an icon or smiley face above your Final Kills!" +general.5149="Spice up your walls with a new color in Hole in the Wall!" +general.5150="Party in style with your own Party Pants for Pixel Party!" +general.5151="How else does your island float? Use your very own Balloon!" +general.5152="Slay your enemies in style with custom weapon names!" +general.5153="Change up your Shopkeeper in Bed Wars with Shopkeeper Skins" +general.5154="%%cardColor%%%%card%%: %%percentColor%%%%percent%%% completed" +general.5155="Epic White Baby Rabbit Pet" +general.5156="Legendary Snow Click Effect" +general.5157="Legendary Packed Ice Pet" +general.5158="EASY" +general.5159="MEDIUM" +general.5160="HARD" +general.5161="Mystery Dust Delivery" +general.5162="Your free monthly %%amount%% Mystery Dust for %%month%% has arrived!" +general.5163="You earned %%amount%% Mystery Dust!" +general.5164="You have reached the Mystery Dust cap!" +general.5165="+%%amount%% Event Experience (Daily Cap)" +general.5166="HYPIXEL %%game%% tournament is live!" +general.5167="Compete, climb the leaderboard and earn free rewards!" +general.5168="Earn tributes by playing!" +general.5169="Click HERE to enter the Tournament Hall!" +general.5170="Click to join the tournament hall!" +general.5171="HYPIXEL is hosting a %%game%% tournament!" +general.5172="To participate, visit the hall on %%month%% %%day%%%%ordinal%%" +general.5173="Click HERE to read the announcement!" +general.5174="Click to view!" +general.5175="Tournament Summary" +general.5176="%%type%% - %%bracket%% bracket" +general.5177="MVP: %%player%% with %%points%% points" +general.5178="You earned (hover!): %%points%%" +general.5179="You earned: %%points%%" +general.5180="%%underline%%Breakdown" +general.5181="%%what%% (x%%occur%%): %%points%% points" +general.5182="Total Points: %%total%% Position: #%%pos%%" +general.5183="Total Points: %%total%%" +general.5184="Bracket: %%progress%%" +general.5185="You didn't earn any tributes this game because you reached the max amount (%%max%%) of tributes this tournament" +general.5186="Climb the leaderboards to gain bonus tributes" +general.5187="You didn't earn any tributes this game" +general.5188="Earn tributes from winning and spend them on unique rewards in the Tournament Hall" +general.5189="Also earned: +%%earned_this_game%% Tributes" +general.5190="Spend tributes on unique rewards!" +general.5191="%%mode%% TOURNAMENT" +general.5192="This is a %%bracket%% bracket game" +general.5193="Points: %%positive%%" +general.5194="%%hours%%h%%mins%%m remaining for the tournament!" +general.5195="Less than an hour left" +general.5196="Earn points to climb up the Tournament Leaderboard" +general.5197="Visit the Tournament Hall for more info" +general.5198="Points to retain bracket: %%earned%%/%%required%%" +general.5199="%%before%% retained! (minimum bracket)" +general.5200="You are in the lowest bracket,\ncan't go any lower. :(" +general.5201="%%before%% retained! (best bracket!)" +general.5202="You are in the top bracket! Congrats!" +general.5203="%%before%% retained!" +general.5204="Demoted! %%before%% ➜ %%after%%" +general.5205="PROMOTED! %%before%% ➜ %%after%%" +general.5206="Your bracket determines the\namount of points you earn per game." +general.5207="%%points%% Tournament Point" +general.5208="%%points%% Tournament Points" +general.5209="+%%amount%% Tributes (%%reason%%)" +general.5210="Spend Tributes in the Tournament Hall\nfor unique Hypixel rewards!\n\nYou may earn up to %%max%% tributes per tournament.\nYou earned %%earned%% so far!" +general.5211="Resets in less than an hour." +general.5212="Resets in a month and a day." +general.5213="Resets in a month and %%days%% days." +general.5214="Resets in %%months%% months and a day." +general.5215="Resets in %%months%% months and %%days%% days." +general.5216="Resets in a month." +general.5217="Resets in %%months%% months." +general.5218="Resets in a day and 1 hour." +general.5219="Resets in a day and %%hours%% hours." +general.5220="Resets in %%days%% days and 1 hour." +general.5221="Resets in %%days%% days and %%hours%% hours." +general.5222="Resets in a day." +general.5223="Resets in %%days%% days." +general.5224="Resets in an hour." +general.5225="Resets in %%hours%% hours." +general.5226="Resets in less than an hour" +general.5227="%%fortune%% was radiating with Generosity, so you got an Experience Bag!" +general.5228="%%fortune%% and %%fortune1%% were radiating with Generosity, so you got 2 Experience Bags!" +general.5229="%%amount%% players were radiating with Generosity, so you got a Mega Experience Bag!" +general.5230="%%amount%% were radiating with Generosity, so you got %%amount%% Experience Bags!" +general.5231="+%%amount%% %%game%% %%currencyType%%" +general.5232="Spend %%game%% %%currencyType%% in the %%game%% Lobby to unlock upgrades and cosmetics. Arcade %%currencyType%% can also be converted to other types of %%currencyType%% in the Arcade Lobby." +general.5233="Spend %%game%% %%currencyType%% in the %%game%% Lobby to unlock cosmetics" +general.5234="Spend %%game%% %%currencyType%% in the %%game%% Lobby to unlock upgrades and cosmetics" +general.5235="Bunny Bench" +general.5236="Egg Painting Station" +general.5237="Little Chick Tea Table" +general.5238="Little Chick Dresser" +general.5239="Little Chick Bed" +general.5240="You can't afford this!" +general.5241="Purchase with %%currency%%" +general.5242="Event Silver" +general.5243="Something went wrong, please report this!" +general.5244="Purchasing event items in game shops is currently disabled, sorry!" +general.5245="Currently unavailable!" +general.5246="Event: %%color%%%%festival%%" +general.5247="Cost: %%cost%% / %%silver%% Event Silver" +general.5248="All purchased!" +general.5249="Click to view items!" +general.5250="Check out a variety of similar cosmetics that you can pick and choose from!" +general.5251="Pick which games you want to purchase this cosmetic in!" +general.5252="Available Games:" +general.5253="Unlock this Death Cry to use in %%gameType%%." +general.5254="Unlock this Death Cry to show off in multiple games!" +general.5255="%%deathCry%% Death Cry" +general.5256="Unlock this set of Kill Messages to show off in %%gameType%%." +general.5257="Unlock this set of Kill Messages to show off in multiple games!" +general.5258="%%killMessages%% Kill Messages" +general.5259="Unlock this Kill Note to show off in %%gameType%%." +general.5260="Unlock this Spray to show off in %%gameType%%." +general.5261="Unlock this Spray to show off in multiple games!" +general.5262="%%killNote%% Kill Note" +general.5263="%%killEffect%% Kill Effect" +general.5264="%%projectileTrail%% Projectile Trail" +general.5265="%%victoryDance%% Victory Dance" +general.5266="Start the animation with your very own Animated Hat!" +general.5267="Show off your moves with your very own Gestures." +general.5268="Always get the final word in with these Last Words!" +general.5269="Rooted" +general.5270="Bee Abduction" +general.5271="➤ A game of %%name%% is available to join! %%click%% to join!" +general.5272="Total %%currency%%: %%color%%%%amount%%" +general.5273="You must be at least %%rank%% to use that!" +general.5274="Random Favorite" +general.5275="Class Levels" +general.5276="Allows for the increase or decrease of Class Levels" +general.5277="Energy Gain" +general.5278="Allows for the increase or decrease of Energy Gain" +general.5279="0.5x Energy" +general.5280="0.75x Energy" +general.5281="1x Energy" +general.5282="1.5x Energy" +general.5283="2x Energy" +general.5284="Game Duration" +general.5285="Allows for the increase or decrease of the Game Duration" +general.5286="15 Minutes" +general.5287="30 Minutes" +general.5288="45 Minutes" +general.5289="1 Hour" +general.5290="2 Hours" +general.5291="Health" +general.5292="Allows for the increase or decrease of Health" +general.5293="0.5x Health" +general.5294="0.75x Health" +general.5295="1x Health" +general.5296="1.5x Health" +general.5297="2x Health" +general.5298="Instant Deathmatch" +general.5299="Enable for Instant Deathmatch" +general.5300="Permanent Jump Boost" +general.5301="Enable for Permanent Jump Boost" +general.5302="Permanent Saturation" +general.5303="Enable for Permanent Saturation" +general.5304="Permanent Speed" +general.5305="Enable for Permanent Speed" +general.5306="Permanent Strength" +general.5307="Enable for Permanent Strength" +general.5308="Preparation Time" +general.5309="Allows for the increase or decrease of Preparation Time" +general.5310="No Preparation Time" +general.5311="1 Minute" +general.5312="5 Minutes" +general.5313="7 Minutes 35 Seconds" +general.5314="20 Minutes" +general.5315="Time of Day" +general.5316="Allows for changing time of day" +general.5317="Morning" +general.5318="Afternoon" +general.5319="Evening" +general.5320="Night" +general.5321="Midnight" +general.5322="Wither Health" +general.5323="Allows for the increase or decrease of the Wither Healths" +general.5324="No Withers" +general.5325="100 HP" +general.5326="500 HP" +general.5327="1000 HP" +general.5328="1500 HP" +general.5329="Wither Rage Duration" +general.5330="Allows for the increase or decrease of the Wither Rage Duration" +general.5331="No Wither Rage" +general.5332="10 Minutes" +general.5333="Sparkler" +general.5334="Flamingo" +general.5335="Wool Wars Wins" +general.5336="Wool Wars Kills" +general.5337="Wool Wars Deaths" +general.5338="Wool Wars Assists" +general.5339="Wool Wars Wool Placed" +general.5340="Wool Wars Blocks Broken" +general.5341="Capture the Wool Kills" +general.5342="Capture the Wool Wools Captured" +general.5343="Sheep Wars Wins" +general.5344="Sheep Wars Kills" +general.5345="Sheep Thrown" +general.5346="You cannot add any more keywords." +general.5347="Invalid usage! Use: /block add <player>" +general.5348="You cannot block yourself." +general.5349="You've already blocked that player! /block remove <player> to unblock them!" +general.5350="You have reached the maximum of %%limit%% blocked players!" +general.5351="An error occured trying to block that player!" +general.5352="You can't block this player!" +general.5353="Blocked %%player%%." +general.5354="Block a player." +general.5355="Manage your block list." +general.5356="You can't use this yet! Please check back later." +general.5357="Unknown argument '%%arg%%'!" +general.5358="Block commands:" +general.5359="Prints this help message." +general.5360="Invalid usage! Use: %%usage%%" +general.5361="The page number must be positive!" +general.5362="I don't know how to parse page number %%number%%!" +general.5363="You have not blocked anyone." +general.5364="------ No Blocked Players ------" +general.5365="%yellow%%------ Blocked Players (Page %%page%% of %%max_page%%) ------" +general.5366="page" +general.5367="List blocked players." +general.5368="Unblock all players." +general.5369="Nothing happened." +general.5370="You're about to remove ALL blocked players. Are you sure you want to do this?" +general.5371="CANCEL" +general.5372="Click to cancel and keep the players blocked." +general.5373="CLEAR BLOCKED PLAYERS LIST" +general.5374="Click to clear your blocked players list." +general.5375="Please wait before doing this again." +general.5376="There is no pending removeall. Run /block removeall again." +general.5377="You have not blocked any players." +general.5378="There was a problem clearing your blocked players list! Please report this." +general.5379="Removed all blocked players." +general.5380="Invalid usage! Use: /block remove <player>" +general.5381="Can't find that player!" +general.5382="An unexpected error occured while trying to unblock." +general.5383="You don't have that player blocked." +general.5384="There was an unexpected error while trying to unblock." +general.5385="There was an unexpected error while trying to unblock %%player%%." +general.5386="Unblocked %%player%%." +general.5387="Unblock a player." +general.5388="%red%%Unblock Player" +general.5389="Click here to remove %%player%% from your block list." +general.5390="Block Player" +general.5391="Click here to add %%player%% to your block list." +general.5392="Allows setting up additional words that play a ping sound and are highlighted when mentioned in chat." +general.5393="CHAT KEYWORDS" +general.5394="Click to add a keyword!" +general.5395="[ADD KEYWORD]" +general.5396="You can have up to %%max%% keywords at once." +general.5397="You have no chat keywords defined." +general.5398="Click to remove '%%word%%' as a chat keyword!" +general.5399="Keyword was\ntoo long" +general.5400="Keyword is\ntoo short" +general.5401="Keyword had\ninvalid char" +general.5402="'%%word%%' is already on your chat keywords list!" +general.5403="Added '%%word%%' to your chat keywords!" +general.5404="There was an issue adding '%%word%%' to your chat keywords!" +general.5405="You don't have that keyword on your list!" +general.5406="Removed '%%word%%' from your chat keywords!" +general.5407="There was an issue removing '%%word%%' from your chat keywords!" +general.5408="Click to modify keywords!" +general.5409="Click to add keywords!" +general.5410="Chat Keywords" +general.5411="Comfy Web" +general.5412="Gothic Jerry" +general.5413="Haunted Conscience" +general.5414="Pumpkin Pals" +general.5415="Browse your unlocked %%gamename%% cosmetics, or buy them directly with %%currency%%." +general.5416="ENABLED" +general.5417="DISABLED" +general.5418="Anyone" +general.5419="Currently: %%status%%" +general.5420="DISABLED" +general.5421="ENABLED" +general.5422="Options:" +general.5423="Public Profanity Filter" +general.5424="Change if the profanity filter should censor public chat." +general.5425="Party Profanity Filter" +general.5426="Change if the profanity filter should censor party chat." +general.5427="Guild Profanity Filter" +general.5428="Change if the profanity filter should censor guild chat." +general.5429="PM Profanity Filter" +general.5430="Change if the profanity filter should censor private messages." +general.5431="Change who can send you Duel requests." +general.5432="Receive messages when your fellow friends log in or out" +general.5433="Change who can private message you." +general.5434="Online Game Stats" +general.5435="When disabled your player stats will be frozen to external tools while you are online." +general.5436="Class: %%class%%" +general.5437="Food: %%food%%%" +general.5438="Health: %%health%%%" +general.5439="Health: %%health%% ❤" +general.5440="%%listing%%%%andPrefix%% and %%lastValue%%" +general.5441="%%listing%%%%andPrefix%% and %%lastValue%%." +general.5442="Cost: %%cost%% %%currency%%" +general.5443="Your recent %%type%% report has been reviewed and a punishment was issued. Please continue using /report to help us keep rule breakers in check!" +general.5444="Your recent %%type%% report has been reviewed and was deemed insufficient. Although a punishment wasn't issued, this report has been logged for future reference. Please continue using /report to help us keep rule breakers in check!" +general.5445="Your recent %%count%% %%type%% reports have been reviewed and punishments were issued. Please continue using /report to help us keep rule breakers in check!" +general.5446="Your recent %%count_and_type_1%%, and %%count_and_type_2%% reports have been reviewed and punishments were issued. Please continue using /report to help us keep rule breakers in check!" +general.5447="Bingo" +general.5448="No pinned card yet!" +general.5449="You can pin a Bingo Card that you're working on completing here! Simply right-click it in the Overview Menu or click the Pin icon when viewing the full card." +general.5450="Click to browse cards!" +general.5451="Next Card: %%card%%" +general.5452="Switch to the next difficulty of your game category." +general.5453="Click to switch!" +general.5454="Complete %%percent%%% of the %%current%% Card to unlock this one!" +general.5455="Current Progress: %%coloredProgress%%" +general.5456="Change Focused Cards" +general.5457="Focus Category" +general.5458="This will be the set of Bingo Cards in your menu. You can change categories at any time, and can complete them all if you wish!" +general.5459="Click to focus!" +general.5460="%%cardColor%%%%card%%: %%coloredProgress%% completed" +general.5461="%%category%% Bingo Cards" +general.5462="You can't pin this card!" +general.5463="%%category%%: %%coloredPercent%% completed" +general.5464="Click to view your focused card!" +general.5465="Participate in various bingo cards as part of the Hypixel Anniversary event! Complete objectives across the server to earn rewards!" +general.5466="This event is now over, sorry!" +general.5467="%%year%%%%suffix%% Anniversary Bingo" +general.5468="Bingo Shop" +general.5469="Spend your hard-earned Bingo Bucks on various exclusive cosmetics!" +general.5470="Your Bucks: %%bucks%%" +general.5471="Click to shop!" +general.5472="Already owned!" +general.5473="You must complete any %%difficulty%% card to unlock this!" +general.5474="Click to confirm purchase!" +general.5475="Difficulty: %%difficulty%%" +general.5476="Rarity: %%rarity%%" +general.5477="Added: %%year%%" +general.5478="Cost: %%cost%% Bingo Bucks" +general.5479="You purchased the %%cosmetic%% %%type%%!" +general.5480="You don't have enough Bingo Bucks to purchase that!" +general.5481="+%%amount%% Bingo Bucks" +general.5482="Salmon Pet" +general.5483="Skeleton Horse (Baby) Pet" +general.5484="Blaze Cloak" +general.5485="Rabbit: White (Baby) Pet" +general.5486="Snow Click Effect" +general.5487="Packed Ice Pet" +general.5488="Pastel Sheep Pet" +general.5489="Hay Bale Pet" +general.5490="Feathered Cloak" +general.5491="Squid Morph" +general.5492="Rocket Punch Messages" +general.5493="Flying Guardian Pet" +general.5494="Pig Cannon Gadget" +general.5495="Melon Pet" +general.5496="Casual Easy" +general.5497="This card contains easier objectives for casual games." +general.5498="Casual Hard" +general.5499="This card contains harder objectives for casual games." +general.5500="PvP Easy" +general.5501="This card contains easier objectives for PvP focused games." +general.5502="PvP Hard" +general.5503="This card contains harder objectives for PvP focused games." +general.5504="Classic Easy" +general.5505="This card contains easier objectives for our more classic games." +general.5506="Classic Hard" +general.5507="This card contains harder objectives for our more classic games." +general.5508="Egg Meteors" +general.5509="Eggs rain down around you, destroying the map!" +general.5510="Bee That Chicken" +general.5511="Flowers For You" +general.5512="Lazy Spring" +general.5513="Painted Dragon Egg" +general.5514="Forum Nerd" +general.5515="Forum Expert" +general.5516="Forum Veteran" +general.5517="Forum Professional" +general.5518="Forum Legend" +general.5519="Unlocked by obtaining the %%title%% title on the Hypixel Forums!" +general.5520="Forums" +general.5521="Statuses related to the Hypixel Forums." +general.5522="Sand Castle" +general.5523="Sea Bass" +general.5524="Sloth Burn" +general.5525="Surfs Up" +general.5526="2025 Summer Event Level Status" +general.5527="Search" +general.5528="Click to search!" +general.5529="Fish in style by adding fancy effects to your bobber while fishing in the Main Lobby!" +general.5530="Even Vampires can have style! Change up your color scheme for hunting Survivors with this Vampire Color cosmetic!" +general.5531="Starting Sword" +general.5532="Starting Swords" +general.5533="Wood Skin" +general.5534="Wood Skins" +general.5535="Change what Sword you spawn and respawn with. This does not change your damage." +general.5536="Golden Sword" +general.5537="Select %%name%% as your %%category%%. This sword is cosmetic only and does not change the damage inflicted." +general.5538="The type of wood you will receive as a building block." +general.5539="Oak Planks" +general.5540="Spruce Planks" +general.5541="Birch Planks" +general.5542="Jungle Planks" +general.5543="Acacia Planks" +general.5544="Dark Oak Planks" +general.5545="Oak Logs" +general.5546="Spruce Logs" +general.5547="Birch Logs" +general.5548="Jungle Logs" +general.5549="Acacia Logs" +general.5550="Dark Oak Logs" +general.5551="Select %%name%% as the wood you will receive as a building block." +general.5552="Requires: %%achievement%% Achievement" +general.5553="Available during the %%name%% Event!" +general.5554="This cosmetic can only be purchased during the %%name%% Seasonal Event!" +general.5555="Witch Ritual" +general.5556="Pumpkin Spice-Powered" +general.5557="Coffin Island Topper" +general.5558="Crystal Ball Island Topper" +general.5559="Coffin Cage" +general.5560="Crow Cage" +general.5561="RIP Emblem" +general.5562="Halloween Spray/Kill Note Pack #3" +general.5563="Haunted House" +general.5564="Vampire Jerry" +general.5565="Murder Mystery Poster" +general.5566="Ouija" +general.5567="Disasters: Survivals" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/general_goliath.properties b/configuration/i18n/en_US/official/general_goliath.properties new file mode 100644 index 000000000..d44169c83 --- /dev/null +++ b/configuration/i18n/en_US/official/general_goliath.properties @@ -0,0 +1,790 @@ +general_goliath.0="I couldn't find any PUBLIC messages from that player in the last 10 minutes!" +general_goliath.1="Your chat report has been logged for staff review, thank you! :)" +general_goliath.2="You don't have any pending chat reports!" +general_goliath.3="Use: /chatreport (username)" +general_goliath.4="I couldn't find anyone with that name. Please check the spelling!" +general_goliath.5="You can't report yourself!" +general_goliath.6="Please open a support ticket with evidence!" +general_goliath.7="Please type /chatreport confirm to log %%player_name%%'s recent PUBLIC chat for staff review." +general_goliath.8="There are already reports against %%player_name%%" +general_goliath.9="Priority is already high for the open report against %%player_name%%!" +general_goliath.10="Increased priority for the open report against %%player_name%%!" +general_goliath.11="CHAT REPORT" +general_goliath.12="WARNING" +general_goliath.13="Please keep chat appropriate and follow our rules. If you continue breaking the rules, you may be muted or banned. A list of rules can be found at https://hypixel.net/rules" +general_goliath.14="Your report against %%player_name%% has been addressed! Thanks for your help!" +general_goliath.15="Thanks for your report. We understand your concerns, but currently, this is not something we can take action on." +general_goliath.16="We need more evidence regarding your chat report against %%player_name%%! Please open a report at https://hypixel.net/report" +general_goliath.17="A staff member increased the priority on your chatreport against %%player_name%%!" +general_goliath.18="Mystery %%plural%%" +general_goliath.19="Box" +general_goliath.20="Boxes" +general_goliath.21="%%amount%% Mystery Dust" +general_goliath.22="You claimed your %%reward%% %%plural%%!" +general_goliath.23="reward" +general_goliath.24="rewards" +general_goliath.25="Guild Commands:" +general_goliath.26="Prints this help message" +general_goliath.27="The guild invite from %%name%% has expired" +general_goliath.28="The guild invite to %%player%% has expired" +general_goliath.29="The guild invites to %%players%% have expired" +general_goliath.30="The guild join request to %%name%% has expired" +general_goliath.31="The guild join request from %%player%% has expired" +general_goliath.32="The guild join requests from %%players%% have expired" +general_goliath.33="Couldn't find a guild by your old ID!" +general_goliath.34="<message>" +general_goliath.35="That message is too long!" +general_goliath.36="You are chatting too fast! Slow down!" +general_goliath.37="You are chatting too fast! You must wait %%time%% in between messages." +general_goliath.38="You are not in a guild!" +general_goliath.39="You are not in a guild and have been moved to the %%channel%% channel!" +general_goliath.40="Your guild's chat is muted for %%time%%!" +general_goliath.41="You're currently guild muted for %%time%%!" +general_goliath.42="You cannot send guild chat with your guild chat disabled! Use %%command%% to enable it!" +general_goliath.43="/g toggle" +general_goliath.44="Officer" +general_goliath.45="Guild" +general_goliath.46="Click here to view %%player%%'s profile" +general_goliath.47="/guild accept " +general_goliath.48="You have been invited to these guilds while offline: %%guilds%%" +general_goliath.49="Your invitation to "%%guild%%" has been cancelled due the Guild being full!" +general_goliath.50="You joined %%guild%%!" +general_goliath.51="GUILD QUEST COMPLETED!" +general_goliath.52="The guild has completed this week's Guild Quest!" +general_goliath.53="GUILD QUEST TIER %%tier%% COMPLETED!" +general_goliath.54="The guild has completed Tier %%tier%% of this week's Guild Quest!" +general_goliath.55="+%%amount%% Guild Experience" +general_goliath.56="You got %%multiplier%%x Guild Exp because of your Guild Catch Up Multiplier" +general_goliath.57="LEVEL UP!" +general_goliath.58="The Guild has reached Level %%level%%!" +general_goliath.59="ACHIEVEMENT UNLOCKED" +general_goliath.60="The Guild has unlocked %%achievement%% %%tier%%!" +general_goliath.61="%%player%% transferred Guild Master rank to %%newPlayer%%" +general_goliath.62="Something went wrong whilst transferring this guild! Please report this! (Error: gtransfer-nodef)" +general_goliath.63="%%player%% disbanded the guild." +general_goliath.64="You cannot have a guild name longer than %%char%% characters!" +general_goliath.65="You cannot have [TAG]s in your guild name!" +general_goliath.66="There is already a guild by the name of %%guild%%!" +general_goliath.67="Unmute a player or the whole guild" +general_goliath.68="<player/everyone>" +general_goliath.69="The guild is not muted!" +general_goliath.70="%%sender%% has unmuted the guild chat!" +general_goliath.71="%%sender%% has unmuted %%name%%" +general_goliath.72="You have been unmuted!" +general_goliath.73="This player is not muted!" +general_goliath.74="You cannot transfer your Guild to yourself!" +general_goliath.75="%%player%% cannot be a Guild Master as they are not VIP+" +general_goliath.76="================== WARNING ==================\nThis will transfer the guild OUT OF YOUR CONTROL. It cannot be undone.\nIf you wish to continue, /guild confirm within 10 seconds." +general_goliath.77="Transfers ownership of the guild to another player" +general_goliath.78="Disabled guild chat!" +general_goliath.79="Enabled guild chat!" +general_goliath.80="Toggle guild chat for yourself" +general_goliath.81="No access." +general_goliath.82="You have not unlocked any Guild Tag colors! You can do so by gaining Guild Exp and leveling up your guild." +general_goliath.83="Invalid usage! Correct usage: /guild tag HYP or /guild tag reset" +general_goliath.84="The Guild [TAG] can't be longer than %%length%% characters!" +general_goliath.85="The Guild [TAG] must only contain letters and numbers!" +general_goliath.86="The Guild [TAG] contains blacklisted words!" +general_goliath.87="%%player%% set the guild tag to [%%tag%%]! You may have to change lobbies for it to update." +general_goliath.88="Sets the guild [TAG]" +general_goliath.89="Your Guild must be at least level %%level%% to set a Guild Tag!" +general_goliath.90="%%player%% set the guild tag color to %%color%%! You may have to change lobbies for it to update." +general_goliath.91="Your Guild has not unlocked any Guild Tag Colors!" +general_goliath.92="You can set your Guild Tag to any of the following colors:" +general_goliath.93="Click to set your Guild Tag Color to %%color%%" +general_goliath.94="Click a color to select it." +general_goliath.95=" Guild > %%name%% disabled the chat throttle!" +general_goliath.96=" Guild > %%name%% enabled the chat throttle! You can only send messages every 10 seconds" +general_goliath.97="Toggle slow chat, requiring guild members to wait 10 seconds between messages" +general_goliath.98="The Guild Shop is no longer available. All former perks are now unlocked for everyone by default." +general_goliath.99="Show the Guild Shop" +general_goliath.100="Invalid value '%%value%%'! Should be true/false" +general_goliath.101="%%player%% enabled %%option%%" +general_goliath.102="%%player%% disabled %%option%%" +general_goliath.103="%%player%% set the Guild Description to %%description%%" +general_goliath.104="Sorry, I couldn't recognize that game!" +general_goliath.105="%%player%% removed %%game%% as a Guild Game." +general_goliath.106="%%player%% added %%game%% as a Guild Game." +general_goliath.107="Only usable by Guild Master" +general_goliath.108="Settings:" +general_goliath.109="<setting> <value>" +general_goliath.110="Modify settings for your guild" +general_goliath.111="Whether or not the guild is publicly listed. This lets players join without being invited." +general_goliath.112="Modify the Guild's description in the Guild Finder." +general_goliath.113="Guild Visibility" +general_goliath.114="Guild Games" +general_goliath.115="Lets you change the Guild's preferred games. This lets new players find a guild that's active in the games they play most frequently." +general_goliath.116="%%player%% renamed the guild to %%name%%!" +general_goliath.117="Renames the Guild" +general_goliath.118="Guild Quest Progress" +general_goliath.119="To complete the quest, Guild Members need to complete Challenges in any game." +general_goliath.120="Reward: %%amount%% Guild Experience for each tier" +general_goliath.121="Shows information regarding the current Guild Quest" +general_goliath.122="%%player%% is not in your guild!" +general_goliath.123="%%player%% is the guild master so can't be promoted anymore!" +general_goliath.124="You haven't created any ranks! You need to create some using %%command%%!" +general_goliath.125="%%name%% is already the highest rank you've created!" +general_goliath.126="You can only promote up to your own rank!" +general_goliath.127="You cannot promote yourself!" +general_goliath.128="%%player%% was promoted from %%oldRank%% to %%rank%%" +general_goliath.129="Promotes the player to the next rank" +general_goliath.130="Modify a rank's permissions" +general_goliath.131="Guild Party" +general_goliath.132="Forms a party from your online Guild Members" +general_goliath.133="Disabled guild online mode!" +general_goliath.134="Enabled guild online mode!" +general_goliath.135="Toggle if offline players are displayed in the guild list" +general_goliath.136="Guild Name: %%name%%" +general_goliath.137="Total Members: %%total%%" +general_goliath.138="Online Members: %%online%%" +general_goliath.139="Offline Members: %%offline%%" +general_goliath.140="Show the current online members of your guild" +general_goliath.141="You don't have access to the officer chat!" +general_goliath.142="Send a chat message to your guild officer chat channel" +general_goliath.143="Disabled guild join/leave notifications!" +general_goliath.144="Enabled guild join/leave notifications!" +general_goliath.145="Toggle guild join/leave notifications" +general_goliath.146="Mutes a player or the whole guild" +general_goliath.147="<player/everyone> <time>" +general_goliath.148="Invalid time format! Try %%example%%" +general_goliath.149="7D, 1D, 6H, 1H" +general_goliath.150="You cannot mute someone for less than a minute" +general_goliath.151="You cannot mute someone for more than one month" +general_goliath.152="%%sender%% has muted the guild chat for %%time%%" +general_goliath.153="The guild chat has been muted for %%time%%" +general_goliath.154="You cannot mute the guild master!" +general_goliath.155="You cannot mute yourself from the guild!" +general_goliath.156="This player is already muted!" +general_goliath.157="You have been guild muted for %%time%% by %%name%%" +general_goliath.158="Guild MOTD Commands: " +general_goliath.159="Guild MOTD" +general_goliath.160="Guild MOTD Preview" +general_goliath.161="Modifies the MOTD for the Guild" +general_goliath.162="You do not have a MOTD! Use /guild motd add to add one!" +general_goliath.163="List lines in the MOTD" +general_goliath.164="Line number must be greater than 0!" +general_goliath.165="Set line #%%line%% to '%%message%%'!" +general_goliath.166="There is no line #%%line%%! Try /guild motd add" +general_goliath.167="Invalid line number '%%line%%'!" +general_goliath.168="Adds a line in the MOTD" +general_goliath.169="The Guild MOTD can only be %%lines%% lines!" +general_goliath.170="Preview what the MOTD will look like to players" +general_goliath.171="There is no Guild MOTD!" +general_goliath.172="Cleared Guild MOTD" +general_goliath.173="Clears the MOTD" +general_goliath.174="Lists players in your guild" +general_goliath.175="Sets a line in the MOTD" +general_goliath.176="Set line #%%line%% to '%%message%%'!" +general_goliath.177="<text>" +general_goliath.178="Opens the Guild Menu" +general_goliath.179="%%player%% is not in your guild!" +general_goliath.180="Rank: %%rank%%" +general_goliath.181="Joined: %%date%%" +general_goliath.182="Rank last changed by: %%by%%" +general_goliath.183="Rank last changed at: %%date%%" +general_goliath.184="Guild Exp Contributions:" +general_goliath.185="Today: " +general_goliath.186="You are the Guild Master! You cannot leave until you /guild disband or /guild transfer!" +general_goliath.187="You left the guild" +general_goliath.188="%%player%% left the guild!" +general_goliath.189="Leaves your current guild" +general_goliath.190="You cannot kick yourself from the guild!" +general_goliath.191="Kicks the player from your guild" +general_goliath.192="You cannot kick %%player%% because they are an %%rank%%!" +general_goliath.193="You cannot kick %%player%% because they are a %%rank%%!" +general_goliath.194="You do not have permission to kick people from the guild!" +general_goliath.195="You were kicked from the guild by %%player%% for reason '%%reason%%'" +general_goliath.196="%%player%% was kicked from the guild by %%kicker%%!" +general_goliath.197="Request to join the specified guild" +general_goliath.198="<player> <reason>" +general_goliath.199="Could not find a guild by the name of or with the member '%%search%%'!" +general_goliath.200="You requested to join %%name%%! They have 5 minutes to accept!" +general_goliath.201="You've already requested to join %%name%%! Wait for them to accept!" +general_goliath.202="This Guild has joins disabled! Ask the Guild Master, %%master%% to invite you!" +general_goliath.203="%%inviter%% has requested to join the Guild!\n" +general_goliath.204="Click here to accept or type /guild accept %%acceptName%%!\n" +general_goliath.205="Click to run\n/guild accept %%player%%" +general_goliath.206="You do not have permission to invite players!" +general_goliath.207="You cannot invite this player to your guild!" +general_goliath.208="%%player%% is already in your guild!" +general_goliath.209="Your guild is full!" +general_goliath.210="%%player%% is already in another guild!" +general_goliath.211="<player>" +general_goliath.212="%%inviter%% has invited you to join their guild, %%guild%%!\n" +general_goliath.213="Click here to accept or type /guild accept %%master%%!\n" +general_goliath.214="Invites the player to your guild" +general_goliath.215="You invited %%player%% to your guild. They have 5 minutes to accept." +general_goliath.216="%%inviter%% has invited you to join their guild, %%guild%%! Use /guild accept %%master%% to join!" +general_goliath.217="You sent an offline invite to %%player%%! They will have 5 minutes to accept once they come online!" +general_goliath.218="Created: %%date%%" +general_goliath.219="Members: %%members%%/%%max%%" +general_goliath.220="Description: %%description%%" +general_goliath.221="not set" +general_goliath.222="MOTD last edited: unknown" +general_goliath.223="MOTD last edited by %%player%% at %%date%%" +general_goliath.224="Guild Exp: %%exp%%" +general_goliath.225="Guild Level: %%level%% (%%percent%%%%%aqua%% to Level %%plusOne%%)" +general_goliath.226="Prints information about your guild" +general_goliath.227="Incorrect usage, try one of the following:\n/guild history\n/guild log (page number)" +general_goliath.228="'%%input%%' is not a valid page number." +general_goliath.229="There is no recent history to display." +general_goliath.230="Page must be between 1 and %%page%%." +general_goliath.231="24 hour Guild History (Page %%page%%/%%max%%)" +general_goliath.232="View the last 24 hours of guild events" +general_goliath.233="Your Guild does not have a Discord invite link!" +general_goliath.234="To change the link, use /guild discord (invite link) or /guild discord reset to remove it." +general_goliath.235="That doesn't appear to be a valid Discord invite link!" +general_goliath.236="%%player%% updated the Guild Discord invite link." +general_goliath.237="Set or view the guild's discord link" +general_goliath.238="Disbands the guild" +general_goliath.239="%%player%% is the guild master so can't be promoted anymore!" +general_goliath.240="%%name%% is already the lowest rank you've created!" +general_goliath.241="You can only demote up to your own rank!" +general_goliath.242="You cannot demote yourself!" +general_goliath.243="%%player%% was demoted from %%oldRank%% to %%rank%%" +general_goliath.244="Demotes the player to the previous rank" +general_goliath.245="You must be VIP+ to create a guild!\nHowever, you can still join other peoples' guilds!" +general_goliath.246="You must be have purchased a rank to create a guild!\nHowever, you can still join other peoples' guilds!" +general_goliath.247="You created the %%guild%% guild!" +general_goliath.248="Creates a guild with the specified name" +general_goliath.249="name" +general_goliath.250="You haven't used a confirmable command, or the command expired!" +general_goliath.251="Must be a player to run this command!" +general_goliath.252="You must be in a guild to use this command!" +general_goliath.253="You must be the Guild Master to use that command!" +general_goliath.254="Your guild rank does not have permission to use this!" +general_goliath.255="You have to purchase %%upgrade%% in the /guild shop!" +general_goliath.256="You're already in a guild!" +general_goliath.257="An error occurred while executing that command! Please report this to a staff member!" +general_goliath.258="You do not have permission to join that server!" +general_goliath.259="Can't find a player by the name of '%%name%%'" +general_goliath.260="That player isn't online!" +general_goliath.261="%%player%% isn't online!" +general_goliath.262="That player has added you their ignored players list" +general_goliath.263="Invalid usage! '/%%command%%'" +general_goliath.264="Send a chat message to your guild chat channel" +general_goliath.265="Incorrect usage, try one of the following:\n/guild log\n/guild log (page number)\n/guild log (player name)\n/guild log (player name) (page number)" +general_goliath.266="There are no logs to display." +general_goliath.267="Guild Log (Page %%page%%/%%max%%)" +general_goliath.268="Guild Log for %%user%% (Page %%page%%/%%max%%)" +general_goliath.269="set rank of %%player%% to %%rank%%" +general_goliath.270="created the guild" +general_goliath.271="disbanded the guild" +general_goliath.272="invited %%player%%" +general_goliath.273="joined" +general_goliath.274="kicked %%player%% : "%%details%%"" +general_goliath.275="left" +general_goliath.276="set %%target%% to "%%details%%"" +general_goliath.277="transferred ownership to %%player%%" +general_goliath.278="muted the guild chat for %%details%%" +general_goliath.279="unmuted the guild chat" +general_goliath.280="muted %%player%% for %%details%%" +general_goliath.281="unmuted %%name%%" +general_goliath.282="turned the chat throttle %%details%%" +general_goliath.283="created rank %%details%%" +general_goliath.284="deleted rank %%details%%" +general_goliath.285="View the audit log" +general_goliath.286="The guild is full!" +general_goliath.287="You haven't been invited to a guild by %%player%%, or the invitation has expired!" +general_goliath.288="That guild is full!" +general_goliath.289="You joined %%name%%!" +general_goliath.290="%%player%% joined the guild!" +general_goliath.291="Accepts a guild invitation" +general_goliath.292="View your rank's permissions" +general_goliath.293="You don't seem to be in this guild!" +general_goliath.294="Your rank does not have any permissions!" +general_goliath.295="Lists the players with most experience earned" +general_goliath.296="Not a valid number!" +general_goliath.297="Must be a positive number!" +general_goliath.298="There was an issue on our side, please try again later!" +general_goliath.299="No one earned guild experience on the %%date%%." +general_goliath.300="Top Guild Experience" +general_goliath.301="%%days%% days ago" +general_goliath.302="today" +general_goliath.303="Please wait before doing that again!" +general_goliath.304="renamed rank %%target%% to %%details%%" +general_goliath.305="kicked %%player%%: "%%details%%"" +general_goliath.306="kicked %%player%% ." +general_goliath.307="I couldn't find a rank by the name of '%%name%%'!" +general_goliath.308="%%player%%' rank was changed from %%oldRank%% to %%rank%%" +general_goliath.309="%%player%%'s rank was changed from %%oldRank%% to %%rank%%" +general_goliath.310="They already have that rank!" +general_goliath.311="You cannot promote someone to guild master, use '/guild transfer' instead!" +general_goliath.312="%%player%% reset the guild tag! You may have to change lobbies for it to update." +general_goliath.313="Report a player" +general_goliath.314="Looks like something went wrong, try again in a second!" +general_goliath.315="You can report cheaters using\n/watchdogreport (username) (type of cheats)" +general_goliath.316="You can report chat abuse using\n/chatreport (username)" +general_goliath.317="Displays information about the Guild Member" +general_goliath.318="Sets a player's rank" +general_goliath.319="Sets the guild tag color" +general_goliath.320="%%prefix%%A player has been removed from your lobby for hacking or abuse." +general_goliath.321="%%name%% hasn't sent you any direct messages in the past 10 minutes!" +general_goliath.322="%%name%% hasn't sent any guild messages in the past 10 minutes!" +general_goliath.323="%%name%% hasn't sent any messages in the past 10 minutes!" +general_goliath.324="You can submit a report in the next step, but we recommend you leave this person's guild to prevent you seeing this chat any more.\n" +general_goliath.325="Do you wish to leave this guild?\n\n" +general_goliath.326="You can submit a report in the next step, but we have an option where you can ignore a player and stop you seeing their messages in chat.\n" +general_goliath.327="Do you wish to ignore them?\n\n" +general_goliath.328="You can submit a report in the next step, but we recommend you leave this person's guild to prevent you seeing this chat any more.\n" +general_goliath.329="Do you wish to remove them?\n\n" +general_goliath.330="If you feel the messages are affecting you negatively, please submit a report by clicking the button below\n\n" +general_goliath.331=" YES " +general_goliath.332=" NO " +general_goliath.333="Cancel Report" +general_goliath.334="Submit Report" +general_goliath.335="Direct Message Report" +general_goliath.336="Guild Chat Report" +general_goliath.337="Party Chat Report" +general_goliath.338="Bad name" +general_goliath.339="Build Battle" +general_goliath.340="Cheating" +general_goliath.341="Direct Messages" +general_goliath.342="Guild Chat" +general_goliath.343="Guild Name/Tag" +general_goliath.344="Housing" +general_goliath.345="Party Chat" +general_goliath.346="Bad Pet Name" +general_goliath.347="Pixel Painters" +general_goliath.348="Bad Skin/Cape" +general_goliath.349="Thanks for your %%type%% report. We understand your concerns and it will be reviewed as soon as possible." +general_goliath.350="Report %%name%%?" +general_goliath.351="Select one reason:" +general_goliath.352="Click to report %%name%% for %%report%%" +general_goliath.353="Public Chat Report" +general_goliath.354="You've closed your report!" +general_goliath.355="Invalid username. Did you type their name right?" +general_goliath.356="There is no player named '%%name%%'. Did you spell their name right?" +general_goliath.357="You've already reported %%name%% recently!" +general_goliath.358="An error occurred trying to open a report, please try again in a moment." +general_goliath.359="You do not have any pending reports to confirm!" +general_goliath.360="Please specify a player you would like to report (/%%command%% %%usage%%)" +general_goliath.361="Sorry, I don't understand this report type." +general_goliath.362="That player is currently offline." +general_goliath.363="You've opened too many %%name%% reports! You may only have %%reports%% open %%name%% reports." +general_goliath.364="Thanks for the concern, there are already pending reports for this player. " +general_goliath.365="Sorry, this report type doesn't work with book reports. Please use the in-game command and speak to a developer." +general_goliath.366="Something went wrong, please try resubmitting your report." +general_goliath.367="Please type %%command%% to log your report for staff review." +general_goliath.368="Guild > %%player%% left." +general_goliath.369="Guild > %%player%% joined." +general_goliath.370="You're already in a party, leave it to accept this invite!" +general_goliath.371="Failed to join party." +general_goliath.372="Usage: /party accept <inviter>" +general_goliath.373="You are already in a party! Leave it to join another one." +general_goliath.374="That party has been disbanded." +general_goliath.375="This party is full!" +general_goliath.376="You are already in this party." +general_goliath.377="You are not allowed to join that party!" +general_goliath.378="Something went wrong while fetching the party data!" +general_goliath.379="You don't have an invite to that player's party." +general_goliath.380="That invite is no longer valid." +general_goliath.381="Failed to fetch player by that name, try again later." +general_goliath.382="Accept a party invite from a player" +general_goliath.383="This can only be ran in testnet/betanet!" +general_goliath.384="Invited %%players%% to your party!" +general_goliath.385="There doesn't seem to be anyone online!" +general_goliath.386="You are not allowed to invite players." +general_goliath.387="Invites all online players into your party" +general_goliath.388="You need to be in a party to use this command!" +general_goliath.389="You are not this party's leader!" +general_goliath.390="Can't find a party with that player in it!" +general_goliath.391="You can't challenge your own party!" +general_goliath.392="You've already challenged that party! Wait for them to reply!" +general_goliath.393="Failed to fetch other party data!" +general_goliath.394="Failed to fetch party data!" +general_goliath.395="Challenge another Party to a CvC duel" +general_goliath.396="All players must be online to play a Cops and Crims battle." +general_goliath.397="didn't have all players online" +general_goliath.398="All players must be in a Cops and Crims lobby to play!" +general_goliath.399="didn't have all players in a Cops and Crims lobby" +general_goliath.400="You must have exactly 8 members including yourself in the party!" +general_goliath.401="didn't have 8 players in their party" +general_goliath.402="Usage: /party chat <message>" +general_goliath.403="You are not in a party right now." +general_goliath.404="Failed to send message, please try again." +general_goliath.405="Send a chat message to the entire party" +general_goliath.406="That player does not exist." +general_goliath.407="Usage: /party demote <user>" +general_goliath.408="You are not currently in a party!" +general_goliath.409="That player is not in your party!" +general_goliath.410="You can't demote yourself!" +general_goliath.411="You can't demote a non-moderator!" +general_goliath.412="%%name1%% has demoted %%name2%% to Party Member" +general_goliath.413="Failed to update party!" +general_goliath.414="Failed to fetch player data!" +general_goliath.415="Failed to get party data!" +general_goliath.416="Demotes another party member from Moderator to Member" +general_goliath.417="You are not allowed to disband this party." +general_goliath.418="Failed to fetch party, please try again." +general_goliath.419="Disbands the party" +general_goliath.420="Give me a name to hijack bro." +general_goliath.421="That player does not have a party." +general_goliath.422="You are already in a party, leave it to hijack another one." +general_goliath.423="Database failed to acknowledge hijack, seems like the odds are not in your favor." +general_goliath.424="Database failed to acknowledge hijack, seems like the odds are not in your favor. (1)" +general_goliath.425="Unsuccessful hijack attempt! Abort mission." +general_goliath.426="Database failed to acknowledge hijack, seems like the odds are not in your favor. (2)" +general_goliath.427="%%player%% has hijacked the party!\nBow down to your new leader" +general_goliath.428="Failed to fetch party." +general_goliath.429="Failed to hijack party :(" +general_goliath.430="Take over another player's party" +general_goliath.431="You can only invite up to 10 people at once!" +general_goliath.432="Failed to fetch your party, please try again later" +general_goliath.433="You cannot invite this player to your party!" +general_goliath.434="Couldn't find a player with that name!" +general_goliath.435="You cannot party yourself!" +general_goliath.436="You cannot invite that player since they're not online." +general_goliath.437="%%player%% is already in the party." +general_goliath.438="%%player%% has already been invited to the party." +general_goliath.439="You cannot invite that player since they have ignored you." +general_goliath.440="Failed to invite player." +general_goliath.441="There was a problem inviting this player." +general_goliath.442="You cannot invite that player." +general_goliath.443="Invite another player to your party" +general_goliath.444="Usage: /party kick <member>" +general_goliath.445="You are not in a party right now!" +general_goliath.446="You are not this party's leader." +general_goliath.447="You cannot kick yourself out of the party!" +general_goliath.448="%%player%% has been removed from the party." +general_goliath.449="You have been kicked from the party by %%other%% " +general_goliath.450="Failed to kick player from party, please try again." +general_goliath.451="Failed to fetch your party, please report this." +general_goliath.452="Remove a player from your party" +general_goliath.453="There are no offline players to remove." +general_goliath.454="Failed to remove offline players" +general_goliath.455="You do not have access to this command." +general_goliath.456="Failed to fetch party data." +general_goliath.457="Remove all players that are offline in your party" +general_goliath.458="%%player%% has left the party." +general_goliath.459="You left the party." +general_goliath.460="Failed to leave the party, please try again." +general_goliath.461="You are not in a party." +general_goliath.462="Failed to fetch your party" +general_goliath.463="Leaves your current party" +general_goliath.464="You are not currently in a party." +general_goliath.465="Lists the players in your current party" +general_goliath.466="Failed to mute party, please try again." +general_goliath.467="The party is now muted.\nOnly Party Mods, Staff and the Leader will be able to chat." +general_goliath.468="The party is no longer muted." +general_goliath.469="You are not allowed to use this command!" +general_goliath.470="Mutes party chat so only Staff, Party Mods and the Leader can use it" +general_goliath.471="Failed to update your member data!" +general_goliath.472="You shouldn't be here!" +general_goliath.473="This poll has ended." +general_goliath.474="You've already answered this poll!" +general_goliath.475="I don't understand this answer!" +general_goliath.476="Unknown answer!" +general_goliath.477="Vote registered! The results will be shown shortly." +general_goliath.478="Answer a poll" +general_goliath.479="You don't have access to this command, you need to be %%mvp%% or %%yt%%" +general_goliath.480="There is already an ongoing poll!" +general_goliath.481="Each answer can only be 20 characters long." +general_goliath.482="One or more answer lengths are too short! They must be at least 1 character long!" +general_goliath.483="Party Poll command is only usable by the Party Leader. Polls last for 30 seconds. Results will be shown when the poll ends. You can have a maximum of four possible answers in your poll!\nInvalid usage! /party poll <question/answer/answer/answer[/answer]>" +general_goliath.484=" - %%number%%. %%answer%%" +general_goliath.485="%%name%% created a poll! Answer it below by clicking on an option" +general_goliath.486="Question: %%question%%" +general_goliath.487="The poll will end in %%seconds%% seconds!" +general_goliath.488="The poll ended early so here are the results!" +general_goliath.489="%%answer%% - %%votes%% Votes (%%percentage%%%) [%%visualised%%]" +general_goliath.490="Creates a poll for party members to vote on" +general_goliath.491="You do not have permission to use this command! You need %%yt%% rank or %%superstar%%." +general_goliath.492="Enables private games for your party" +general_goliath.493="Usage: /party promote <user>" +general_goliath.494="You can't promote yourself!" +general_goliath.495="%%name1%% has promoted %%name2%% to Party Leader\n%%name1%% is now a Party Moderator" +general_goliath.496="%%name1%% has promoted %%name2%% to Party Moderator" +general_goliath.497="Promotes another party member to either Party Mod or Party Leader" +general_goliath.498="Failed to update Party Settings!" +general_goliath.499="%%player%% disabled %%option%%" +general_goliath.500="Failed to fetch party data, please try again." +general_goliath.501="Party Settings\n/p setting allinvite - Toggles all invite\n/p private - Toggles private games\n/p mute - Mutes the party chat" +general_goliath.502="Toggles party settings" +general_goliath.503="Allow all players to invite players to the party" +general_goliath.504="Play private games with your party" +general_goliath.505="You are already in a party! Leave to to silentjoins." +general_goliath.506="That player is not currently in a party." +general_goliath.507="Failed to fetch data." +general_goliath.508="Failed to leave party" +general_goliath.509="All online guild members are already in your party!" +general_goliath.510="The party was transferred to %%other%% by %%who%%" +general_goliath.511="Failed to transfer party." +general_goliath.512="Failed to fetch user data." +general_goliath.513="Transfers the party to another player" +general_goliath.514="Something went wrong while fetching player data!" +general_goliath.515="You cannot warp a party larger than 10 players!" +general_goliath.516="Warps the members of a party to your current server" +general_goliath.517="Failed to create a party for you" +general_goliath.518="Failed to fetch your party data." +general_goliath.519="Failed to fetch other player's info" +general_goliath.520="You were yoinked into the party by %%sender%%" +general_goliath.521="%%player%% was yoinked into the party by %%who%%" +general_goliath.522="That command is currently disabled, please try again later!" +general_goliath.523="You don't have access to this command!" +general_goliath.524="Something went wrong while processing your command, please try again later." +general_goliath.525="You do not have permission to use this command! You need YouTube rank or %%superstar%%." +general_goliath.526="You must be the party leader to use this command." +general_goliath.527="Maximum player count needs to be at least 2." +general_goliath.528="Created a public party! Players can join with /party join %%name%%\nParty is capped at %%count%% players.\n" +general_goliath.529="Failed to create party, please try again later" +general_goliath.530="Failed to open party to the public, please try again." +general_goliath.531="The party is now open to the public! Players can join with /party join %%name%%\n\nParty is capped at %%count%% players." +general_goliath.532="Failed to change maximum capacity, please try again." +general_goliath.533="Changed the maximum party size!\n\nParty is capped at %%count%% players." +general_goliath.534="You must be in a party to use this command!" +general_goliath.535="The party is already private!" +general_goliath.536="The party is no longer public" +general_goliath.537="The party has been emptied!" +general_goliath.538="The party invite from %%player%% has expired." +general_goliath.539="The party invite to %%player%% has expired" +general_goliath.540="The party was disbanded because the party leader disconnected." +general_goliath.541="%%name%% has disbanded the party!" +general_goliath.542="Party failed to disband, please report this." +general_goliath.543="%%player%% has already been invited to the party! Wait for them to accept!" +general_goliath.544="%%player%% invited %%them%% to the party! They have 60 seconds to accept." +general_goliath.545="%%player%% has invited you to join their party!\n" +general_goliath.546="%%player%% has invited you to join %%leader%%'s party!\n" +general_goliath.547="You have 60 seconds to accept. Click here to join!" +general_goliath.548="Click to run\n/party accept %%player%%" +general_goliath.549="The party was transferred to %%other%% because %%leader%% left" +general_goliath.550="%%player%% was removed from the party because they disconnected" +general_goliath.551="The party leader, %%player%% has disconnected, they have 5 minutes to rejoin before the party is disbanded." +general_goliath.552="%%player%% has disconnected, they have 5 minutes to rejoin before they are removed from the party." +general_goliath.553="Failed to move you to the ALL channel, please report this." +general_goliath.554="You are not in a party and were moved to the ALL channel." +general_goliath.555="This party is currently muted." +general_goliath.556="Failed to fetch data, please report this." +general_goliath.557="Woah, this Party has a chat throttle. Try again in %%seconds%%s" +general_goliath.558="Party >" +general_goliath.559="%%player%% has invited all members of %%guild%% to their party!\n" +general_goliath.560="Maximum player count cannot exceed 100." +general_goliath.561="================== WARNING ==================\nThis will DESTROY THE GUILD and remove all of it's members\nAll of the Guild Experience will be DESTROYED. This cannot be undone.\nIf you wish to continue, /guild confirm within 10 seconds." +general_goliath.562="You'll be partying with: " +general_goliath.563=" and %%count%% other player!" +general_goliath.564=" and %%count%% other players!" +general_goliath.565="You're not eligible for this milestone reward!" +general_goliath.566="You've already claimed this milestone reward!" +general_goliath.567="Successfully claimed the following:" +general_goliath.568="Gift Giver Achievement" +general_goliath.569="Legendary Gift Giver Hat" +general_goliath.570="Legendary Gift Giver Suit" +general_goliath.571="Legendary Gifterino Companion" +general_goliath.572="Something went wrong while handling that! Please try again in a moment." +general_goliath.573="You were tipped by 1 player in the last minute!" +general_goliath.574="You were tipped by %%amount%% players in the last minute!" +general_goliath.575="Rewards" +general_goliath.576="That's not a valid username!" +general_goliath.577="Something went wrong, please try again in a moment!" +general_goliath.578="No one has a network booster active right now! Try again later." +general_goliath.579="We're still processing your most recent /tip!" +general_goliath.580="Can't find a player by the name of '%%player%%'" +general_goliath.581="You cannot give yourself tips!" +general_goliath.582="You tipped 1 player in 1 game!" +general_goliath.583="You tipped 1 player in %%games%% different games!" +general_goliath.584="You tipped %%amount%% players in 1 game!" +general_goliath.585="You tipped %%amount%% players in %%games%% different games!" +general_goliath.586="You tipped 1 player!" +general_goliath.587="You tipped %%amount%% players!" +general_goliath.588="You already tipped everyone that has boosters active, so there isn't anybody to be tipped right now!" +general_goliath.589="You (anonymously) tipped %%player%% in %%gameType%%!" +general_goliath.590="You tipped %%player%% in %%gameType%%!" +general_goliath.591="You've already tipped that person today in %%gameType%%! Try another user!" +general_goliath.592="That player is not online, try another user!" +general_goliath.593="There is currently no booster active in %%gameType%%!" +general_goliath.594="You've already tipped someone in the past hour in %%gameType%%! Wait a bit and try again!" +general_goliath.595="You must have exactly %%count%% people in the party to play this!" +general_goliath.596="Something went wrong and I couldn't find that map! Please report this to a staff!" +general_goliath.597="There are no servers running that map right now! Try again later!" +general_goliath.598="Only the party leader can warp you into a game! Have them click an NPC or use /party leave" +general_goliath.599="You can't start a private game with only yourself in the party!" +general_goliath.600="Your party is too large to play %%gameType%%: %%map%%! Max of %%count%% players per party!" +general_goliath.601="You must have at least %%count%% people in the party to play this!" +general_goliath.602="Your party is too large to play this map! Try a different map!" +general_goliath.603="Your party can't queue for %%gameType%%: %%map%% because %%player%% isn't online!" +general_goliath.604="Your party can't queue for %%gameType%%: %%map%% because %%player%% doesn't have permission to join that server!" +general_goliath.605="Sorry, we couldn't find any servers with enough room for %%game%%: %%map%%! Try again in a few minutes!" +general_goliath.606="Sending you to %%server%%!" +general_goliath.607="Couldn't find a server available! Try again in a moment!" +general_goliath.608="No such game '%%gameType%%'." +general_goliath.609=" is in the house %%name%%" +general_goliath.610="%%name%% hasn't sent any messages recently!" +general_goliath.611="%%name%% hasn't sent you any direct messages recently!" +general_goliath.612="%%name%% hasn't sent any guild messages recently!" +general_goliath.613="%%name%% hasn't sent any party messages recently!" +general_goliath.614="================== WARNING ==================\nThis will DESTROY THE GUILD and remove all of its members\nAll of the Guild Experience will be DESTROYED. This cannot be undone.\nIf you wish to continue, /guild confirm within 10 seconds." +general_goliath.615="You cannot mute a guild member with a higher guild rank!" +general_goliath.616="You have joined %%player%%' party!" +general_goliath.617="You have joined %%player%%'s party!" +general_goliath.618="Reward Summary" +general_goliath.619="[WARNING] A chat report was submitted to us regarding your account and has been verified by our team.\nAlthough we're not taking any action at this time, please keep in mind that our chat rules still apply to YOUTUBE ranked players.\nRules: https://hypixel.net/rules\nCreators Contact: creators@hypixel.net\n" +general_goliath.620="You must be VIP+ to create a guild!\nHowever, you can still join other people's guilds!" +general_goliath.621="You don't have access to this command, you need to be %%mvp%% or %%yt%%" +general_goliath.622="They are already in a guild!" +general_goliath.623="gave %%details%% permission to rank %%target%%" +general_goliath.624="took %%details%% permission from rank %%target%%" +general_goliath.625="requested to join" +general_goliath.626="set %%rank%% as the default rank" +general_goliath.627="Your Hypixel API key has been reset!\n\nReason: %%reason%%" +general_goliath.628="Your leaderboard stats have been wiped, including Ranked SkyWars and Tournaments, due to abusive behavior.\nIf you believe this was an error, please contact\n%%underline%%support.hypixel.net" +general_goliath.629="Your SkyBlock Profile %%profileName%% has been wiped as a co-op member was determined to be boosting.\nIf you believe this to be in error, you can contact our support team: %%underline%%support.hypixel.net" +general_goliath.630="Your SkyBlock Profile %%profileName%% has been wiped as a co-op member was determined to be boosting.\n\nIf you believe this to be in error, you can contact our support team: %%underline%%support.hypixel.net" +general_goliath.631="Guild: Message Of The Day (Preview)" +general_goliath.632="Guild: Message Of The Day" +general_goliath.633="The name of your %%pet%% companion was reset as it violates the Hypixel Server Rules.\n\nName:\n%%name%%\n\n%%underline%%hypixel.net/rules\n" +general_goliath.634="You earned" +general_goliath.635="%%experience%% Hypixel Experience" +general_goliath.636="+%%earned%% %%reason%%" +general_goliath.637="Play Time Bonus" +general_goliath.638="%%earned%% %%gameType%% Coin" +general_goliath.639="%%earned%% %%gameType%% Coins" +general_goliath.640="+%%coins%% Game Reward" +general_goliath.641="+%%earned%% %%reason%%" +general_goliath.642="%%earned%% Guild Experience" +general_goliath.643="+%%earned%% %%reason%%" +general_goliath.644="Guild Experience was reduced to %%percent%%%,\nbecause your Guild has reached the daily cap." +general_goliath.645="Your game had %%amount%% %%rank%%s (or higher)" +general_goliath.646="%%player%% joined the party." +general_goliath.647="Party Members (%%count%%)" +general_goliath.648="Party Leader: %%player%%" +general_goliath.649="Party Moderators: %%players%%" +general_goliath.650="Party Members: %%players%%" +general_goliath.651="Party > " +general_goliath.652="Migration Status" +general_goliath.653="You are confirmed as a Microsoft Account!" +general_goliath.654="Your account has not been confirmed as migrated." +general_goliath.655="Current %%type%% Level" +general_goliath.656="Punishment Information" +general_goliath.657="Date: %%date%%" +general_goliath.658="Reason: %%reason%%" +general_goliath.659="Status: %%status%%" +general_goliath.660="Expires: %%date%%" +general_goliath.661="Expired: %%date%%" +general_goliath.662="Click to view appeal!" +general_goliath.663="None" +general_goliath.664="Active (Permanent)" +general_goliath.665="Active" +general_goliath.666="Competitive Ban Status" +general_goliath.667="Competitive game bans are used to keep the integrity of the competitive scene fair and remove repeat rule breakers." +general_goliath.668="Click for more information!" +general_goliath.669="You have received multiple %%type%%s recently. Your future %%type%%s will be much longer than normal." +general_goliath.670="You have received one or more %%type%%s recently. Your future %%type%%s will be longer than normal." +general_goliath.671="You are in good standing and have received little to no %%type%%s recently." +general_goliath.672="Mute" +general_goliath.673="Ban" +general_goliath.674="mute" +general_goliath.675="ban" +general_goliath.676="Hypixel Atlas" +general_goliath.677="Click on the icon for the game you want to review replays for." +general_goliath.678="EARN MORE EXPERIENCE" +general_goliath.679="Request an Atlas report for %%game%%." +general_goliath.680="Requirements" +general_goliath.681="%%amount%% %%game%% %%stat%%" +general_goliath.682="Hypixel Level %%level%%" +general_goliath.683="You do not meet the requirements!" +general_goliath.684="Click to request a report!" +general_goliath.685="Not enough verdicts!" +general_goliath.686="N/A" +general_goliath.687="Atlas Stats" +general_goliath.688="Verdicts Submitted: %%amount%%" +general_goliath.689="Accuracy: %%color%%%%amount%%" +general_goliath.690="These stats may be cached for up to %%minutes%% minutes!" +general_goliath.691="There are currently no reports available! gg :)" +general_goliath.692="Audit Log" +general_goliath.693="Change Guild Discord" +general_goliath.694="Guild Settings" +general_goliath.695="View Stats" +general_goliath.696="Officer" +general_goliath.697="Member" +general_goliath.698="Invalid usage! To use -a, use "/tip -a <player> <game>"" +general_goliath.699="It was an example! Put an online player's name there!" +general_goliath.700="Tipping is currently disabled at this time and boosters have been paused, they will be back soon!" +general_goliath.701="You have been blocked from using /tip for 5 minutes! Please don't spam the command!" +general_goliath.702="Slow down! You can only use /tip every few seconds." +general_goliath.703="Enabled /tip messages!" +general_goliath.704="Disabled /tip messages!" +general_goliath.705="Use this command to tip coins to another player." +general_goliath.706="Example usage: /tip Steve Skywars or /tip -a Steve Skywars to send it anonymously." +general_goliath.707="You can also use /tip all to tip all active boosters!" +general_goliath.708="%%player%% was removed from your party because they disconnected." +general_goliath.709="The party was disbanded because all invites expired and the party was empty." +general_goliath.710="You've already invited %%player%% to your guild! Wait for them to accept!" +general_goliath.711="Breaking chat related rules or scamming" +general_goliath.712="Having an inappropriate username" +general_goliath.713="Using illegitimate methods to boost game stats" +general_goliath.714="Using disallowed modifications to gain an unfair advantage" +general_goliath.715="Working with the other team to gain an advantage" +general_goliath.716="Inappropriate guild information" +general_goliath.717="Having an inappropriate in-game item" +general_goliath.718="Having an inappropriate pet name" +general_goliath.719="Having an inappropriate skin or cape" +general_goliath.720="Creating an inappropriate sign or hologram" +general_goliath.721="There is no player with that name. Did you spell their name right?" +general_goliath.722="Use this command to challenge another party to\nan 8v8 Cops vs Crims battle! To use it, type:\n/party challenge <Player>" +general_goliath.723="You are not in a party with exactly 8 players." +general_goliath.724="Can't find a player with that name!" +general_goliath.725="That player is not in a party with exactly 8 players." +general_goliath.726="The CvC challenge to %%other%%'s party has expired!" +general_goliath.727="The CvC challenge from %%other%%'s party has expired!" +general_goliath.728="Your party has challenged %%other%%'s party to a CvC match!\n\nThey have 5 minutes to respond before the challenge expires." +general_goliath.729="Your party has been challenged by %%other%%'s party to a CvC match!\n\nYour party leader has 5 minutes to do /party challenge %%name%% before the challenge expires." +general_goliath.730="%%player%%'s party tried to accept the challenge, but %%reason%%" +general_goliath.731="Can't start the challenge, because the other party %%reason%%. Try again in a few seconds." +general_goliath.732="Please look at the object you want to report and use /worldreport to report it" +general_goliath.733="You're about to report this %%type%%" +general_goliath.734="Please click on the text you want to report:" +general_goliath.735="Click to link your Discord account" +general_goliath.736="Wow, you scared me there!" +general_goliath.737="You are not allowed to leave this area!" +general_goliath.738="The question is ... what do YOU do!?" +general_goliath.739="Nothing." +general_goliath.740="%%player_name%% isn't on your friends list!" +general_goliath.741="%%rank%% Rank Permissions" +general_goliath.742="Click to view page %%page%%" +general_goliath.743="Tag Color" +general_goliath.744="Discord" +general_goliath.745="%%name%% Selector" +general_goliath.746="%%name%% Lobby Selector" +general_goliath.747="Enabled best friend join/leave notifications!" +general_goliath.748="Must be a smaller number!" +general_goliath.749="%%color%%%%experience%% Event Experience" +general_goliath.750="Use this command to tip coins to another player." +general_goliath.751="Example usage: %%commandA%% or %%commandB%% to send it anonymously." +general_goliath.752="Did you know that you can use %%command%% to tip all active boosters?" +general_goliath.753="Click here to tip all active boosters" +general_goliath.754="Click to run /tip all" +general_goliath.755="Report" +general_goliath.756="Report %%name%%" +general_goliath.757="Who would you like to report?" +general_goliath.758="%%yes%%" +general_goliath.759="Submit Report" +general_goliath.760="YES" +general_goliath.761="%%no%%" +general_goliath.762="Cancel Report" +general_goliath.763="I couldn't find anyone for you to report" +general_goliath.764="NO" +general_goliath.765="Please use /report <player>" +general_goliath.766="Click to report this player." +general_goliath.767="Please hold the item you want to report in your hand and use /itemreport to report it" +general_goliath.768="Do you wish to ignore them?\n" +general_goliath.769="Do you wish to leave this guild?\n" +general_goliath.770="Do you wish to remove them?\n" +general_goliath.771="Report %%item_name%%" +general_goliath.772="Report %%type%%" +general_goliath.773="Report House" +general_goliath.774="Report Island" +general_goliath.775="%%game%% Lobby" +general_goliath.776="%%game%%" +general_goliath.777="%%when%% on %%server%%" +general_goliath.778="I couldn't find the player you want to report!" +general_goliath.779="You cannot report yourself" +general_goliath.780="Unknown report type" +general_goliath.781="You cannot report that" +general_goliath.782="I don't know how to handle this report type" +general_goliath.783="Please wait before reporting this player again!" +general_goliath.784="You can't join this group because the leader has blocked you!" +general_goliath.785="That player has added you to their blocked players list!" +general_goliath.786="That player has added you to their blocked players list" +general_goliath.787="You cannot invite that player since they have blocked you." +general_goliath.788="Submitting Report..." +general_goliath.789="Please wait..." \ No newline at end of file diff --git a/configuration/i18n/en_US/official/main_lobby.properties b/configuration/i18n/en_US/official/main_lobby.properties new file mode 100644 index 000000000..0da1d30cc --- /dev/null +++ b/configuration/i18n/en_US/official/main_lobby.properties @@ -0,0 +1,1063 @@ +main_lobby.0="Total points: %%points%%" +main_lobby.1="Targets hit: %%killed%%" +main_lobby.2="Time spent: %%time%%" +main_lobby.3="Archery Bow 2000™" +main_lobby.4="Rank: %%rank%%" +main_lobby.5="Achievements: %%achievements%%" +main_lobby.6="Hypixel Level: %%level%%" +main_lobby.7="Lobby: %%lobby%%" +main_lobby.8="Players: %%players%%" +main_lobby.9="I'm already sending you to %%name%%!" +main_lobby.10="Sorry, I'm having trouble sending you to %%name%% - give me a moment!" +main_lobby.11="You must be using 1.8 to use Player Housing!" +main_lobby.12="Jump into the portal," +main_lobby.13="or right-click your compass to start playing." +main_lobby.14="You can also" +main_lobby.15="right-click one of the NPCs near the portal." +main_lobby.16="Make sure to explore!" +main_lobby.17="There's tons of secrets!" +main_lobby.18="Check out your inventory." +main_lobby.19="There's achievements, gadgets and more!" +main_lobby.20="www.hypixel.net - News, discussion and more!" +main_lobby.21="Right click a NPC to play!" +main_lobby.22="[NPC] The Carpenter: Housing isn't available at this moment! Come back later." +main_lobby.23="Player Housing" +main_lobby.24="Duels" +main_lobby.25="Smash Heroes" +main_lobby.26="Warlords" +main_lobby.27="Mega Walls" +main_lobby.28="TNT Games" +main_lobby.29="Prototype" +main_lobby.30="Build Battle" +main_lobby.31="Murder Mystery" +main_lobby.32="Arcade" +main_lobby.33="UHC Champions" +main_lobby.34="Blitz SG" +main_lobby.35="Mini Walls" +main_lobby.36="Cops and Crims" +main_lobby.37="Speed UHC" +main_lobby.38="Classic Games" +main_lobby.39="Bed Wars" +main_lobby.40="SkyWars" +main_lobby.41="The Pit" +main_lobby.42="Mystery Dust: %%dust%%" +main_lobby.43="Pixel Painters" +main_lobby.44="You have received the super reward!" +main_lobby.45="You already earned the reward this year!" +main_lobby.46="This game is temporarily disabled!" +main_lobby.47="Weekly Best Scores" +main_lobby.48="Pumpkin Smash" +main_lobby.49="Your best: %%best%%" +main_lobby.50="Refreshes every 5 minutes" +main_lobby.51="N/A" +main_lobby.52="TURBO BAT RACERS" +main_lobby.53="Pick a Course (Click)" +main_lobby.54="Best Times" +main_lobby.55="Your best: %%best%%" +main_lobby.56="EZ" +main_lobby.57="MED" +main_lobby.58="HARD" +main_lobby.59="You just finished the %%course%% in %%duration%%!" +main_lobby.60="Race finished in %%duration%%!" +main_lobby.61="Try it again to beat your time or try another course!" +main_lobby.62="Good job! You've beaten your previous time of %%time%%!" +main_lobby.63="Unfortunately, you haven't your best time of %%time%% yet!" +main_lobby.64="Failed the race at %%checkpoint%%/%%total%%" +main_lobby.65="FAILED!" +main_lobby.66="NEXT RACE" +main_lobby.67="In %%remaining%%s" +main_lobby.68="GO!" +main_lobby.69="Get ready!" +main_lobby.70="Race starting in %%seconds%% seconds!" +main_lobby.71="Picked %%name%% course and leaderboards!" +main_lobby.72="You exploded from an evil bomb!" +main_lobby.73="Pumpkin Whacker 3000" +main_lobby.74="Used to smash pumpkins. Also gives a mean head massage." +main_lobby.75="Give up" +main_lobby.76="Smash the pumpkins into the targets!" +main_lobby.77="Time Left: %%timeleft%%" +main_lobby.78="Score: %%score%%" +main_lobby.79="Target: %%percentCleared%%%" +main_lobby.80="Woo! You survived with a score of %%score%%!" +main_lobby.81="Try again to beat your score!" +main_lobby.82="Ayy! You've smashed your previous score of %%score%%!" +main_lobby.83="Unfortunately, you haven't beaten your best score of %%score%% yet!" +main_lobby.84="You died after %%elapsed%% seconds with a score of %%score%%!" +main_lobby.85="Recorded on achievement completion" +main_lobby.86="ACHIEVEMENTS" +main_lobby.87=" on Hypixel" +main_lobby.88="1. Complete tasks:" +main_lobby.89=" %%underline%%VIEW TASKS" +main_lobby.90="Click to open the Achievements menu!" +main_lobby.91="2. Get points:" +main_lobby.92=" POINTS: %%points%%" +main_lobby.93="That's your Achievement Points!" +main_lobby.94="3. Earn Rewards:" +main_lobby.95=" %%underline%%VIEW REWARDS" +main_lobby.96="Click to open the \nAchievement Rewards menu!" +main_lobby.97="Achievements Guide" +main_lobby.98="Recorded on level gain" +main_lobby.99="Top Hypixel Players" +main_lobby.100="Achievement Points" +main_lobby.101="Your Achievement Points: %%points%%" +main_lobby.102="Hypixel Level" +main_lobby.103="Your Level: %%level%%" +main_lobby.104="Main Lobby: " +main_lobby.105="Found Presents: " +main_lobby.106="Peeta" +main_lobby.107="CLICK TO TELEPORT" +main_lobby.108="Turbo Bat Racers" +main_lobby.109="Baskets Found: " +main_lobby.110="You already found this Candy Basket!" +main_lobby.111="You found a Candy Basket!" +main_lobby.112="Congratulations! You found all Candy Baskets!" +main_lobby.113="You have received a reward for your commitment!" +main_lobby.114="Candy Hunt Reward" +main_lobby.115="For the best experience, click the text below to enable Snow Particles in this lobby!" +main_lobby.116="Click to enable Snow Particles" +main_lobby.117="You can disable them at any time with /snow" +main_lobby.118="You can't do that right now." +main_lobby.119="Easter Eggs: " +main_lobby.120="You already found this egg!" +main_lobby.121="You found an easter egg!" +main_lobby.122="Egg Hunt Super Reward" +main_lobby.123="+%%achievement%% Achievement!" +main_lobby.124="Congratulations! You found all the easter eggs!" +main_lobby.125="Easter Guide" +main_lobby.126="EASTER EGG NEARBY!" +main_lobby.127="Fishing Rod 3000" +main_lobby.128="Use this to fish off of the dock near the Fishing Hut!" +main_lobby.129="Salmon" +main_lobby.130="Oh no, we couldn't give you a hot potato because you already had it before!" +main_lobby.131="Fish Collection" +main_lobby.132="Your Fishing Stats" +main_lobby.133=" - Fish Caught: %%amount%%" +main_lobby.134=" - Junk Caught: %%amount%%" +main_lobby.135=" - Treasure Caught: %%amount%%" +main_lobby.136=" - Special Fish Caught: %%amount%%" +main_lobby.137="Use your Fishing Rod 3000 to fish off the dock behind you! If you're patient enough, you may catch some rare oddities from the depths." +main_lobby.138="Fishing Information" +main_lobby.139="Caught!" +main_lobby.140="???" +main_lobby.141="Not Caught!" +main_lobby.142="???" +main_lobby.143="Oops The Fish" +main_lobby.144="Puffer Emoji" +main_lobby.145="Nemo" +main_lobby.146="Knockback Slimeball" +main_lobby.147="Shark" +main_lobby.148="Sea Bass" +main_lobby.149="Hot Potato" +main_lobby.150="Oops, wrong game." +main_lobby.151="Maybe he's lost again?" +main_lobby.152="So this is where it's been all this time?" +main_lobby.153="Seems a bit small." +main_lobby.154="No wait- it's at least a C+!" +main_lobby.155="Would you look at that?" +main_lobby.156="Top %%mode%% Caught" +main_lobby.157="The Fishing Hut is currently inactive!" +main_lobby.158="Check back another time!" +main_lobby.159="Fish Monger Suit Helmet" +main_lobby.160="Fish Monger Suit Chestplate" +main_lobby.161="Fish Monger Suit Leggings" +main_lobby.162="Fish Monger Suit Boots" +main_lobby.163="Spook The Fish" +main_lobby.164="Chocolate Bar" +main_lobby.165="Pumpkin Spice Latte" +main_lobby.166="Wow, so spooky!" +main_lobby.167="Might be a bit soggy." +main_lobby.168="Wouldn't be fall without some pumpkin spice." +main_lobby.169="Total" +main_lobby.170="Equip cosmetics using the Collectibles Menu!" +main_lobby.171="Claim this SkyBlock fish from your Jerry!" +main_lobby.172="%%festival%% Fish" +main_lobby.173="Lobby Cosmetic" +main_lobby.174="Apple Bobbing" +main_lobby.175="Top %%mode%% Score" +main_lobby.176="Someone is already playing! Wait for them to finish!" +main_lobby.177="Apple Bobbing" +main_lobby.178="%%who%% PLAYING" +main_lobby.179="Jump and grab as many apples as you can!" +main_lobby.180="Woo! You got a score of %%score%%!" +main_lobby.181="You ended after %%elapsed%% seconds with a score of %%score%%!" +main_lobby.182="DODGE THIS!" +main_lobby.183="SMASH THIS IN THE TARGET" +main_lobby.184="Earn items and cosmetics!" +main_lobby.185="UNDEAD SHOOTING RANGE" +main_lobby.186="Earn 333 points before 1 min" +main_lobby.187="to earn 10 Achievement Points" +main_lobby.188="Turbo Bat Racers" +main_lobby.189="Up the stairs!" +main_lobby.190="Undead Archery after 1 min." +main_lobby.191="Undead Archery after 3 min." +main_lobby.192="Not instantly refreshed" +main_lobby.193="TOP SCORES %%year%%" +main_lobby.194="Oh look, a dirty helmet." +main_lobby.195="That's a pretty scuzzy shirt." +main_lobby.196="Gross, mossy pants." +main_lobby.197="These boots are falling apart." +main_lobby.198="VANISHED USER PLAYING" +main_lobby.199="Wow, you caught %%color%%%%item%%! %%lore%%" +main_lobby.200="Wow, you caught a %%color%%%%item%%! %%lore%%" +main_lobby.201="%%name%% caught %%color%%%%item%%! %%lore%%" +main_lobby.202="%%name%% caught a %%color%%%%item%%! %%lore%%" +main_lobby.203="Chill The Fish" +main_lobby.204="BrrRrRRr" +main_lobby.205="Frozen Fish" +main_lobby.206="Heat in a microwave for 30 seconds." +main_lobby.207="Festive Pufferfish Hat" +main_lobby.208="Look at its cute little hat!" +main_lobby.209="There are too many boats in this lobby! Try again later." +main_lobby.210="You already got a boat recently!" +main_lobby.211="Aye captain! Here's your boat!" +main_lobby.212="Egg The Fish" +main_lobby.213="Don't crack it, it's fragile!" +main_lobby.214="Cracked Egg" +main_lobby.215="Poor chicken. :(" +main_lobby.216="Raw Ham" +main_lobby.217="Well, that saves a trip to the supermarket." +main_lobby.218="Feed it to a rabbit!" +main_lobby.219="Soggy Hot Cross Bun" +main_lobby.220="Make sure to learn the song on your recorder." +main_lobby.221="Fishing Rod Upgrades" +main_lobby.222="Increases fishing speed" +main_lobby.223="Increases treasure drop chances" +main_lobby.224="Slightly increases special fish drop chances" +main_lobby.225="Upgrade the enchantments on your fishing rod!" +main_lobby.226="Fishing Rod Upgrades" +main_lobby.227="Required Fish" +main_lobby.228="Required Treasure" +main_lobby.229="Required Junk" +main_lobby.230="An enchantment level was too high for your stats and was lowered!" +main_lobby.231="You have already claimed this upgrade!" +main_lobby.232="Upgraded your Fishing Rod with %%enchantName%% %%enchantTier%%!" +main_lobby.233="You haven't reached the requirements yet!" +main_lobby.234="Fishing Rewards" +main_lobby.235="Rewards available during seasonal events!" +main_lobby.236="You have already claimed those rewards!" +main_lobby.237="Claimed %%name%%!" +main_lobby.238="Golden Pufferfish Hat" +main_lobby.239="Portable Pond Gadget" +main_lobby.240="Seasoned Fisher Banner" +main_lobby.241="Barnacle" +main_lobby.242="It really grows on you." +main_lobby.243="Leviathan" +main_lobby.244="That's one huge catch!" +main_lobby.245="Star-Eater Scales" +main_lobby.246="It's destiny." +main_lobby.247="Sunscreen" +main_lobby.248="Safety first!" +main_lobby.249="Just like the beach!" +main_lobby.250="Mahi Mahi" +main_lobby.251="So tasty!" +main_lobby.252="Lure" +main_lobby.253="Luck of the Sea" +main_lobby.254="Collector" +main_lobby.255="Report bugs and leave feedback at hypixel.net/ptl" +main_lobby.256="You can have it for dessert!" +main_lobby.257="Eyeball" +main_lobby.258="How'd this get in here..." +main_lobby.259="Wayfinder's Compass" +main_lobby.260="It's the season of the lost, don't lose your way." +main_lobby.261="Eggnog" +main_lobby.262="Now is when everyone starts arguing." +main_lobby.263="Dawning Snowball" +main_lobby.264="Oh how I miss you..." +main_lobby.265="Fished Punch Message" +main_lobby.266="Festive Fisher Banner" +main_lobby.267="CLICK TO PLAY" +main_lobby.268="Welcome to Hypixel!" +main_lobby.269="What do you want to do?" +main_lobby.270="1. %%underline%%Change language." +main_lobby.271="Click to change your language" +main_lobby.272="2. %%underline%%Start the tutorial." +main_lobby.273="Click to start the tutorial" +main_lobby.274="3. %%underline%%Play some games." +main_lobby.275="Click to teleport to the game NPCs." +main_lobby.276="%%underline%%Close this book." +main_lobby.277="Click to close this book." +main_lobby.278="Your SkyBlock island is part of a much larger universe..." +main_lobby.279="Wait, how did I get here?" +main_lobby.280="Jerry" +main_lobby.281="These mines help supply the castle with resources." +main_lobby.282="The minecart is open for rides, but be careful! There might be some unexpected twists and turns!" +main_lobby.283="Take a trip on the roller coaster" +main_lobby.284="Ride the carousel" +main_lobby.285="You're already in a minecart!" +main_lobby.286="Someone recently used this, please wait a few seconds and try again!" +main_lobby.287="Press CROUCH to exit the Roller Coaster and return to the start!" +main_lobby.288="Paintball" +main_lobby.289="Who doesn't love some fun paintball fights?" +main_lobby.290="Challenge your friends and see who can survive!" +main_lobby.291="Practice paintball with friends!" +main_lobby.292="Paintballs" +main_lobby.293="You entered the correct code!" +main_lobby.294="That code was incorrect!" +main_lobby.295="Treasure Chest" +main_lobby.296="Achievements are challenges you can accomplish across the entire Hypixel server for rewards!" +main_lobby.297="You can view your achievement progress anytime by talking to me again or in your My Profile menu." +main_lobby.298="Welcome to the castle!" +main_lobby.299="Watch your step!" +main_lobby.300="Move along." +main_lobby.301="Wow, guard duty sucks." +main_lobby.302="I need to keep watch." +main_lobby.303="Hmm." +main_lobby.304="My legs are tired." +main_lobby.305="Guard" +main_lobby.306="Archer" +main_lobby.307="Albus" +main_lobby.308="Librarian Albus" +main_lobby.309="Shhh!" +main_lobby.310="Be quiet, some people are reading!" +main_lobby.311="Respect the library's rules!" +main_lobby.312="Can you please keep your footsteps down?" +main_lobby.313="Thank you for respecting the rules." +main_lobby.314="Some people really need to respect the silence." +main_lobby.315="I just want to read in peace." +main_lobby.316="The number is %%number%%, I hope you figure out what it's for." +main_lobby.317="Thank you for listening, you have earned my respect." +main_lobby.318="In my reading I found the number %%number%% associated with you." +main_lobby.319="I'm unsure as to what this may pertain to but I wish you luck!" +main_lobby.320="Eleanor" +main_lobby.321="Librarian Eleanor" +main_lobby.322="Interested in a book?" +main_lobby.323="How can I help?" +main_lobby.324="Illybay" +main_lobby.325="Illybad the Piano Man" +main_lobby.326="Buchard" +main_lobby.327="Buchard the Baker" +main_lobby.328="Nothing like a good cake!" +main_lobby.329="I wonder if I put brownie batter into a donut..." +main_lobby.330="*mutters about flour*" +main_lobby.331="When will this bread be done..." +main_lobby.332="Prison Dog" +main_lobby.333="Bark!" +main_lobby.334="Boof." +main_lobby.335="Awooo!" +main_lobby.336="Daedalus" +main_lobby.337="The king went missing in the Labyrinth not long ago." +main_lobby.338="That mysterious maze always has tunnels opening and closing." +main_lobby.339="I wonder how we could map it..." +main_lobby.340="Quinten" +main_lobby.341="Butchard really makes some good cake..." +main_lobby.342="Lord Siopilos" +main_lobby.343="Welcome! I'm the Master of Bows!" +main_lobby.344="Where has the king gone..." +main_lobby.345="How can I help you?" +main_lobby.346="Lady Alikay" +main_lobby.347="Hello! I'm the Master of Planners!" +main_lobby.348="There's gotta be something in all these old books..." +main_lobby.349="Why does this have to have math." +main_lobby.350="Lord Uberhay" +main_lobby.351="Hey! I'm the Master of Armor." +main_lobby.352="We need to be prepared..." +main_lobby.353="Where can we get more supplies?" +main_lobby.354="Jun 11th, 2019\n\nFor years SkyBlock has been one of the most requested games on the Network, today we are releasing our own version of SkyBlock in the Prototype lobby!" +main_lobby.355="Sep 21st, 2012\n\nWelcome to Hypixel.net, is it currently in Alpha state, so if you guys encounter any bugs, just let me know!" +main_lobby.356="Jan 26th, 2014\n\nLots of new features have been released today! First of all, guilds are finally out, so let’s celebrate!" +main_lobby.357="Aug 1st, 2014\n\nThe August Mega Update has Arrived!" +main_lobby.358="Feb 21st, 2015\n\nWarlords has now entered the full open beta phase! The entire staff have been busy fixing the initial bugs found during the 3 hour Early Access Window." +main_lobby.359="Apr 11th, 2015\n\nHypixelians! Prepare yourself for a PvP experience like no other that has ever come to Hypixel!!!" +main_lobby.360="Jun 14th, 2015\n\nSkyWars is now available for everyone to play on the server! Join via the compass!" +main_lobby.361="Aug 20th, 2015\n\nMystery Box is Live! Housing is Live (Beta Mode)! Brand New Pets system! Vanity Shop Revamp!" +main_lobby.362="Jan 5th, 2017\n\nGreat news coming right up! In the next few days we will be introducing the Prototype Lobby (PTL), available to all players." +main_lobby.363="Feb 20th, 2017\n\nOur latest test game has just been added to the Hypixel Prototype Lobby – introducing Murder Mystery!" +main_lobby.364="Jun 27th, 2017\n\nIt's officially here - Bed Wars has fully released!" +main_lobby.365="Jul 27th, 2018\n\nToday we are releasing the Guild Update! It is one of the largest updates we've ever made!" +main_lobby.366="Dec 13th, 2018\n\nSince Sunday, all of us have been counting down the days, minutes, and even seconds until the first Hytale trailer would be released." +main_lobby.367="May 10th, 2021\n\nToday we're very excited to introduce a brand new feature to the server, Hypixel SMP!" +main_lobby.368="Mar 10th, 2021\n\nToday, we're beyond excited to announce the release of the official Hypixel SkyBlock Wiki available at" +main_lobby.369="CLICK FOR FULL POST" +main_lobby.370="Click to view the full post!" +main_lobby.371="Welcome to the dock!" +main_lobby.372="Here you can fish for treasure and junk, but you may find some other seasonal oddities too!" +main_lobby.373="Click me again to collect your fishing rod!" +main_lobby.374="Dock Master" +main_lobby.375="Welcome to the Fishing Hut!" +main_lobby.376="Here you can fish for all kinds of things, speak to the Dock Master to get started!" +main_lobby.377="Fish for hidden treasures!" +main_lobby.378="Changes the effect on your hook when fishing in the main lobby." +main_lobby.379="Selecting this option disables your Fish Hook Trail." +main_lobby.380="You haven't caught enough Special Fish for this!" +main_lobby.381="Catch 1 Special Fish" +main_lobby.382="You caught a cod!" +main_lobby.383="You caught a salmon!" +main_lobby.384="You caught a clownfish!" +main_lobby.385="You caught a pufferfish!" +main_lobby.386="Oh no, you caught a bowl!" +main_lobby.387="Oh no, you caught leather!" +main_lobby.388="Oh no, you caught leather boots!" +main_lobby.389="Oh no, you caught rotten flesh!" +main_lobby.390="Oh no, you caught a stick!" +main_lobby.391="Oh no, you caught string!" +main_lobby.392="Oh no, you caught a bone!" +main_lobby.393="Oh no, you caught an ink sac!" +main_lobby.394="Oh no, you caught a tripwire hook!" +main_lobby.395="Oh no, you caught a lily pad!" +main_lobby.396="Oh no, you caught a water bottle!" +main_lobby.397="Oh no, you caught a broken fishing rod!" +main_lobby.398="Oh no, you caught a soggy piece of paper!" +main_lobby.399="Oh no, you caught rabbit hide!" +main_lobby.400="You caught an enchanted book, that's a treasure!" +main_lobby.401="You caught a name tag, that's a treasure!" +main_lobby.402="You caught a saddle, that's a treasure!" +main_lobby.403="You caught an enchanted bow, that's a treasure!" +main_lobby.404="You caught an enchanted fishing rod, that's a treasure!" +main_lobby.405="You caught a diamond, that's a treasure!" +main_lobby.406="You caught a diamond sword, that's a treasure!" +main_lobby.407="You caught a gold pickaxe, that's a treasure!" +main_lobby.408="You caught a compass, that's a treasure!" +main_lobby.409="You caught an emerald, that's a treasure!" +main_lobby.410="You caught a secret fish!" +main_lobby.411="You caught %%amount%% %%game%% Coins!" +main_lobby.412="You caught %%amount%% Hypixel Experience!" +main_lobby.413="Dumpster Diver" +main_lobby.414="Increases junk drop chances" +main_lobby.415="Total Fishing Leaderboard" +main_lobby.416="Fish Collection Menu" +main_lobby.417="Check out your collection of fish, upgrade your fishing rod, check your stats and more!" +main_lobby.418="Collect Fishing Rod" +main_lobby.419="Not currently available!" +main_lobby.420="You selected %%trail%%!" +main_lobby.421="This trail is not currently available!" +main_lobby.422="Fish Hook Trails" +main_lobby.423="Collect Fishing Rod" +main_lobby.424="Collect your fishing rod to start fishing!" +main_lobby.425="Click to collect!" +main_lobby.426="Master Reward Tier I" +main_lobby.427="Master Reward Tier II" +main_lobby.428="Master Reward Tier III" +main_lobby.429="Summer Reward Tier I" +main_lobby.430="Summer Reward Tier II" +main_lobby.431="Summer Reward Tier III" +main_lobby.432="Summer Reward Tier IV" +main_lobby.433="Summer Reward Tier V" +main_lobby.434="Summer Reward Tier VI" +main_lobby.435="Summer Reward Tier VII" +main_lobby.436="Halloween Reward Tier I" +main_lobby.437="Halloween Reward Tier II" +main_lobby.438="Halloween Reward Tier III" +main_lobby.439="Halloween Reward Tier IV" +main_lobby.440="Halloween Reward Tier V" +main_lobby.441="Halloween Reward Tier VI" +main_lobby.442="Halloween Reward Tier VII" +main_lobby.443="Winter Reward Tier I" +main_lobby.444="Winter Reward Tier II" +main_lobby.445="Winter Reward Tier III" +main_lobby.446="Winter Reward Tier IV" +main_lobby.447="Winter Reward Tier V" +main_lobby.448="Winter Reward Tier VI" +main_lobby.449="Winter Reward Tier VII" +main_lobby.450="Untracked %%reward%%." +main_lobby.451="Tracking %%reward%%." +main_lobby.452="TRUE" +main_lobby.453="FALSE" +main_lobby.454="Enabled:" +main_lobby.455="I see you've found the Labyrinth." +main_lobby.456="This network of caves runs throughout the lobby with many entrances and exits." +main_lobby.457="It connects various points of Hypixel's history." +main_lobby.458="We haven't been able to map every tunnel, if you wish to venture deeper I wish you luck!" +main_lobby.459="You might find some ancient relics scattered around, maybe you can find them all!" +main_lobby.460="Collect hidden relics within the maze!" +main_lobby.461="You've already found this relic!" +main_lobby.462="You found the %%name%% Labyrinth Relic!\nSpeak to Lobby Explorer Theseus to view your relics!" +main_lobby.463="Labyrinth Relics" +main_lobby.464="Relics represent points in Hypixel's history. Find them scattered throughout the Labyrinth!" +main_lobby.465="Found: %%color%%%%found%%/%%total%%" +main_lobby.466="Click to view your collection!" +main_lobby.467="Explore the Labyrinth to find this relic!" +main_lobby.468="FOUND!" +main_lobby.469="NOT FOUND!" +main_lobby.470="v0.3.1 Prototype Railgun" +main_lobby.471="Paradoxed Infinity Bow" +main_lobby.472="Experimental Turbocharged Kart" +main_lobby.473="Hat of Undeniable Wealth and Respect" +main_lobby.474="Herobrine's Sword" +main_lobby.475="Fractured Golem of Appreciation" +main_lobby.476="Dull Vampire Fang" +main_lobby.477="Speleologist's Pickaxe" +main_lobby.478="Friends Online: %%friends%%" +main_lobby.479="Guild Online: %%guild%%" +main_lobby.480="Guild Online: No guild!" +main_lobby.481="All Games" +main_lobby.482="FEATURED" +main_lobby.483="Teleports you to the specified zone." +main_lobby.484="Activities:" +main_lobby.485="Already here!" +main_lobby.486="Click to teleport!" +main_lobby.487="Teleported to %%zone%%!" +main_lobby.488="You can interact with the Lobby Explorer or use /stuck to get back to spawn!" +main_lobby.489="Click to return to spawn!" +main_lobby.490="%%magic%%H You unlocked the Grappling Hook Gadget %%magic%%H\nHover over this message to read how to use it!" +main_lobby.491="To open Gadgets menu click here or open your\nCollectibles menu in your inventory." +main_lobby.492="Spawn" +main_lobby.493="Hello! This lobby is quite vast if you step beyond our cozy central area." +main_lobby.494="I can help you reach various destinations quicker if you wish!" +main_lobby.495="I happen to have a spare Grappling Hook Gadget that may help as well." +main_lobby.496="Happy exploring!" +main_lobby.497="Click NPCs to join games!" +main_lobby.498="This castle may be new to this land but it holds many secrets." +main_lobby.499="Be sure to check every room!" +main_lobby.500="Explore the secrets of the castle!" +main_lobby.501="Ruins" +main_lobby.502="These ruins have been here a long time, but the throne remains intact." +main_lobby.503="While it may be overgrown, you can still feel the sense of history." +main_lobby.504="Perhaps some other players might have been around when this structure was pristine." +main_lobby.505="Village" +main_lobby.506="Welcome to the Village!" +main_lobby.507="This is where most of our population lives, at the base of the castle." +main_lobby.508="Be sure to explore the castle, it has many secrets to uncover!" +main_lobby.509="Speak with me again if you wish to return to spawn!" +main_lobby.510="Farm" +main_lobby.511="This farm here provides the food for the village and castle." +main_lobby.512="Lots of different crops are grown!" +main_lobby.513="Port" +main_lobby.514="This shipping port is often very busy!" +main_lobby.515="Lots of shipments come in through our docks, including our supplies for decorating for holidays!" +main_lobby.516="Ancient Statues" +main_lobby.517="These statues have been here for a very long time, near the beginning of time." +main_lobby.518="At one point they may have been the pinnacle height of the lobby, but have since faded to the background." +main_lobby.519="However, they continue to guard from behind the cliffs, out of sight from most players." +main_lobby.520="Lobby Explorer Tom" +main_lobby.521="Lobby Explorer Oliver" +main_lobby.522="Lobby Explorer Charlotte" +main_lobby.523="Lobby Explorer Victoria" +main_lobby.524="Lobby Explorer Percy" +main_lobby.525="Lobby Explorer Theseus" +main_lobby.526="Lobby Explorer Nico" +main_lobby.527="Lobby Explorer Lily" +main_lobby.528="Lobby Explorer Sophia" +main_lobby.529="Lobby Explorer Iris" +main_lobby.530="Lobby Explorer Simon" +main_lobby.531="Zone Teleporter" +main_lobby.532="Undiscovered Zone" +main_lobby.533="Explore the lobby to find and unlock this zone!" +main_lobby.534="You haven't discovered this zone yet, explore the lobby to find it!" +main_lobby.535="%%magic%%H You have discovered the %%zone%% zone! %%magic%%H" +main_lobby.536="Return to Spawn" +main_lobby.537="Travel to:" +main_lobby.538="SkyBlock" +main_lobby.539="Halloween Guide" +main_lobby.540="Angler" +main_lobby.541="It looks kinda scary." +main_lobby.542="Clay Ball" +main_lobby.543="That's no egg!" +main_lobby.544="From the sea birthed beauty." +main_lobby.545="Cherry Blossom" +main_lobby.546="So pretty!" +main_lobby.547="Change the particles displayed on your hook while fishing." +main_lobby.548="Catch 1 Treasure Item" +main_lobby.549="You haven't caught enough treasure for this!" +main_lobby.550="You haven't caught enough junk for this!" +main_lobby.551="Catch 1 Junk Item" +main_lobby.552="Treasure's Sheen" +main_lobby.553="Beloved Junk" +main_lobby.554="Who let these loud mouths into my library?" +main_lobby.555="I don't know who these admins are but they need to follow the rules too!" +main_lobby.556="Who let these people into my kitchen??" +main_lobby.557="Hey! Don't burn that!" +main_lobby.558="Required Special Fish" +main_lobby.559="Summer Guide" +main_lobby.560="Welcome to Hypixel's %%festival%% Event!" +main_lobby.561="Earn Event Experience by playing games and completing Quests." +main_lobby.562="The more you level up, the more exclusive cosmetics you can unlock!" +main_lobby.563="Track your progress by clicking me again or viewing your My Profile menu!" +main_lobby.564="Check out our news post for a full breakdown of what's included in this event!" +main_lobby.565="Click to open!" +main_lobby.566="Stay tuned for a full news post for this event!" +main_lobby.567="News post soon!" +main_lobby.568="Event Page" +main_lobby.569="EVENT" +main_lobby.570="PAGE" +main_lobby.571="Click below to open our full Event Page!" +main_lobby.572="Lucent Bee Hive" +main_lobby.573="It's glowing!" +main_lobby.574="Summer Reward Tier VIII" +main_lobby.575="Pufferfish Pet" +main_lobby.576="Event Level: %%color%%%%level%%" +main_lobby.577="Success!" +main_lobby.578="Archimedes' Trail" +main_lobby.579="You haven't deactivated the %%orb%% enough times!" +main_lobby.580="You caught %%color%%%%amount%% Event Experience!" +main_lobby.581="Rarity: %%rarity%%" +main_lobby.582="Deactivations: %%count%%" +main_lobby.583="Found!" +main_lobby.584="Not Found!" +main_lobby.585="Uncommon" +main_lobby.586="Ultra Rare" +main_lobby.587="Shadow of Nyx" +main_lobby.588="Heart of Aphrodite" +main_lobby.589="Spark of Zeus" +main_lobby.590="Oh no, you caught burned flesh!" +main_lobby.591="Oh no, you caught charcoal!" +main_lobby.592="Click to view this Seasonal Release's Newspost" +main_lobby.593="This is used for upgrading your Main Lobby Fishing Rod." +main_lobby.594="Hypixel Level Guide" +main_lobby.595="You caught a cooked cod!" +main_lobby.596="Vulcan's Dock Master" +main_lobby.597="Enabled:" +main_lobby.598="Failed!" +main_lobby.599="%%magic%%H Unlocked the Vulcan's Blessing Enchantment! %%magic%%H\nClaim it in your Fishing Rod Enchants menu." +main_lobby.600="You caught a gold sword, that's a treasure!" +main_lobby.601="Curing Process" +main_lobby.602="Click for item stats!" +main_lobby.603="Find all of them to earn an awesome reward!" +main_lobby.604="Environment: %%color%%%%environment%%" +main_lobby.605="Fishing Stats: Total" +main_lobby.606="Click for more stats!" +main_lobby.607="You can try again!" +main_lobby.608="Stay tuned to hypixel.net for the full Event Newspost!" +main_lobby.609="You can't use cosmetics in this area!" +main_lobby.610="Treasure Caught: %%amount%%" +main_lobby.611="Fish Caught: %%amount%%" +main_lobby.612="You caught a molten gold, that's a treasure!" +main_lobby.613="Fish Hook Trails" +main_lobby.614="%%magic%%H Obtained a Flame of the Sun Titan %%magic%%H" +main_lobby.615="That code is outdated!" +main_lobby.616="You caught a charred pufferfish!" +main_lobby.617="Flame of the Sun Titan" +main_lobby.618="You caught an eye of ender, that's a treasure!" +main_lobby.619="Achievement Guide" +main_lobby.620="Oh no, you caught a steak!" +main_lobby.621="Use /presents" +main_lobby.622="Oh no, you caught a bucket of lava!" +main_lobby.623="CLICK TO CLAIM" +main_lobby.624="You can't use that while on the roller coaster!" +main_lobby.625="Lifetime Fishing Leaderboard" +main_lobby.626="No guild!" +main_lobby.627="Found In: %%color%%%%environment%%" +main_lobby.628="Something went wrong interacting with that NPC!" +main_lobby.629="Oh no, you caught a nether brick!" +main_lobby.630="Fireproofing process failed!\nSpeak to Vulcan's Dock Master to try again." +main_lobby.631="%bold%%%CLICK TO PLAY%%reset%%" +main_lobby.632="You caught a cooked salmon!" +main_lobby.633="Click to view upgrades!" +main_lobby.634="[NPC] %%name%%" +main_lobby.635="You caught a blaze rod, that's a treasure!" +main_lobby.636="The Roller Coaster is currently disabled, come back later!" +main_lobby.637="Entered %%code%%" +main_lobby.638="Oh no, you caught coal!" +main_lobby.639="You caught a chainmail chestplate, that's a treasure!" +main_lobby.640="%%enchant%% Upgrades" +main_lobby.641="You caught blaze powder, that's a treasure!" +main_lobby.642="%%magic%%H %%reward%% Progress: %%amountHas%%/%%amountNeeded%%" +main_lobby.643="You caught magma cream, that's a treasure!" +main_lobby.644="Fishing Rod Enchants" +main_lobby.645="10 Salmon Scales" +main_lobby.646="%%second%%s" +main_lobby.647="Unable to teleport you right now, try again shortly!" +main_lobby.648="%%magic%%H Collected 10 Salmon Scales %%magic%%H" +main_lobby.649="Rewards for dedicated fishing!" +main_lobby.650="Guilds Guide" +main_lobby.651="Sorry, I'm having trouble sending you to %%name%%, give me a moment!" +main_lobby.652="None caught!" +main_lobby.653="Find all of them to earn a super reward!" +main_lobby.654="%%magic%%H You unlocked the Grappling Hook Gadget %%magic%%H\nHover over this message to read how to use it!" +main_lobby.655="You haven't found this ingredient yet!" +main_lobby.656="Disabled Snow Particles! You can re-enable them at any time with /snow!" +main_lobby.657="Oh no, you caught a fermented spider eye!" +main_lobby.658="Enabled Snow Particles! You can disable them at any time with /snow!" +main_lobby.659="You can't use that gadget here!" +main_lobby.660="You haven't caught any Special Fish yet!" +main_lobby.661="Halloween Skull Pack" +main_lobby.662="This pack contains spooky themed skulls to use in your Housing plot!" +main_lobby.663="Craft 10,000 Arcade Coins!" +main_lobby.664="Craft 1,000 Hypixel Experience!" +main_lobby.665="Craft 10 SkyWars Souls!" +main_lobby.666="Craft 2,500 Bed Wars Coins!" +main_lobby.667="Spooked Punch Message" +main_lobby.668="Craft the Spooked Punch Message, which MVP+ players can use on staff!" +main_lobby.669="Fishing Rod Enchants" +main_lobby.670="Castle" +main_lobby.671="Mines" +main_lobby.672="Labyrinth" +main_lobby.673="Paintball Fight" +main_lobby.674="Fishing Hut" +main_lobby.675="Halloween Event" +main_lobby.676="Holidays Event" +main_lobby.677="Easter Event" +main_lobby.678="Summer Event" +main_lobby.679="There is no event currently active!" +main_lobby.680="Main Lobby Activities" +main_lobby.681="Main Lobby Activities" +main_lobby.682="View what activities are available in the Main Lobby for this event!" +main_lobby.683="Find this activity around the lobby!" +main_lobby.684="This activity is not currently available!" +main_lobby.685="Click here to teleport back to the Event Guide!" +main_lobby.686="Candy Hunt" +main_lobby.687="Search for candy baskets around the lobby to earn a reward!" +main_lobby.688="Archery" +main_lobby.689="Use zombies as target practice while competing for the leaderboard!" +main_lobby.690="Pumpkin Smash" +main_lobby.691="Whack pumpkins at the targets to earn points, but watch out for the evil bombs!" +main_lobby.692="Turbo Bat Racers" +main_lobby.693="Ride your bat through obstacle courses of varying difficulty throughout the lobby." +main_lobby.694="Witch's Cauldron" +main_lobby.695="Find hidden ingredients and brew recipes for unique items in the Witch's Cauldron!" +main_lobby.696="Fishing" +main_lobby.697="Fish for treasure and seasonally available fish throughout the lobby. Complete the collection!" +main_lobby.698="Happy spring!" +main_lobby.699="Have a wonderful spring!" +main_lobby.700="I love this season!" +main_lobby.701="Too bad I have to sit here." +main_lobby.702="Did I get ya?" +main_lobby.703="Outdated Vault Code: 372" +main_lobby.704="No Event!" +main_lobby.705="Pile Of Sand" +main_lobby.706="Rubber Duck" +main_lobby.707="This isn't meant to be here!" +main_lobby.708="Molten Iron" +main_lobby.709="Is it hot in here?" +main_lobby.710="Regular Fish" +main_lobby.711="Wait, what?" +main_lobby.712="Lava Shark" +main_lobby.713="Even scarier than a regular shark!" +main_lobby.714="Emerald Fish Hook Trail" +main_lobby.715="Legendary Fisher Banner" +main_lobby.716="Legendary Fisher Status" +main_lobby.717="Aquarium Cloak" +main_lobby.718="Spooked Pufferfish Hat" +main_lobby.719="Spooky Fish Gadget" +main_lobby.720="Spooky Fisher Banner" +main_lobby.721="School Cloak" +main_lobby.722="Hades' Hook" +main_lobby.723="Speak to Neptune's Nereid to learn how to ice fish in the Main Lobby! Only available during the Holidays Event!" +main_lobby.724="Neptune's Nereid" +main_lobby.725="Neptune's Nereid" +main_lobby.726="Your Fishing Stats in %%color%%%%environment%%" +main_lobby.727="Invalid fishing environment! Use one of the following or leave blank for total stats: %%options%%" +main_lobby.728="Fishing in lava requires the Vulcan's Blessing enchantment.\nSpeak to Vulcan's Dock Master for more information!" +main_lobby.729="The ice is too thick to break here. Try the ponds in the mountains!" +main_lobby.730="This water has frozen over but the ice is thin. Speak to Neptune's Nereid to learn about the Neptune's Fury enchantment." +main_lobby.731="To catch cold climate fish you must have the Neptune's Fury enchantment, speak with Neptune's Nereid.\nYou will currently catch only regular water fish." +main_lobby.732="You haven't caught enough fish in ICE for this!" +main_lobby.733="This item was only available during the %%event%% %%year%% event." +main_lobby.734="Catch 1 Fish in ICE" +main_lobby.735="Catch %%amount%% Fish in ICE" +main_lobby.736="Unavailable!" +main_lobby.737="Changes your fishing rod in your inventory." +main_lobby.738="Inaugural Ice Fishing Rod" +main_lobby.739="Change your fishing rod in your inventory and displayed in hover text when you catch Special Fish!" +main_lobby.740="This item will not be available after the %%event%% %%year%% event!" +main_lobby.741="You caught a trout!" +main_lobby.742="You caught a perch!" +main_lobby.743="You caught a pike!" +main_lobby.744="Oh no, you caught a snowball!" +main_lobby.745="Oh no, you caught an ice shard!" +main_lobby.746="Oh no, you caught a clump of leaves!" +main_lobby.747="Oh no, you caught frozen flesh!" +main_lobby.748="You caught an iron sword, that's a treasure!" +main_lobby.749="Fishing Rod: %%rod%%" +main_lobby.750="Allows for fishing in ice." +main_lobby.751="Neptune's Fury" +main_lobby.752="Speak to Neptune's Nereid in the Ice Fishing area during the Holidays Event in December." +main_lobby.753="Frozen Meal" +main_lobby.754="Instant dinner!" +main_lobby.755="Festive Lights" +main_lobby.756="Just needs to be untangled." +main_lobby.757="Menu Settings" +main_lobby.758="Settings for Fish Collection menu." +main_lobby.759="Uncaught Fish: %%toggle%%" +main_lobby.760="Hidden" +main_lobby.761="Shown" +main_lobby.762="Menu Icons: %%toggle%%" +main_lobby.763="Normal" +main_lobby.764="Simplified" +main_lobby.765="Click to toggle Uncaught Fish!" +main_lobby.766="Right click to toggle Menu Icons!" +main_lobby.767="When the water freezes over, the underwater life does not vanish." +main_lobby.768="Nearby are a set of ponds with many fish that prefer the cold, but are trapped beneath the ice." +main_lobby.769="However, the ice is thin." +main_lobby.770="Here is an enchantment that will allow your fishing rod to break through, so that you may uncover what lies below." +main_lobby.771="You selected %%cosmetic%%!" +main_lobby.772="This item is not currently available!" +main_lobby.773="This environment is only available during certain seasonal events." +main_lobby.774="Fishing Stats: %%color%%%%environment%%" +main_lobby.775="Master Reward Tier IV" +main_lobby.776="Chill The Fish 3" +main_lobby.777="Friends Guide" +main_lobby.778="Hypixel Level Guide" +main_lobby.779="Guilds Guide" +main_lobby.780="Change the particles displayed on your hook while fishing." +main_lobby.781="Fishing Rods" +main_lobby.782="You haven't unlocked that reward yet!" +main_lobby.783="Event Fishing Reward" +main_lobby.784="Summer Fishing Reward" +main_lobby.785="Halloween Fishing Reward" +main_lobby.786="Holidays Fishing Reward" +main_lobby.787="Easter Fishing Reward" +main_lobby.788="Springtime Fishing Rod" +main_lobby.789="Easter Reward Tier I" +main_lobby.790="Easter Reward Tier II" +main_lobby.791="Easter Reward Tier III" +main_lobby.792="Your tracked seasonal fishing reward was disabled because it's no longer available!" +main_lobby.793="Your tracked reward was disabled because you claimed it." +main_lobby.794="%%magic%%H %%reward%% Progress: COMPLETED!" +main_lobby.795="Find sparking hidden Easter Eggs around the lobby for a reward!" +main_lobby.796="Search for hidden Easter Eggs around the lobby to earn a reward!" +main_lobby.797="Main Lobby Fishing" +main_lobby.798="LOCKED %%amountHas%%/%%amountReq%% %%dropType%%" +main_lobby.799="Required %%dropType%%: %%amount%%" +main_lobby.800="Mythical Fish" +main_lobby.801="Uncover mysterious fish from beneath the waters." +main_lobby.802="A mysterious and powerful fish." +main_lobby.803="A mysterious fish, caught with the Mythical Hook Enchantment." +main_lobby.804="Mythical Fish Caught: %%amount%%" +main_lobby.805=" - Mythical Fish Caught: %%amount%%" +main_lobby.806="Mythical Fish" +main_lobby.807="Mythical Hook" +main_lobby.808="Allows for catching Mythical Fish" +main_lobby.809="Not found!" +main_lobby.810="You found a %%ingredient%% ingredient!\nUse it back at the Witch's Cauldron near spawn!" +main_lobby.811="Click me!" +main_lobby.812="JUMP" +main_lobby.813="You've already crafted this!" +main_lobby.814=" HAPPY EASTER" +main_lobby.815="Click ingredients you have to fill the recipe!" +main_lobby.816="Click to add!" +main_lobby.817="Weight Record: %%weight%%" +main_lobby.818="SPOOKY HALLOWEEN" +main_lobby.819="Oops! Try again later!" +main_lobby.820="Features:" +main_lobby.821="Lobby features:" +main_lobby.822="Snowballs" +main_lobby.823="You've crafted %%name%%!" +main_lobby.824="Recipe:" +main_lobby.825="Click here to view news post!" +main_lobby.826="SUCCESS!" +main_lobby.827="Teleported back to spawn!" +main_lobby.828="on Hypixel" +main_lobby.829="No Ingredients!" +main_lobby.830=" %%underline%%READ MORE" +main_lobby.831="CLAIMED" +main_lobby.832="Unrecorded" +main_lobby.833="You haven't crafted this!" +main_lobby.834="Invalid Recipe!" +main_lobby.835="Catch %%orb%% 1 time" +main_lobby.836="Fishing Rewards are currently disabled, check back later!" +main_lobby.837="Yearly Best Scores" +main_lobby.838="Points: %%points%% - Hits: %%hits%% - Time: %%time%%" +main_lobby.839=" %%underline%%THREAD SOON" +main_lobby.840="There's no valid recipe input!" +main_lobby.841="✦ GAME ANNOUNCEMENT FROM HYPIXEL ✦" +main_lobby.842="Fishing Menu" +main_lobby.843="Find this ingredient around the lobby!" +main_lobby.844="Caught: %%count%%" +main_lobby.845="Find glowing hidden Candy Baskets around the lobby for a reward!" +main_lobby.846="You caught a %%weight%%kg %%mythicalFish%%!" +main_lobby.847="Snowball" +main_lobby.848="You found %%color%% Wool!" +main_lobby.849="You need to find all %%total%% pieces of Wool hidden around the Main Lobby to enter the Vault! You've found %%found%% so far." +main_lobby.850="Also on Hypixel:" +main_lobby.851="Click to remove!" +main_lobby.852="Lifetime Fishing" +main_lobby.853="Weekly Best Scores" +main_lobby.854="Environment: %%color%%%%environment%% | Type: %%dropColor%%%%drop%%" +main_lobby.855="REWARDS DISABLED" +main_lobby.856="You have found all pieces of Wool, so you can now enter the Vault!" +main_lobby.857="Slot: %%name%%" +main_lobby.858="Whoosh! You found all %%total%% pieces of Wool, so you were able to enter the Vault!" +main_lobby.859="%%festival%% %%year%%" +main_lobby.860="You already found this ingredient!" +main_lobby.861="You already found this ghost!" +main_lobby.862="Empty Slot" +main_lobby.863="Upgraded your Fishing Rod with %%enchantName%%!" +main_lobby.864="You're already using this ingredient!" +main_lobby.865="CLICK HERE!" +main_lobby.866="%%player%% caught an ULTRA RARE %%mythicalFish%%!" +main_lobby.867="No guild!" +main_lobby.868="The recipe combination isn't valid!" +main_lobby.869="A Mythical Fish emerges from the depths!!" +main_lobby.870="Already using this!" +main_lobby.871="You can't ride a pet while playing!" +main_lobby.872="NEW WEIGHT RECORD!" +main_lobby.873="Congratulations! You found all the ghosts!" +main_lobby.874="Click ingredients below to craft!" +main_lobby.875="You found a ghost!" +main_lobby.876="Combination reset!" +main_lobby.877="%%festival%% %%year%% Fishing" +main_lobby.878="You've crafted this!" +main_lobby.879=" HAPPY SUMMER" +main_lobby.880="Find sparkling hidden Easter Eggs around the lobby for a reward!" +main_lobby.881="Cauldron Recipe Book" +main_lobby.882="Catch %%orb%% %%amount%% times" +main_lobby.883="%%weight%%kg" +main_lobby.884="???" +main_lobby.885="Witch's Cauldron" +main_lobby.886="%%magic%%H %%reward%% Progress: %%amountHas%%/%%amountNeeded%% %%dropType%%" +main_lobby.887="You broke your hook and the Mythical Fish got away!" +main_lobby.888="You're currently using this ingredient in the recipe!" +main_lobby.889="Congrats, you successfully entered the code!" +main_lobby.890="Find ingredients scattered around the lobby in order to craft rewards! Can you figure out all of the recipes?" +main_lobby.891="Yearly Best Times" +main_lobby.892="This event is over now, sorry!" +main_lobby.893="The fish snapped the line and got away!" +main_lobby.894="Click to see your recipes!" +main_lobby.895="Your slots are full!" +main_lobby.896="Caught a %%weight%%kg %%mythicalFish%%!" +main_lobby.897="Your line snapped and the Mythical Fish got away!" +main_lobby.898="Already Crafted!" +main_lobby.899="Try using different ingredients!" +main_lobby.900="You haven't caught %%orb%% enough times!" +main_lobby.901="Forest Fright" +main_lobby.902="Riverside Revenge" +main_lobby.903="Cryptic Castle" +main_lobby.904="Undead Archery" +main_lobby.905="Turbo Bat Racers" +main_lobby.906="Pumpkin Smash" +main_lobby.907="Undead Archery" +main_lobby.908="Special Fish" +main_lobby.909="Collect various unique fish throughout the different seasons!" +main_lobby.910="Special Fish" +main_lobby.911="Special Fish are unique fish that you can only catch once." +main_lobby.912="There are some available year-round, but most only appear in our waters at certain times of the year and in certain fishing environments." +main_lobby.913="Can you catch them all?" +main_lobby.914="Mythical Fish" +main_lobby.915="Mythical Fish are unique fish that appear more commonly than Special Fish." +main_lobby.916="They are more fiesty and you need to fight them in order to reel them in." +main_lobby.917="In order to catch Mythical Fish, you must enable the Mythical Hook Enchantment." +main_lobby.918="Ember of Helios" +main_lobby.919="Fishing Rod 3000" +main_lobby.920="Haunted Fishing Rod" +main_lobby.921="Event Guide" +main_lobby.922="Dust of Selene" +main_lobby.923="Present Hunt" +main_lobby.924="Search for hidden presents around every lobby on Hypixel to earn a reward!" +main_lobby.925="Find sparkling hidden presents around EVERY lobby for a reward!" +main_lobby.926="Calculates the time it takes for a fish to appear after the bobber hits liquid." +main_lobby.927="List of all your drop chances, enchantments included." +main_lobby.928="Your relative chances are what actually apply to you, with all other drops accounted for." +main_lobby.929="Full Chances" +main_lobby.930="Your Results:" +main_lobby.931="Rarity Chances:" +main_lobby.932="%%chance%%%" +main_lobby.933="No Lure" +main_lobby.934="Chance of %%type%%" +main_lobby.935="Min: %%minTime%%s" +main_lobby.936="Max: %%maxTime%%s - (Lure Level x %%decrementPer%%s)" +main_lobby.937="%%chance%%% + (%%enchant%% Level x %%chancePerLevel%%%%%gray%%)" +main_lobby.938="Breaks down your chances for this type of fishing drop." +main_lobby.939="Interested in the math behind fishing? Check out some breakdowns of the equations and how they apply to you." +main_lobby.940="No %%enchant%%" +main_lobby.941="Fishing Time" +main_lobby.942="%%chance%%% (%%enchantLevel%%)" +main_lobby.943="Click for math!" +main_lobby.944="The base chances are without counting other drops." +main_lobby.945="Max: %%maxTime%%s (%%lureLevel%%)" +main_lobby.946="%%chance%%% %%drop%%" +main_lobby.947="Base Chances:" +main_lobby.948="Fishing Chance Breakdown" +main_lobby.949="For example, if you have a high Luck of the Sea level, naturally your chances for everything else will lower." +main_lobby.950="Min: %%minTime%%s" +main_lobby.951="Math Disclaimer" +main_lobby.952="%%chance%%% %%drop%%" +main_lobby.953="Base Equation:" +main_lobby.954="Relative Chances:" +main_lobby.955="Festive Fishing Rod" +main_lobby.956="fishing in the Main Lobby" +main_lobby.957="Helios' Breath Trail" +main_lobby.958="Trash" +main_lobby.959="Place the requested ingredients in the oven." +main_lobby.960="Click here!" +main_lobby.961="Baker's Bash" +main_lobby.962="You can't use lobby cosmetics while playing!" +main_lobby.963="Blocked Slot" +main_lobby.964="GO!" +main_lobby.965="Your inventory is full!" +main_lobby.966="You don't have the ingredients! Check above the oven for what you need!" +main_lobby.967="You baked a total of %%score%% treat!" +main_lobby.968="You baked a total of %%score%% treats!" +main_lobby.969="You smoked your previous score of %%score%%!" +main_lobby.970="Unfortunately, you haven't beaten your best score of %%score%% yet!" +main_lobby.971="You can't play this while wearing a Suit!" +main_lobby.972="Baker's Bash" +main_lobby.973="CLICK TO PLAY" +main_lobby.974="Timer started, bake as many treats as you can!" +main_lobby.975="Score: %%score%%" +main_lobby.976="Best: %%score%%" +main_lobby.977="Something went wrong!" +main_lobby.978="Welcome to Hypixel's %%year%%%%suffix%% Anniversary Celebration!" +main_lobby.979="Every year we celebrate with an annual Bingo activity." +main_lobby.980="Choose a category of games you wish to play, and complete objectives to complete Bingo Cards!" +main_lobby.981="Completing Bingo Cards awards you Bingo Bucks to spend on exclusive cosmetic rewards!" +main_lobby.982="Click me again to open the Bingo Menu! Have fun!" +main_lobby.983="Catch %%amount%% Special Fish (%%current%%/%%amount%%)" +main_lobby.984="Catch %%amount%% Treasure Items (%%current%%/%%amount%%)" +main_lobby.985="Catch %%amount%% Junk Items (%%current%%/%%amount%%)" +main_lobby.986="Neptune's Grace" +main_lobby.987="Ominous Rain" +main_lobby.988="Fishing Friday ends in %%time%%" +main_lobby.989="Fishing Friday starts in %%time%%" +main_lobby.990="Fishing speed decreased by -1s" +main_lobby.991="Click to view rewards!" +main_lobby.992=" - Plants Caught: %%amount%%" +main_lobby.993=" - Creatures Caught: %%amount%%" +main_lobby.994="Catch the following Special Fish:" +main_lobby.995="You haven't caught enough creatures for this!" +main_lobby.996="Catch 1 Creature" +main_lobby.997="Catch %%amount%% Creatures (%%current%%/%%amount%%)" +main_lobby.998="You haven't caught enough plants for this!" +main_lobby.999="Catch 1 Plant" +main_lobby.1000="Catch %%amount%% Plants (%%current%%/%%amount%%)" +main_lobby.1001="Catch 1 Squid" +main_lobby.1002="Overgrown Fishing Rod" +main_lobby.1003="Zoologist Fishing Rod" +main_lobby.1004="Fishing Rod" +main_lobby.1005="Organic Material" +main_lobby.1006="Creature Catch" +main_lobby.1007="Fish Hook Trail" +main_lobby.1008="Plant" +main_lobby.1009="Creature" +main_lobby.1010="Land Line" +main_lobby.1011="Catch creatures instead of fish!" +main_lobby.1012="Event: -1s" +main_lobby.1013="%%event%% Rewards" +main_lobby.1014="Spirit of Demeter" +main_lobby.1015="Warp To %%color%%%%destination%%" +main_lobby.1016="Warped to %%color%%%%destination%%!" +main_lobby.1017="Fishing Friday" +main_lobby.1018="Ends in %%time%%" +main_lobby.1019="Creatures Caught: %%amount%%" +main_lobby.1020="Plants Caught: %%amount%%" +main_lobby.1021="You caught wheat!" +main_lobby.1022="You caught a potato!" +main_lobby.1023="You caught a melon slice!" +main_lobby.1024="You caught sweet berries!" +main_lobby.1025="You caught glow berries!" +main_lobby.1026="You caught bamboo!" +main_lobby.1027="You caught dried kelp!" +main_lobby.1028="You caught a baked potato!" +main_lobby.1029="You caught a glistering melon!" +main_lobby.1030="You caught charred berries!" +main_lobby.1031="You caught a nether wart!" +main_lobby.1032="You caught warped roots!" +main_lobby.1033="You caught frozen kelp!" +main_lobby.1034="You caught a nautilus shell, that's a treasure!" +main_lobby.1035="You caught a Sheep!" +main_lobby.1036="You caught a Chicken!" +main_lobby.1037="You caught a Pig!" +main_lobby.1038="You caught a Cow!" +main_lobby.1039="You caught a Creeper!" +main_lobby.1040="You caught a Zombie!" +main_lobby.1041="You caught a Skeleton!" +main_lobby.1042="You caught a Spider!" +main_lobby.1043="You caught a Zombie Pigman!" +main_lobby.1044="You caught a Blaze!" +main_lobby.1045="You caught a Magma Cube!" +main_lobby.1046="You caught a Cave Spider!" +main_lobby.1047="You caught a Slime!" +main_lobby.1048="You caught a Squid!" +main_lobby.1049="Bigger Fish" +main_lobby.1050="Increased weights for Mythical Fish" +main_lobby.1051="Mythical Chance" +main_lobby.1052="Increased chances to catch Mythical Fish" +main_lobby.1053="Dense Vegetation" +main_lobby.1054="Catch Plants and unique Special Fish with Herbivore" +main_lobby.1055="Creatures" +main_lobby.1056="Catch Creatures with Land Line" +main_lobby.1057="Poisonous Potato" +main_lobby.1058="This is outrageous!" +main_lobby.1059="Golden Apple" +main_lobby.1060="The best plant!" +main_lobby.1061="Burnt Plant" +main_lobby.1062="I guess that counts" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/misc.properties b/configuration/i18n/en_US/official/misc.properties new file mode 100644 index 000000000..65c0997a6 --- /dev/null +++ b/configuration/i18n/en_US/official/misc.properties @@ -0,0 +1,519 @@ +mcp_miscellaneous.0="Total Earned Coins: %%earned%%" +mcp_miscellaneous.1=" +%%earned%% %%reason%%" +mcp_miscellaneous.2="Total Earned Experience: %%experience%%" +mcp_miscellaneous.3=" +%%earned%% %%reason%%" +mcp_miscellaneous.4="Only the party leader can warp you into a game! Have them use this sign or /party leave" +mcp_miscellaneous.5="You cannot be in a party while joining %%gametype%% solo!" +mcp_miscellaneous.6="Your party cannot have more than 2 players while joining %%gametype%% team!" +mcp_miscellaneous.7="Your party must be 4 players while joining friends mode!" +mcp_miscellaneous.8="Your party cannot have more than 3 players while joining %%gametype%% team!" +mcp_miscellaneous.9="You cannot be in a party while joining ranked %%gametype%%!" +mcp_miscellaneous.10="Your party can't queue for %%gametype%%: %%map%% because %%player%% isn't online!" +mcp_miscellaneous.11="You have to be in a 4 player party while joining friends mode!" +mcp_miscellaneous.12="You need at least %%required%% kills in any mode to play ranked %%gametype%%!" +mcp_miscellaneous.13="Sorry, we couldn't find any servers with enough room for %%gametype%%: %%map%%! Try again in a few minutes!" +mcp_miscellaneous.14="Found a server running %%gametype%%: %%map%%! Sending you to %%server%%!" +mcp_miscellaneous.15="There are no servers that have enough room for a party right now! Try again in a moment!" +mcp_miscellaneous.16="Sending you to %%server%%!" +mcp_miscellaneous.17="Your party cannot have more than %%number%% players while joining %%gametype%% solo!" +mcp_miscellaneous.18="You earned a total of %%exp%% Experience" +mcp_miscellaneous.19="Can't find a player by that name!" +mcp_miscellaneous.20="Invalid usage! '/%%command%% %%args%%'" +mcp_miscellaneous.21="Invalid input!" +mcp_miscellaneous.22="Click to suggest %%command%%" +mcp_miscellaneous.23="That player isn't online!" +mcp_miscellaneous.24="You are currently muted." +mcp_miscellaneous.25="You are currently muted for %%reason%%." +mcp_miscellaneous.26="An error occurred while executing that command! Please report this to a staff member!" +mcp_miscellaneous.27="You must be in a lobby to use this command!" +mcp_miscellaneous.28="Settings:" +mcp_miscellaneous.29="An error occurred while processing that. Please try again in a moment." +mcp_miscellaneous.30="You are not the party leader!" +mcp_miscellaneous.31="Only usable by Party Leader" +mcp_miscellaneous.32="Your game had %%amount%% %%rank%%s (or higher)" +mcp_miscellaneous.33="Total Earned Hypixel Experience: %%experience%%" +mcp_miscellaneous.34="You earned a total of %%exp%% Hypixel Experience" +mcp_miscellaneous.35="Remove a player from your friends" +mcp_miscellaneous.36="Housing is temporarily disabled for maintenance!" +mcp_miscellaneous.37="You cannot ignore this player!" +mcp_miscellaneous.38="Added %%player%% to your ignore list." +mcp_miscellaneous.39="You've already ignored that player! /ignore remove Player to unignore them!" +mcp_miscellaneous.40="You cannot ignore yourself." +mcp_miscellaneous.41="Invalid usage! Use: /ignore add Player" +mcp_miscellaneous.42="Removed %%player%% from your ignore list." +mcp_miscellaneous.43="You aren't ignoring that player! /ignore add Player to ignore!" +mcp_miscellaneous.44="Invalid usage! Use: /ignore remove Player" +mcp_miscellaneous.45="Player" +mcp_miscellaneous.46="Unignore a player" +mcp_miscellaneous.47="Ignore a player" +mcp_miscellaneous.48="List ignored players" +mcp_miscellaneous.49="(page)" +mcp_miscellaneous.50="I don't know how to parse page number %%number%%!" +mcp_miscellaneous.51="Invalid usage! Use: /ignore list (page)" +mcp_miscellaneous.52="The page number must be positive!" +mcp_miscellaneous.53="------ Ignored Users (Page %%page%% of %%max_page%%) ------" +mcp_miscellaneous.54="Are you sure? This will send you to the lobby. Type /delivery again to confirm" +mcp_miscellaneous.55="Invalid usage! /joinlobby #" +mcp_miscellaneous.56="Attempting to teleport you to %%lobby%%" +mcp_miscellaneous.57="Invalid number!" +mcp_miscellaneous.58="Lobby" +mcp_miscellaneous.59="I'm not sure what you meant by %%input%%" +mcp_miscellaneous.60="Couldn't find a main lobby to teleport you to!" +mcp_miscellaneous.61="Teleports you to the main lobby" +mcp_miscellaneous.62="This command teleports you to the main lobby. Use: /main" +mcp_miscellaneous.63="Please don't spam the command!" +mcp_miscellaneous.64="Right click with the compass in a lobby to select a game!" +mcp_miscellaneous.65="You can report cheaters using\n/watchdogreport (username) (type of cheats)" +mcp_miscellaneous.66="You can report chat abuse using\n/chatreport (username)" +mcp_miscellaneous.67="Looks like something went wrong, try again in a second!" +mcp_miscellaneous.68="Report a player to Watchdog" +mcp_miscellaneous.69="Message" +mcp_miscellaneous.70="Invalid usage! Use: /swaplobby (number)" +mcp_miscellaneous.71="That lobby is full!" +mcp_miscellaneous.72="Unknown lobby type!" +mcp_miscellaneous.73="Sending you to %%server%%" +mcp_miscellaneous.74="You must be in a lobby to use this command!" +mcp_miscellaneous.75="The conversation you were in expired and you have been moved back to the ALL channel." +mcp_miscellaneous.76="Please try this command again in a moment." +mcp_miscellaneous.77="You can only send a message once every half second!" +mcp_miscellaneous.78="Please do not spam the same message over and over." +mcp_miscellaneous.79="Invalid usage! Use: /msg (player) (message)" +mcp_miscellaneous.80="You have opened too many chat conversations with staff. Slow down!" +mcp_miscellaneous.81="An error occurred! Please try again in a moment!" +mcp_miscellaneous.82="You may not message this person while muted. Your mute ends in %%time%%" +mcp_miscellaneous.83="That player has silence enabled and can't be messaged right now!" +mcp_miscellaneous.84="You can only message people who are on your friends list!" +mcp_miscellaneous.85="That player has added you to their ignored players list!" +mcp_miscellaneous.86="Opened a chat conversation with %%name%% for the next 5 minutes. Use /chat a to leave" +mcp_miscellaneous.87="Invalid usage! Use: /r (message)" +mcp_miscellaneous.88="Nobody has messaged you in the past 5 minutes!" +mcp_miscellaneous.89="+%%amount%% Karma!" +mcp_miscellaneous.90="That's not a gift!" +mcp_miscellaneous.91="You must be Hypixel Level 5 or higher in order to send a gift!" +mcp_miscellaneous.92="You sent a gift containing %%award%% %%name%% to %%player%%!" +mcp_miscellaneous.93="You received a gift from %%sender%%!" +mcp_miscellaneous.94="Visit a Mystery Vault located in any lobby to open it!" +mcp_miscellaneous.95="Something weird happened when sending that! Please log out and back in. If it keeps happening, report to staff." +mcp_miscellaneous.96="I couldn't find that crafting recipe!" +mcp_miscellaneous.97="You don't have enough Mystery Dust to craft that!" +mcp_miscellaneous.98="You crafted %%name%%" +mcp_miscellaneous.99="You opened a bag of %%amount%% Hypixel Experience" +mcp_miscellaneous.100="You don't have any of that type of EXP bag left!" +mcp_miscellaneous.101="You've already used that! Try logging out and back in!" +mcp_miscellaneous.102="You are radiating with" +mcp_miscellaneous.103="The next game you play will reward you and the" +mcp_miscellaneous.104="other players with a bag of " +mcp_miscellaneous.105="You are now friends with %%name%%" +mcp_miscellaneous.106="You have %%count%% pending friend requests. Use /f requests to see them!" +mcp_miscellaneous.107="Your friend request to %%name%% has expired." +mcp_miscellaneous.108="The friend request from %%name%% has expired." +mcp_miscellaneous.109="You're already friends with this person!" +mcp_miscellaneous.110="You've already sent a friend request to this person!" +mcp_miscellaneous.111="This person has blocked you from sending friend requests to them!" +mcp_miscellaneous.112="You aren't allowed to send friend requests to this person!" +mcp_miscellaneous.113="This person has friend requests disabled!" +mcp_miscellaneous.114="Please wait before sending this person another request!" +mcp_miscellaneous.115="Invalid usage! Valid usage: /friend accept Player" +mcp_miscellaneous.116="That person hasn't invited you to be friends! Try /friend %%name%%" +mcp_miscellaneous.117="Accept a friend request" +mcp_miscellaneous.118="Invalid usage! Valid usage: /friend deny Player" +mcp_miscellaneous.119="Declined %%name%%'s friend request!" +mcp_miscellaneous.120="%%name%% hasn't sent you a friend request!" +mcp_miscellaneous.121="Decline a friend request" +mcp_miscellaneous.122="You can only use this command once every 10 seconds!" +mcp_miscellaneous.123="Toggled friend invisibility off." +mcp_miscellaneous.124="Toggled friend invisibility on." +mcp_miscellaneous.125="Toggle invisibility in friends list" +mcp_miscellaneous.126="View friend requests" +mcp_miscellaneous.127="Invalid page number!" +mcp_miscellaneous.128="Page number must be positive!" +mcp_miscellaneous.129="Invalid usage! Valid usage: /friend requests (page)" +mcp_miscellaneous.130="Friend Requests (Page %%page%% of %%max_page%%)" +mcp_miscellaneous.131="Click to deny the friend request" +mcp_miscellaneous.132="Click to accept the friend request" +mcp_miscellaneous.133="ACCEPT" +mcp_miscellaneous.134="DENY" +mcp_miscellaneous.135="IGNORE" +mcp_miscellaneous.136="Click to ignore player" +mcp_miscellaneous.137="Toggle friend requests" +mcp_miscellaneous.138="Disabled other player's ability to send you friend requests." +mcp_miscellaneous.139="Enabled other player's ability to send you friend requests." +mcp_miscellaneous.140="You don't have any friends yet! Add some with /friend add player" +mcp_miscellaneous.141="List your friends" +mcp_miscellaneous.142="%%name%% is online!" +mcp_miscellaneous.143="%%name%% is offline!" +mcp_miscellaneous.144="You removed %%friend_name%% from your friends list!" +mcp_miscellaneous.145="%%player_name%% isn't on your friends list!" +mcp_miscellaneous.146="Invalid usage! Valid usage: /friend Player" +mcp_miscellaneous.147="Invalid usage! Valid usage: /friend add Player" +mcp_miscellaneous.148="Kick offline players from the party" +mcp_miscellaneous.149="No offline players to kick!" +mcp_miscellaneous.150="Friend Commands:" +mcp_miscellaneous.151="You can't add yourself as a friend!" +mcp_miscellaneous.152="They've invited you, but an error occurred while completing! Try again in a moment!" +mcp_miscellaneous.153="Click to block all future friend requests and chat messages" +mcp_miscellaneous.154="Add a player as a friend" +mcp_miscellaneous.155="You sent a friend request to %%name%%! They have 5 minutes to accept it!" +mcp_miscellaneous.156="Friend request from" +mcp_miscellaneous.157="Click to block all future friend requests and chat messages from this player" +mcp_miscellaneous.158="You've already opened that crate! It had a %%item%% in it! Try logging out and back in!" +mcp_miscellaneous.159="You were given %%number%% EXP for linking your website account!" +mcp_miscellaneous.160="PARTY" +mcp_miscellaneous.161="ALL" +mcp_miscellaneous.162="Use this command to challenge another party to" +mcp_miscellaneous.163="a 8v8 Cops and Crims battle! To use it, use:" +mcp_miscellaneous.164="/party challenge Player where Player is the other party leader" +mcp_miscellaneous.165="You are now in the %%channel%% channel" +mcp_miscellaneous.166="Could not find that server!" +mcp_miscellaneous.167="You must be in a party to join the party channel!" +mcp_miscellaneous.168="You must be in a guild to join the guild channel!" +mcp_miscellaneous.169="Could not find player %%player%%" +mcp_miscellaneous.170="I couldn't find a lobby to put you in!" +mcp_miscellaneous.171="Something went wrong and I couldn't find that map! Please report this to a staff!" +mcp_miscellaneous.172="You're already in that player's house!" +mcp_miscellaneous.173="Sending you back to %%server%%..." +mcp_miscellaneous.174="Sorry, all housing servers are full right now! Try again in a moment!" +mcp_miscellaneous.175="Sending you to %%server%%..." +mcp_miscellaneous.176="All Housing Servers are busy at the moment. Try again in a second." +mcp_miscellaneous.177="Invalid command!" +mcp_miscellaneous.178="Found a server running %%game%%: %%map%%! Sending you to %%servername%%!" +mcp_miscellaneous.179="[reason]" +mcp_miscellaneous.180="[setting]" +mcp_miscellaneous.181="[tag]" +mcp_miscellaneous.182="[value]" +mcp_miscellaneous.183="For questions or issues related to payments visit " +mcp_miscellaneous.184="support.hypixel.net" +mcp_miscellaneous.185="https://support.hypixel.net/" +mcp_miscellaneous.186="Report server issues or bugs on the forums: " +mcp_miscellaneous.187="hypixel.net/forums/35/" +mcp_miscellaneous.188="https://hypixel.net/forums/35/" +mcp_miscellaneous.189="Found a rule breaker? Report them on the forums: " +mcp_miscellaneous.190="hypixel.net/forums/37/" +mcp_miscellaneous.191="https://hypixel.net/forums/37/" +mcp_miscellaneous.192="Need more help? Check out our help section: " +mcp_miscellaneous.193="hypixel.net/forums/5/" +mcp_miscellaneous.194="https://hypixel.net/forums/5/" +mcp_miscellaneous.195="For help and support visit http://mc.163.com/hypixel" +mcp_miscellaneous.196="You cannot be in a party while joining Murder Mystery Hardcore!" +mcp_miscellaneous.197="I'm not sure what network you're on!" +mcp_miscellaneous.198="Incorrect usage! Correct usage: /tpa player or /tpa accept player" +mcp_miscellaneous.199="Couldn't find a player by the name of '%%name%%'!" +mcp_miscellaneous.200="This person has not requested to teleport to you, or it has expired!" +mcp_miscellaneous.201="That player is no longer online!" +mcp_miscellaneous.202="This player can no longer be teleported to!" +mcp_miscellaneous.203="You teleported to %%name%%" +mcp_miscellaneous.204="%%name%% teleported to you!" +mcp_miscellaneous.205="You have to have VIP+ or higher to use this command!" +mcp_miscellaneous.206="Buy VIP+ and more at http://store.hypixel.net/" +mcp_miscellaneous.207="You cannot teleport to this player! They aren't in the same lobby as you!" +mcp_miscellaneous.208="You cannot teleport to this player!" +mcp_miscellaneous.209="Invalid usage! '/%%command%%'" +mcp_miscellaneous.210="%%leader%% has promoted %%player%% to party leader!" +mcp_miscellaneous.211="Successfully processed your Gift Pack purchase of:" +mcp_miscellaneous.212="Processed your purchase:" +mcp_miscellaneous.213="Invalid usage! Valid usage: /housing partywarp Player" +mcp_miscellaneous.214="You can only have %%count%% active invites simultaneously!" +mcp_miscellaneous.215="You can only send %%count%% unaccepted invites per %%mins%% minutes!" +mcp_miscellaneous.216="%red%%You have sent too many party invites and are banned from sending party invites until %%time%%" +mcp_miscellaneous.217="Found an in-progress %%game%% game! Teleporting you to %%server%%..." +mcp_miscellaneous.218="There are no in-progress games with room! Try joining a new game!" +mcp_miscellaneous.219="You've sent too many friend requests over the past %%time%% minutes! You'll have to wait %%lockout%% minutes before you can send anymore." +mcp_miscellaneous.220="You have reached the maximum of %%amount%% friends! To add more friends please remove some. If you wish to clear your friend list, please contact support." +mcp_miscellaneous.221="This player has reached the maximum of %%amount%% friends!" +mcp_miscellaneous.222="You can't play ranked %%gametype%% this season because of one or more punishments!" +mcp_miscellaneous.223="The lobby you were in is being rebooted, so you were sent to another lobby." +mcp_miscellaneous.224="%%mode%%" +mcp_miscellaneous.225="Available modes:" +mcp_miscellaneous.226="You haven't been invited to Duel, or the invitation has expired!" +mcp_miscellaneous.227="You cannot invite yourself to Duel!" +mcp_miscellaneous.228="You can't invite %%player%% to a Duel because they're not online!" +mcp_miscellaneous.229="You cannot invite this player to a Duel!" +mcp_miscellaneous.230=""%%mode%%" is not a valid Duels mode!" +mcp_miscellaneous.231="Duel Commands:" +mcp_miscellaneous.232="/duel <player> - Opens a GUI to invite a player to a Duel." +mcp_miscellaneous.233="/duel <player> <mode> - Invite a player to a Duel. Use /duel modes to see modes currently supported by the /duel command." +mcp_miscellaneous.234="/duel modes - List modes currently supported by the /duel command." +mcp_miscellaneous.235="/duel accept <player> - Accept a Duel invite from the player." +mcp_miscellaneous.236="Failed to start Duel. %%name%% and %%invited%% are in the same party!" +mcp_miscellaneous.237="Failed to start Duel. %%name%% is not in a party with enough members for %%mode%%!" +mcp_miscellaneous.238="Failed to start Duel. %%target%% is not in a party with enough members for %%mode%%!" +mcp_miscellaneous.239="You accepted %%player%%'s Duel request!" +mcp_miscellaneous.240="%%player%% accepted the Duel request!" +mcp_miscellaneous.241="An error occurred when warping to a game!" +mcp_miscellaneous.242="Cannot start Duel. %%player%% is offline!" +mcp_miscellaneous.243="Error when starting Duel. Invalid number of players found!" +mcp_miscellaneous.244="You cannot invite someone in the same party as you to %%mode%%!" +mcp_miscellaneous.245="You are not in a party with enough members for %%mode%%!" +mcp_miscellaneous.246="%%target%% is not in a party with enough members for %%mode%%!" +mcp_miscellaneous.247="You invited %%invitedplayer%%'s party to %%mode%%! They have 60 seconds to accept." +mcp_miscellaneous.248="You invited %%invitedplayer%% to %%mode%%! They have 60 seconds to accept." +mcp_miscellaneous.249="%%player%% has invited your party to %%mode%%!" +mcp_miscellaneous.250="%%player%% has invited you to %%mode%%!" +mcp_miscellaneous.251="CLICK HERE to accept! You have 60 seconds to accept." +mcp_miscellaneous.252="Click to run\n/duel accept %%player%%" +mcp_miscellaneous.253="Sends a request to Duel a player" +mcp_miscellaneous.254="Huh, we couldn't find a server by that name. Please contact a staff member for help." +mcp_miscellaneous.255="Could not find a server by that name." +mcp_miscellaneous.256="Could not find a player on that server." +mcp_miscellaneous.257="Sending you to %%server%% to teleport a random player!" +mcp_miscellaneous.258="I cannot do that right now, try again shortly." +mcp_miscellaneous.259="I had issues queueing you to that server." +mcp_miscellaneous.260="You cannot do this while in a party!" +mcp_miscellaneous.261="%%player%% is not in that game anymore." +mcp_miscellaneous.262="You may only use the short-handed invite with up to %%limit%% invites!" +mcp_miscellaneous.263="You do not have permissions for this channel!" +mcp_miscellaneous.264="------ No Ignored Users ------" +mcp_miscellaneous.265="The Duel request from %%sender%% has expired." +mcp_miscellaneous.266="The Duel request to %%sender%% has expired." +mcp_miscellaneous.267="Win Bonus" +mcp_miscellaneous.268="Toggles mute for the party" +mcp_miscellaneous.269="Create a party poll!" +mcp_miscellaneous.270="Remove all your friends" +mcp_miscellaneous.271="%%experience%% Battle Pass Experience" +mcp_miscellaneous.272="+%%earned%% %%reason%%" +mcp_miscellaneous.273="%%earned%% %%gameType%% Coin" +mcp_miscellaneous.274="%%earned%% %%gameType%% Coins" +mcp_miscellaneous.275="+%%coins%% Game Reward" +mcp_miscellaneous.276="+%%earned%% %%reason%%" +mcp_miscellaneous.277="%%experience%% Hypixel Experience" +mcp_miscellaneous.278="+%%earned%% %%reason%%" +mcp_miscellaneous.279="Play Time Bonus" +mcp_miscellaneous.280="You earned" +mcp_miscellaneous.281="Bow Duel" +mcp_miscellaneous.282="Bow Duels" +mcp_miscellaneous.283="Classic Duel" +mcp_miscellaneous.284="Classic Duels" +mcp_miscellaneous.285="UHC Duel" +mcp_miscellaneous.286="UHC Duels" +mcp_miscellaneous.287="UHC Doubles" +mcp_miscellaneous.288="UHC Teams" +mcp_miscellaneous.289="Mega Walls Duel" +mcp_miscellaneous.290="Mega Walls Duels" +mcp_miscellaneous.291="Mega Walls Doubles" +mcp_miscellaneous.292="Sumo Duel" +mcp_miscellaneous.293="Sumo Duels" +mcp_miscellaneous.294="SkyWars Duel" +mcp_miscellaneous.295="SkyWars Duels" +mcp_miscellaneous.296="SkyWars Doubles" +mcp_miscellaneous.297="Combo Duel" +mcp_miscellaneous.298="Combo Duels" +mcp_miscellaneous.299="Nodebuff Duel" +mcp_miscellaneous.300="Nodebuff Duels" +mcp_miscellaneous.301="Op Duel" +mcp_miscellaneous.302="Op Duels" +mcp_miscellaneous.303="Op Doubles" +mcp_miscellaneous.304="Blitz Duel" +mcp_miscellaneous.305="Blitz Duels" +mcp_miscellaneous.306="Bow Spleef Duel" +mcp_miscellaneous.307="Bow Spleef Duels" +mcp_miscellaneous.308="There are no servers that have enough room for a party right now! Try again in a moment! (2)" +mcp_miscellaneous.309="You summoned your empty party to your server. :(" +mcp_miscellaneous.310="You summoned %%warped%% to your server." +mcp_miscellaneous.311="one player" +mcp_miscellaneous.312="You summoned your Party of %%warped%% to your server." +mcp_miscellaneous.313="You must be %%rank%%rank to use this command!" +mcp_miscellaneous.314="question/answer/answer[/answer]" +mcp_miscellaneous.315="Invited %%players%% to your party!" +mcp_miscellaneous.316="Click here to join or type /party accept %%player%%!\n" +mcp_miscellaneous.317="Friend > %%player%% left." +mcp_miscellaneous.318="Friend > %%player%% joined." +mcp_miscellaneous.319="HYPIXEL NETWORK" +mcp_miscellaneous.320="Click to select a help option..." +mcp_miscellaneous.321="Click to select!" +mcp_miscellaneous.322="* Found a server issue/bug" +mcp_miscellaneous.323="* Report rule breakers" +mcp_miscellaneous.324="* Ask a payment question" +mcp_miscellaneous.325="Need more help? Visit" +mcp_miscellaneous.326="our forums" +mcp_miscellaneous.327="You currently have a Hypixel Competitive ban and are unable to play in the %%name%% Tournament!" +mcp_miscellaneous.328="Due to a party member currently having a Hypixel Competitive ban you are unable to queue with this party for the %%name%% Tournament!" +mcp_miscellaneous.329="From: %%from%%" +mcp_miscellaneous.330="To: %%to%%" +mcp_miscellaneous.331="This game is not supported in Minecraft %%version%% or later!" +mcp_miscellaneous.332="You need at least Hypixel Level %%required%% to play %%gametype%%!" +mcp_miscellaneous.333="Your Hypixel Level increases as you gain xp through quests, challenges, and completing games. Your level can be seen on your xp bar in lobbies." +mcp_miscellaneous.334="You need at least Hypixel Level %%required%% to play in the %%name%% Tournament!" +mcp_miscellaneous.335="Generosity\nPlaying in a game where at least\none player has Generosity grants\neveryone a bag of Hypixel Experience\nat the end of the game.\n\nOpening a gift sent by your friends\ngrants Generosity." +mcp_miscellaneous.336="There are no servers running that map right now! Try again later!" +mcp_miscellaneous.337="Only the party leader can warp you into a game! Have them click an NPC or use /party leave" +mcp_miscellaneous.338="You can't start a private game with only yourself in the party!" +mcp_miscellaneous.339="Your party is too large to play %%gameType%%: %%map%%! Max of 3 players per party!" +mcp_miscellaneous.340="Your party is too large to play %%gameType%%: %%map%%! Max of 5 players per party!" +mcp_miscellaneous.341="You must have exactly 2 people in the party to play this!" +mcp_miscellaneous.342="You must have at least 2 people in the party to play this!" +mcp_miscellaneous.343="Your party is too large to play this map! Try a different map!" +mcp_miscellaneous.344="Sorry, we couldn't find any servers with enough room for %%game%%: %%map%%! Try again in a few minutes!" +mcp_miscellaneous.345="Couldn't find a server available! Try again in a moment!" +mcp_miscellaneous.346="Sending to server %%server%%..." +mcp_miscellaneous.347="That player's house is full! Try another house!" +mcp_miscellaneous.348="Incorrect password! Try again!" +mcp_miscellaneous.349="NOTE! %%player%% is offline in your party!" +mcp_miscellaneous.350="SORRY! Couldn't find a server!" +mcp_miscellaneous.351="SORRY! Couldn't fit you in a world on server " +mcp_miscellaneous.352="SERVER FOUND! Sending to %%server%%!" +mcp_miscellaneous.353="SERVER FOUND! Sending to %%server%% (your party is there)!" +mcp_miscellaneous.354="OOPS! Cannot join The Pit from here!" +mcp_miscellaneous.355="EEK! Are you trying to teleport to the same pit server?" +mcp_miscellaneous.356="ERROR! Couldn't find the server you're trying to connect to!" +mcp_miscellaneous.357="CONFUSED? The pit server you're trying to join doesn't seem to be a pit server!" +mcp_miscellaneous.358="COULDN'T JOIN! because you left the pit too recently!" +mcp_miscellaneous.359="JOIN REFUSED! %%reason%%" +mcp_miscellaneous.360="ERROR! while transferring you to this server! (1)" +mcp_miscellaneous.361="OOF! Didn't transfer you because you're in combat!" +mcp_miscellaneous.362="ERROR! Couldn't properly transfer off of your current pit server!" +mcp_miscellaneous.363="ERROR! while transferring you to this server! (2)" +mcp_miscellaneous.364="Your party can't queue for : because isn't online!" +mcp_miscellaneous.365="Your party can't queue for : because doesn't have permission to join that server!" +mcp_miscellaneous.366="Only the party leader can warp you into a game! Have them click an NPC or /party leave" +mcp_miscellaneous.367="Failed to find a random house. Try again later!" +mcp_miscellaneous.368="The party leader, %%leader%%, warped you to their house." +mcp_miscellaneous.369="Go Back" +mcp_miscellaneous.370="our forums" +mcp_miscellaneous.371="Hypixel Minigames" +mcp_miscellaneous.372="Found a Server Bug/Issue" +mcp_miscellaneous.373="Report a Rule Breaker" +mcp_miscellaneous.374="Report a player" +mcp_miscellaneous.375="Further information here" +mcp_miscellaneous.376="Store" +mcp_miscellaneous.377="Support" +mcp_miscellaneous.378="Allowed Modifications" +mcp_miscellaneous.379="Hypixel Rules & Policies" +mcp_miscellaneous.380="General Gameplay/Server" +mcp_miscellaneous.381="General Gameplay" +mcp_miscellaneous.382="Rank Information" +mcp_miscellaneous.383="Creator Program" +mcp_miscellaneous.384="Linking your Minecraft account" +mcp_miscellaneous.385="Link and join our Discord" +mcp_miscellaneous.386="Link your account to the forums" +mcp_miscellaneous.387="You can only do this during Halloween!" +mcp_miscellaneous.388="Cannot join a game in progress while in a party." +mcp_miscellaneous.389="Invalid usage! Valid usage: /friend list (Page/Best)" +mcp_miscellaneous.390="Please provide a status to set!" +mcp_miscellaneous.391="Valid options: %%options%%" +mcp_miscellaneous.392="Invalid status, valid options: %%options%%" +mcp_miscellaneous.393="Your online status has been set to %%status%%" +mcp_miscellaneous.394="You are not muted! This command is intended to be used to notify players when you are muted!" +mcp_miscellaneous.395="Woah there, slow down!" +mcp_miscellaneous.396="Set a nickname of a friend" +mcp_miscellaneous.397="%%name%% now has the nickname %%nick%%!" +mcp_miscellaneous.398="%%name%% no longer has a nickname!" +mcp_miscellaneous.399="%%player_name%% isn't on your friends list!" +mcp_miscellaneous.400="A nickname cannot be longer than 16 characters!" +mcp_miscellaneous.401="Toggle a player as best friend" +mcp_miscellaneous.402="%%name%% is no longer a best friend!" +mcp_miscellaneous.403="%%name%% is now a best friend!" +mcp_miscellaneous.404="Only the party leader can do this!" +mcp_miscellaneous.405="The Tournament Hall is currently closed!" +mcp_miscellaneous.406="Hypixel SkyBlock Rules can be found at %%url%%" +mcp_miscellaneous.407="Hypixel Server Rules can be found at %%url%%" +mcp_miscellaneous.408="No such lobby." +mcp_miscellaneous.409="That lobby isn't available right now, please try again later!" +mcp_miscellaneous.410="Click here to link your forums account!" +mcp_miscellaneous.411="Offline" +mcp_miscellaneous.412="Party Leader, %%player%%, summoned you to their server." +mcp_miscellaneous.413="The party leader, %%leader%%, summoned you to SkyBlock, but you cannot join the game from Limbo." +mcp_miscellaneous.414="✖ %%player%% is offline" +mcp_miscellaneous.415="✖ %%player%% cannot warp from Limbo" +mcp_miscellaneous.416="✖ %%player%% is unable to play" +mcp_miscellaneous.417="✖ %%player%% is unable to join because the game is full!" +mcp_miscellaneous.418="✖ %%player%% is unable to join because they are using an unsupported Minecraft version!" +mcp_miscellaneous.419="⚔ %%player%% warped to your dungeon" +mcp_miscellaneous.420="✔ %%player%% warped to your server" +mcp_miscellaneous.421="✖ %%player%% is not allowed on your server!" +mcp_miscellaneous.422="✮ %%player%% is on your server" +mcp_miscellaneous.423="✖ There was an error warping %%player%%!" +mcp_miscellaneous.424="➜ %%player%% warped to SkyBlock" +mcp_miscellaneous.425="✖ %%player%% didn't warp correctly!" +mcp_miscellaneous.426="Warping party..." +mcp_miscellaneous.427="An error occurred while warping the party!" +mcp_miscellaneous.428="SkyBlock Dungeon Warp (%%players%% player)" +mcp_miscellaneous.429="SkyBlock Dungeon Warp (%%players%% players)" +mcp_miscellaneous.430="SkyBlock Party Warp (%%players%% player)" +mcp_miscellaneous.431="SkyBlock Party Warp (%%players%% players)" +mcp_miscellaneous.432="Moving you to %%server%%" +mcp_miscellaneous.433="REMINDER: Your Online Status is currently set to %%status%%" +mcp_miscellaneous.434="%%color%%%%experience%% Event Experience" +mcp_miscellaneous.435="%%color%%+%%earned%% %%reason%%" +mcp_miscellaneous.436="You cannot request to teleport to yourself!" +mcp_miscellaneous.437="You've already requested to teleport to someone! Wait for them to accept!" +mcp_miscellaneous.438="You requested to teleport to %%player%%! They have 30 seconds to accept." +mcp_miscellaneous.439="%%player%% has requested to teleport to you!" +mcp_miscellaneous.440="Click here to accept!" +mcp_miscellaneous.441="Click to teleport %%player%% to you!" +mcp_miscellaneous.442="GUILD" +mcp_miscellaneous.443="OFFICER" +mcp_miscellaneous.444="You must be in SkyBlock to join this channel!" +mcp_miscellaneous.445="You can't play %%gametype%% %%mode%% due to previous infractions.\nRead more about competitive game bans here: %%url%%" +mcp_miscellaneous.446="You can't play %%gametype%% due to previous infractions.\nRead more about competitive game bans here: %%url%%" +mcp_miscellaneous.447="You can't play %%gametype%% %%mode%% due to a previous infraction. Your competitive ban will be lifted on %%time%%.\nRead more about competitive game bans here: %%url%%" +mcp_miscellaneous.448="You can't play %%gametype%% due to a previous infraction. Your competitive ban will be lifted on %%time%%.\nRead more about competitive game bans here: %%url%%" +mcp_miscellaneous.449="You can't play %%gametype%% %%mode%% right now!" +mcp_miscellaneous.450="Prints all available friend commands." +mcp_miscellaneous.451="Toggle friend join/leave notifications" +mcp_miscellaneous.452="You're about to remove ALL of your friends (excluding best friends). Are you sure you want to do this?" +mcp_miscellaneous.453="Click to clear your friends list. (This does not remove your best friends.)" +mcp_miscellaneous.454="You have no friends to remove. This command does not remove best friends." +mcp_miscellaneous.455="This command can only be used when having a large friends list. This command does not remove best friends." +mcp_miscellaneous.456="Remove all your friends (excluding best friends)" +mcp_miscellaneous.457="Network Booster Queue" +mcp_miscellaneous.458="No Network Boosters queued." +mcp_miscellaneous.459="by" +mcp_miscellaneous.460="Stacked Boosters" +mcp_miscellaneous.461="and 1 other" +mcp_miscellaneous.462="and %%amount%% others" +mcp_miscellaneous.463="1 more booster queued." +mcp_miscellaneous.464="%%amount%% more boosters queued." +mcp_miscellaneous.465="SKYBLOCK CO-OP" +mcp_miscellaneous.466="Your party must have %%number%% players to play : !" +mcp_miscellaneous.467="Your party must have at least %%number%% players to play : !" +mcp_miscellaneous.468="You cannot be in a party to play : !" +mcp_miscellaneous.469="Your party is too large to play : !\nThe maximum party size for this mode is players." +mcp_miscellaneous.470="You need to be in a party of %%number%% players to play %%gameType%%: %%mode%%!" +mcp_miscellaneous.471="You need to be in a party of at least %%number%% players to play %%gameType%%: %%mode%%!" +mcp_miscellaneous.472="This mode doesn't support private games! Turn off private game mode before joining!" +mcp_miscellaneous.473="You are banned from that house!" +mcp_miscellaneous.474="Oops! Something wrong happened. Try again later." +mcp_miscellaneous.475="There isn't enough room in this house for your whole party!" +mcp_miscellaneous.476="You can't visit that house because of their visiting rules!" +mcp_miscellaneous.477="You can't visit that house because their house is set to private!" +mcp_miscellaneous.478="That house has a password protecting it! Make sure you are in a lobby!" +mcp_miscellaneous.479="That house is full! Try another house!" +mcp_miscellaneous.480=" Friends (Page %%page%% of %%max_page%%) " +mcp_miscellaneous.481=" Best Friends (Page %%page%% of %%max_page%%) " +mcp_miscellaneous.482="Click here to view %%player%%'s profile" +mcp_miscellaneous.483="%%player%% is currently offline" +mcp_miscellaneous.484="%%player%% is currently %%color%%Away" +mcp_miscellaneous.485="%%player%% is currently %%color%%Busy" +mcp_miscellaneous.486="%%player%% is currently %%color%%%%status%%" +mcp_miscellaneous.487="%%player%% is in Limbo" +mcp_miscellaneous.488="%%player%% is in the Main Lobby" +mcp_miscellaneous.489="%%player%% is in the Tournament Hall" +mcp_miscellaneous.490="%%player%% is %%presence%%" +mcp_miscellaneous.491="%%player%% is in an %%lobby%% Lobby" +mcp_miscellaneous.492="%%player%% is in a %%lobby%% Lobby" +mcp_miscellaneous.493="%%player%% is in an unknown realm" +mcp_miscellaneous.494="%%player%% is playing SMP" +mcp_miscellaneous.495="%%player%% is somewhere" +mcp_miscellaneous.496="%%player%% is in the house %%name%%" +mcp_miscellaneous.497="%%player%% is in Housing" +mcp_miscellaneous.498="%%player%% is in The Hypixel Pit" +mcp_miscellaneous.499="%%player%% is in SkyBlock - %%island%%" +mcp_miscellaneous.500="%%player%% is in SkyBlock" +mcp_miscellaneous.501="%%player%% is watching a replay" +mcp_miscellaneous.502="%%player%% is in an %%game%% Game" +mcp_miscellaneous.503="%%player%% is in a %%game%% Game" +mcp_miscellaneous.504="Last seen %%duration%% ago" +mcp_miscellaneous.505="Friends for %%duration%%" +mcp_miscellaneous.506="That player blocked you!" +mcp_miscellaneous.507="That player is not online!" +mcp_miscellaneous.508="This command is currently unavailable." +mcp_miscellaneous.509="There are no pending voicemails for you. Some voicemails might have expired by now." +mcp_miscellaneous.510="You're all caught up, no more pending voicemails!" +mcp_miscellaneous.511="There are no pending voicemails for you." +mcp_miscellaneous.512="Invalid usage! '/friend %%command%%'" +mcp_miscellaneous.513="You have left too many %%game%% games early!" +mcp_miscellaneous.514="You are blocked from joining a new game for 1 minute." +mcp_miscellaneous.515="You are blocked from joining a new game for %%minutes%% minutes." +mcp_miscellaneous.516="A member of your party has left too many %%game%% games early!" +mcp_miscellaneous.517="You are temporarily blocked from joining a new game for 1 minute." +mcp_miscellaneous.518="You are temporarily blocked from joining a new game for %%minutes%% minutes." \ No newline at end of file diff --git a/configuration/i18n/en_US/official/prototype_lobby.properties b/configuration/i18n/en_US/official/prototype_lobby.properties new file mode 100644 index 000000000..819e82287 --- /dev/null +++ b/configuration/i18n/en_US/official/prototype_lobby.properties @@ -0,0 +1,29 @@ +prototype_lobby.hype="Hype" +prototype_lobby.1="Hype: %%hype%%/%%maxHype%%" +prototype_lobby.2="Hype is used to show how hyped you are for Prototype games. Earn Hype by playing Prototype Lobby minigames!" +prototype_lobby.3="Add Hype to %%game%%" +prototype_lobby.4="Click to add Hype to %%game%%!" +prototype_lobby.5="Hype" +prototype_lobby.6="Hype %%game%%" +prototype_lobby.7="Adds all of your Hype to %%game%%." +prototype_lobby.8="Adds %%hype%% Hype to %%game%%." +prototype_lobby.9="Click to Hype!" +prototype_lobby.10="Give All Hype" +prototype_lobby.11="%%hype%% Hype" +prototype_lobby.12="You added %%hype%% Hype to %%game%%!" +prototype_lobby.13="You don't have any Hype. Earn Hype by playing Prototype Lobby minigames!" +prototype_lobby.14="You don't have enough Hype. Earn Hype by playing Prototype Lobby minigames!" +prototype_lobby.15="This lobby is currently closed." +prototype_lobby.16=" You have reached your Hype limit! Add Hype to Prototype Lobby minigames by right-clicking with the Hype Diamond!" +prototype_lobby.17="MAX HYPE" +prototype_lobby.18="Hype Meter" +prototype_lobby.19="CLICK FOR INFO" +prototype_lobby.20="RELEASED" +prototype_lobby.21="Hype: %%hype%%/%%maxHype%%" +prototype_lobby.22="Welcome to the Prototype Lobby" +prototype_lobby.23="All games in this lobby are currently in development." +prototype_lobby.24="Click here to leave feedback!" +prototype_lobby.25="Hype Diamond (Right Click)" +prototype_lobby.26="Games in this lobby are under heavy development!" +prototype_lobby.27="Report bugs and leave feedback at hypixel.net/ptl" +prototype_lobby.28="This game is confirmed for release, no hype needed!" \ No newline at end of file diff --git a/configuration/i18n/en_US/official/replays.properties b/configuration/i18n/en_US/official/replays.properties new file mode 100644 index 000000000..4486f5b31 --- /dev/null +++ b/configuration/i18n/en_US/official/replays.properties @@ -0,0 +1,123 @@ +replays.0="You are already viewing that replay!" +replays.1="Ran by %%player%%" +replays.2="Cinematic Cameras (BETA)" +replays.3="Click to report!" +replays.4="Play Recording Again" +replays.5="Left Click to go to this time!" +replays.6="You can't decrease the speed any lower!" +replays.7="Report %%name%%" +replays.8="This replay is too short to render a timeline" +replays.9="%%value%%s Backwards" +replays.10="%%name%% disabled!" +replays.11="No replayer found?!" +replays.12="Click to leave!" +replays.13="You can't increase the speed any higher!" +replays.14="Click to read more about the Replay Viewer" +replays.15="Teleport to Player" +replays.16="Manage your settings for viewing replays." +replays.17="Settings" +replays.18="you" +replays.19="Replay Viewer" +replays.20="%%value%%s Forward" +replays.21="Click to put in chat!" +replays.22="Click to Stop" +replays.23="More" +replays.24="The Replay you were in has been shut down!" +replays.25="Currently Selected: %%option%%" +replays.26="You can't report yourself!" +replays.27="Click here to put share command in chat!" +replays.28="Click to Resume" +replays.29="Click to share!" +replays.30="Report Player" +replays.31="You were kicked for inactivity! " +replays.32="That player has despawned!" +replays.33="Usage: /tp [target player]" +replays.34="Click to Pause" +replays.35="Time: %%time%% seconds" +replays.36="You cannot share this replay!" +replays.37="Unable to submit the report right now, please try again shortly!" +replays.38="Viewer Settings" +replays.39="This instance doesn't have a replay for you. If this keeps happening please report this." +replays.40="Report this player for %%type%%." +replays.41="You will be afk-ed in 10 seconds!" +replays.42="No bookmarks!" +replays.43="View bookmarks for this recording." +replays.44="No bookmarks found!" +replays.45="Left Click to teleport!" +replays.46="You were kicked due to having a replay open for too long! " +replays.47="Hypixel Replay Viewer" +replays.48=" READ MORE" +replays.49="Share this replay along with your current timestamp and location." +replays.50="Reporting via replays is currently disabled, please try again later!" +replays.51="You do not have permission to watch replays." +replays.52="No players found!" +replays.53="Decrease Speed" +replays.54="Hypixel Replay is in BETA! Please report bugs at https://hypixel.net/bugs" +replays.55="Right Click to share!" +replays.56="%%player%% ran command /%%command%%" +replays.57="Right Click for first person!" +replays.58="Bookmarks" +replays.59="Thank you for your report against %%name%%! This replay will be submitted along with the report." +replays.60="Click to set %%setting%% to %%option%%" +replays.61="Player: %%player%%" +replays.62="No replayer!" +replays.63="Bookmark created!" +replays.64="Please wait a little before using that!" +replays.65="You went too far away from the map!" +replays.66="Share" +replays.67="You have been kicked as the replay was open for too long!" +replays.68="Increase Speed" +replays.69="Teleporting %%name%% to %%destination%%" +replays.70="%%color%%%%name%%" +replays.71="Leave Replay" +replays.72="%%name%% enabled!" +replays.73="No replayer?!" +replays.74="I don't know where you want to teleport to!" +replays.75="You cannot create bookmarks for this replay!" +replays.76="Report this player for breaking the rules. This replay will be saved along with the report to be reviewed." +replays.77="Waiting" +replays.78="Playing" +replays.79="Paused" +replays.80="Finished" +replays.81="You have hit the limit of active highlights! Please try again another time!" +replays.82="Highlight submitted!" +replays.83="Submit Highlight" +replays.84="Did something cool? Share your current timestamp and location with us for a chance to be showcased on Hypixel social media!" +replays.85="By submitting this highlight, you agree to the Hypixel Server potentially using this content on the Hypixel Twitter, TikTok, Instagram, or other social media platform. Make sure you are in the right location and time to showcase your highlight!" +replays.86="Click to submit!" +replays.87="Left click to change the duration." +replays.88="Date: " +replays.89="Time: " +replays.90="Failed to do that, please try again shortly.!" +replays.91="Loading replay ..." +replays.92="Map: " +replays.93="Game: " +replays.94="You need to be playing Minecraft with protocol version %%version%% or higher to view this replay." +replays.95="The replay is currently paused." +replays.96="Longest Tick: " +replays.97="The replay is currently stopped." +replays.98="Middle Click to put UUID in chat!" +replays.99="Submit Verdict" +replays.100="Replay" +replays.101="You need to be playing Minecraft version %%version%% or higher to view this replay." +replays.102="Detection: %%detection%%" +replays.103="Mode: " +replays.104="Found bookmark matching player... skipping to %%ticks%% ticks!" +replays.105="Players" +replays.106="Replay from " +replays.107="Chat Messages" +replays.108="Toggle chat messages such as kills and other actions in the game." +replays.109="Chat Timeline" +replays.110="Toggle a timeline of the replay which is displayed via the chat." +replays.111="Show Spectators" +replays.112="Toggle the ability to see spectators from the replay." +replays.113="Night Vision" +replays.114="Toggle having night vision when watching a replay." +replays.115="Fly Speed" +replays.116="Skip Intervals" +replays.117="Food Level: %%level%%" +replays.118="Show Particles" +replays.119="Toggle showing particles when watching a replay." +replays.120="Change the speed you fly at in the replay." +replays.121="Change the interval used when using the forward & backward buttons. Can also be toggled by left clicking the buttons themselves." +replays.122="Toggle the time on the scoreboard advancing while the replay is being played." \ No newline at end of file diff --git a/configuration/i18n/en_US/official/social_menu.properties b/configuration/i18n/en_US/official/social_menu.properties new file mode 100644 index 000000000..2f7a111a1 --- /dev/null +++ b/configuration/i18n/en_US/official/social_menu.properties @@ -0,0 +1,246 @@ +social_menu.0="The guild master is responsible for moderating the guild chat." +social_menu.1="Recommended:" +social_menu.2="Kick from guild" +social_menu.3="Leave guild" +social_menu.4="Click to kick the player from your guild." +social_menu.5="Click to leave the guild you are in." +social_menu.6="Click to cancel." +social_menu.7="The party leader is responsible for moderating the party chat." +social_menu.8="Kick from party" +social_menu.9="Leave party" +social_menu.10="Click to kick the player from your party." +social_menu.11="Click to leave the party you are in." +social_menu.12="If a player is harassing you in private messages, we suggest removing them from your friends list." +social_menu.13="Unfriend & ignore" +social_menu.14="Click to unfriend this player and add them to your ignore list." +social_menu.15="Remove friend" +social_menu.16="Click to unfriend this player." +social_menu.17="REPORT" +social_menu.18="Social Dashboard" +social_menu.19="Remove Friend" +social_menu.20="Click here to remove %%player%% from your friends list." +social_menu.21="Add Friend" +social_menu.22="Click here to send %%player%% a friend request." +social_menu.23="Only Officers and the Guild Master can do this." +social_menu.24="Only the Guild Master can do this." +social_menu.25="This player isn't in your guild." +social_menu.26="You must be in a guild to do this." +social_menu.27="Kick from guild" +social_menu.28="Click here to remove %%player%% from your guild." +social_menu.29="Invite to guild" +social_menu.30="Click here to invite %%player%% to your guild." +social_menu.31="Enter reason" +social_menu.32="You can't invite %%player%% to your guild because they are already in a guild." +social_menu.33="Demote to Member" +social_menu.34="Click here to demote %%player%% to Member in your guild." +social_menu.35="Promote to Officer" +social_menu.36="Click here to promote %%player%% to Officer in your guild." +social_menu.37="You can't use this because you're not in a guild." +social_menu.38="You can't use this because %%player%% isn't in your guild." +social_menu.39="Unignore Player" +social_menu.40="Click here to remove %%player%% from your ignore list." +social_menu.41="Ignore Player" +social_menu.42="Click here to add %%player%% to your ignore list." +social_menu.43="Kick from Party" +social_menu.44="Click here to remove %%player%% from your party." +social_menu.45="Invite to Party" +social_menu.46="Click here to invite %%player%% to a party." +social_menu.47="Only the party leader can kick players from the party." +social_menu.48="Promote to Party Leader" +social_menu.49="Click here to promote %%player%% to Party Leader." +social_menu.50="You can't use this because %%player%% isn't in your party." +social_menu.51="You must be the Party Leader to use this." +social_menu.52="You must be in a party to use this." +social_menu.53="Close" +social_menu.54="None" +social_menu.55="Current: %%value%%" +social_menu.56="Left-click to change!" +social_menu.57="Right-click to remove!" +social_menu.58="Anybody can see your linked social media accounts!" +social_menu.59="Paste your Discord username or invite link in chat:" +social_menu.60="Paste your %%socialMedia%% link in chat:" +social_menu.61=" > %%name%%'s Discord Username is %%username%% <" +social_menu.62=" > Click here to visit %%name%%'s %%socialMedia%%! < " +social_menu.63="This %%socialMedia%% page isn't managed by us, so we cannot guarantee it is appropriate. Open the page at your own discretion." +social_menu.64="Your %%socialMedia%% link has been set to %%url%%!" +social_menu.65="The URL %%url%% isn't valid!" +social_menu.66="Currently ON" +social_menu.67="Currently OFF" +social_menu.68="Chat Report" +social_menu.69="Click here to report %%name%% for chat-related offenses." +social_menu.70="Where did %%name%% break the rules?" +social_menu.71="> Public Chat" +social_menu.72="> Private Messages" +social_menu.73="> Party Chat" +social_menu.74="> Guild Chat" +social_menu.75="Cheating Report" +social_menu.76="Click here to report %%name%% for cheating in games." +social_menu.77="Guild Settings" +social_menu.78="Joinable" +social_menu.79="Change various guild-related settings, such as preferences and guild-wide options." +social_menu.80="Whether or not players can request to join the guild." +social_menu.81="Notifications" +social_menu.82="Whether or not you see join and leave messages of guildmates." +social_menu.83="Guild Settings" +social_menu.84="Edit Guild Tag" +social_menu.85="Changes the tag next to your guild members' names." +social_menu.86="You aren't in a guild!" +social_menu.87="Only the Guild Master can change this!" +social_menu.88="Enter your\nguild tag!" +social_menu.89="Social Media" +social_menu.90="Click to edit your Social Media links." +social_menu.91="Click to view %%player%%'s Social Media links." +social_menu.92="Social Media" +social_menu.93="No Social Media" +social_menu.94="%%player%% has not linked any Social Media accounts." +social_menu.95="Bummer! No friends :(" +social_menu.96="You can add friends with the 'Add Friend' book in the top right, or via /friend add PlayerName!" +social_menu.97="Friends" +social_menu.98="View your Hypixel friends' profiles, and interact with your online friends!" +social_menu.99="Click to add a friend to your friend list." +social_menu.100="Friends can see what each other are doing on the network, and can see which each other are online." +social_menu.101="Enter username" +social_menu.102="Click to remove a current friend from your friend list." +social_menu.103="Guild" +social_menu.104="Form a guild with other Hypixel players to conquer game modes and work towards common Hypixel rewards." +social_menu.105="Invite Player" +social_menu.106="Remove Player" +social_menu.107="Guild Rank: %%rank%%" +social_menu.108="Member since: %%time%%" +social_menu.109="Member" +social_menu.110="Officer" +social_menu.111="%%time%% ago" +social_menu.112="Create Guild" +social_menu.113="You aren't in a guild" +social_menu.114="Click here to create your own guild!" +social_menu.115="Only players with VIP+ or higher can create guilds, but anybody can join them." +social_menu.116="Click to browse guilds on our website!" +social_menu.117="Enter Guild name" +social_menu.118="Click to view Guilds on the Hypixel Forums" +social_menu.119="Click to visit the forums" +social_menu.120="View Profile" +social_menu.121="Shows information about your profile." +social_menu.122="Party" +social_menu.123="Create a party and join up with other players to play games together!" +social_menu.124="Warp Party" +social_menu.125="Invites a player to your party." +social_menu.126="Removes a player from your party." +social_menu.127="Teleports all party members to your lobby." +social_menu.128="Disband Party" +social_menu.129="Breaks up the current party." +social_menu.130="Leave Party" +social_menu.131="Leaves the current party." +social_menu.132="Go to Housing" +social_menu.133="Visit Housing" +social_menu.134="Shows information about %%player%%." +social_menu.135="Recent Players" +social_menu.136="Clear Recent Players" +social_menu.137="Clears your recent players list." +social_menu.138="No Recent Players Found" +social_menu.139="Try playing some games on the network, and come back here to see who you've played with!" +social_menu.140="Recent Players" +social_menu.141="View players you have played recent games with." +social_menu.142="Error loading skull" +social_menu.143="Met playing: %%game%%" +social_menu.144="Hypixel Level: %%level%%" +social_menu.145="Guild: %%guild%%" +social_menu.146="None" +social_menu.147="Online Status: %%status%%" +social_menu.148="Online" +social_menu.149="%%game%% Lobby %%number%%" +social_menu.150="Main Lobby %%number%%" +social_menu.151="Server: %%server%%" +social_menu.152="Game: %%game%%" +social_menu.153="Last Online: %%time%%" +social_menu.154="An error occurred, please try again in a moment." +social_menu.155="There was an issue loading the data you asked for. Please try again." +social_menu.156="No results" +social_menu.157="There were no matches for '%%query%%'!" +social_menu.158="LEFT CLICK to go to the previous page" +social_menu.159="RIGHT CLICK to go to the first page" +social_menu.160="Page %%current%%/%%total%%" +social_menu.161="LEFT CLICK to go to the next page" +social_menu.162="RIGHT CLICK to go to the last page" +social_menu.163="%%name%%: %%description%%" +social_menu.164="Alphabetical" +social_menu.165="Show everyone listed from A-Z" +social_menu.166="Last Online" +social_menu.167="Show everyone in the order they were last online" +social_menu.168="Last Met" +social_menu.169="Show everyone in the order in which you met them" +social_menu.170="Alphabetical order, but show online players first" +social_menu.171="Guild Rank order then Alphabetical order then Online status" +social_menu.172="Sort by Guild Rank, then alphabetically" +social_menu.173="LEFT CLICK to change between all the available sorting options." +social_menu.174="RIGHT CLICK to reverse the current order!" +social_menu.175="Change sort" +social_menu.176="Current sort: %%sort%%" +social_menu.177="Sorting order: %%order%%" +social_menu.178="Search Players" +social_menu.179="Clear Search Results" +social_menu.180="Report Player" +social_menu.181="Create Party" +social_menu.182="Click to invite a player to your party" +social_menu.183="You can only use the Social Menu in lobbies!" +social_menu.184="Invalid usage!" +social_menu.185="Please note: Although you're able to link your social media in your profile, it is against the rules to advertise it to other players in chat." +social_menu.186="Breaking this rule will result in a mute or a ban." +social_menu.187="VIEW RULES" +social_menu.188="https://hypixel.net/rules" +social_menu.189="I UNDERSTAND" +social_menu.190="second" +social_menu.191="seconds" +social_menu.192="minute" +social_menu.193="minutes" +social_menu.194="hours" +social_menu.195="days" +social_menu.196="Click here to see player options for %%player%%" +social_menu.197="N/A" +social_menu.198="Click to view %%who%%'s profile!" +social_menu.199="Click here to invite a player to your Guild." +social_menu.200="Edit settings such as your tag, permissions and guild finder options" +social_menu.201="Guild Tag" +social_menu.202="Unlocked by leveling up the Guild!" +social_menu.203="Changes the color of the tag next to your guild members' names." +social_menu.204="Click to view available colors!" +social_menu.205="Shown in Guild Finder" +social_menu.206="Guild Games" +social_menu.207="Click to pick games!" +social_menu.208="Changes the Guild's list of games used in the Guild Finder." +social_menu.209="Guild Finder" +social_menu.210="Search Guilds" +social_menu.211="You can browse Guilds on the Hypixel Forums to find a Guild to join." +social_menu.212="Click to view" +social_menu.213="Guild Master: " +social_menu.214="Members: " +social_menu.215="Guild Level: " +social_menu.216="Games: " +social_menu.217="none" +social_menu.218="Click to request to join" +social_menu.219="You're already in this guild" +social_menu.220="To request to join, you must first leave your current guild" +social_menu.221="Find a Guild you can join based on your favorite games" +social_menu.222="Sorts by who was online most recently" +social_menu.223="Shows highest Guild Rank first" +social_menu.224="How long they've been in the guild" +social_menu.225="Sort by Achievement Points" +social_menu.226="Sort by Hypixel Level" +social_menu.227="You don't have the correct permissions" +social_menu.228="Report %%player%%" +social_menu.229="Send Duel Request" +social_menu.230="Lacking permission to edit this!" +social_menu.231="%%game%% Lobby" +social_menu.232="Sorts by who was most recently online" +social_menu.233="Demote to lower rank" +social_menu.234="Click here to demote %%player%% to a lower guild rank." +social_menu.235="Promote to higher rank" +social_menu.236="Click here to promote %%player%% to a higher guild rank." +social_menu.237="Promote to lower guild rank" +social_menu.238="Promote to higher guild rank" +social_menu.239="Promote Party Role" +social_menu.240="Click here to promote %%player%% in your party." +social_menu.241="Click to show social options for %%who%%" +social_menu.242="Party Commands:\n" +social_menu.243="Ender Tier" +social_menu.244="Dark Ender Tier" +social_menu.245="Players ranked MVP or higher\ncan use /stats (username) to view\nother players' stats." \ No newline at end of file diff --git a/configuration/i18n/en_US/official/toolbox_miscellaneous.properties b/configuration/i18n/en_US/official/toolbox_miscellaneous.properties new file mode 100644 index 000000000..65b237ba6 --- /dev/null +++ b/configuration/i18n/en_US/official/toolbox_miscellaneous.properties @@ -0,0 +1,27 @@ +toolbox_miscellaneous.0="Penguin Companion" +toolbox_miscellaneous.1="Turtle Companion" +toolbox_miscellaneous.2="Gifterino Companion" +toolbox_miscellaneous.3="Black Pug Companion" +toolbox_miscellaneous.4="Duck Companion" +toolbox_miscellaneous.5="Frog Companion" +toolbox_miscellaneous.6="Sloth Companion" +toolbox_miscellaneous.7="Hp8 Companion" +toolbox_miscellaneous.8="White Pug Companion" +toolbox_miscellaneous.9="Shibe Companion" +toolbox_miscellaneous.10="Chimp Companion" +toolbox_miscellaneous.11="Panda Companion" +toolbox_miscellaneous.12="Elephant Companion" +toolbox_miscellaneous.13="Jack Dog Companion" +toolbox_miscellaneous.14="%%count%% Loot Chests" +toolbox_miscellaneous.15="%%days%% of %%rank%%" +toolbox_miscellaneous.16="%%count%% Bed Wars Loot Chests" +toolbox_miscellaneous.17="%%count%% Spooky Bed Wars Loot Chests" +toolbox_miscellaneous.18="%%count%% Murder Mystery Loot Chests" +toolbox_miscellaneous.19="%%count%% Merry Bed Wars Loot Chests" +toolbox_miscellaneous.20="%%count%% Merry Murder Mystery Loot Chests" +toolbox_miscellaneous.21="%%count%% Lunar Bed Wars Loot Chests" +toolbox_miscellaneous.22="%%count%% SkyWars Loot Chests" +toolbox_miscellaneous.23="%%count%% Easter Bed Wars Loot Chests" +toolbox_miscellaneous.24="%%count%% Easter SkyWars Loot Chests" +toolbox_miscellaneous.25="%%count%% Golden Bed Wars Loot Chests" +toolbox_miscellaneous.26="Gorilla Companion" \ No newline at end of file diff --git a/configuration/i18n/en_US/scoreboard.properties b/configuration/i18n/en_US/scoreboard.properties index 1aaf2a405..a862c1adc 100644 --- a/configuration/i18n/en_US/scoreboard.properties +++ b/configuration/i18n/en_US/scoreboard.properties @@ -1,6 +1,4 @@ -# Common -scoreboard.common.date_format = MM/dd/yy -scoreboard.common.date_line= +scoreboard.common.date_line= scoreboard.common.footer = www.hypixel.net # SkyBlock Scoreboard @@ -20,9 +18,17 @@ scoreboard.skyblock.dark_auction.time_left_line=Time Left: s scoreboard.skyblock.dark_auction.current_item_label = Current Item: scoreboard.skyblock.dark_auction.current_item_line= scoreboard.skyblock.dark_auction.waiting = Waiting... +# Main Lobby Scoreboard +scoreboard.main_lobby.rank=Rank: +scoreboard.main_lobby.achievements=Achievements: +scoreboard.main_lobby.level=Hypixel Level: +scoreboard.main_lobby.lobby=Lobby: +scoreboard.main_lobby.online_players=Players: +scoreboard.main_lobby.friends_online=Friends Online: +scoreboard.main_lobby.guild_online=Guild Online: # Bed Wars Game Scoreboard -scoreboard.bedwars_game.title_base = BED WARS +scoreboard.bedwars_game.date_line= scoreboard.bedwars_game.map_line=Map: scoreboard.bedwars_game.players_line=Players: / scoreboard.bedwars_game.starting_in_line=Starting in s @@ -38,12 +44,10 @@ scoreboard.bedwars_lobby.title_base = BED WARS scoreboard.bedwars_lobby.level_line=Level: scoreboard.bedwars_lobby.progress_line=Progress: / scoreboard.bedwars_lobby.progress_bar=[] -scoreboard.bedwars_lobby.progress_bar_filled = \u25A0 -scoreboard.bedwars_lobby.progress_bar_empty = \u25A0 -scoreboard.bedwars_lobby.tokens_line=Tokens: -scoreboard.bedwars_lobby.tickets_line=Tickets: /75 -scoreboard.bedwars_lobby.total_kills_label = Total Kills: 0 -scoreboard.bedwars_lobby.total_wins_label = Total Wins: 0 +scoreboard.bedwars_lobby.tokens_line=Tokens: +scoreboard.bedwars_lobby.tickets_line=Tickets: /75 +scoreboard.bedwars_lobby.total_kills_label=Total Kills: +scoreboard.bedwars_lobby.total_wins_label=Total Wins: # Murder Mystery Game Scoreboard scoreboard.murdermystery_game.title_base = MURDER MYSTERY diff --git a/configuration/i18n/fi_FI/bedwars.properties b/configuration/i18n/fi_FI/bedwars.properties deleted file mode 100644 index ad58a4731..000000000 --- a/configuration/i18n/fi_FI/bedwars.properties +++ /dev/null @@ -1,10 +0,0 @@ -bedwars.kill.died.default=" kuoli." -bedwars.kill.died_by.default=" tapettiin pelaajan toimesta." -bedwars.kill.projectile.default="Pelaajan ampui ." -bedwars.kill.assist.default=" tapettiin pelaajan avulla." -bedwars.kill.void.default=" putosi tyhjyyteen." -bedwars.kill.void_by.default=" putosi tyhjyyteen pelaajan toimesta." -bedwars.kill.bed.default="tuhosi pelaaja" -bedwars.kill.final_kill="VIIMEISTELYTAPPO!" -bedwars.bed_destroyed="SNKY TUHOTTU > Snky ." -bedwars.bed_destroyed_self="SNKY TUHOTTU > Snkysi ." \ No newline at end of file diff --git a/configuration/i18n/fi_FI/general.properties b/configuration/i18n/fi_FI/general.properties new file mode 100644 index 000000000..71e113d82 --- /dev/null +++ b/configuration/i18n/fi_FI/general.properties @@ -0,0 +1 @@ +general.not_implemented=Tämä ominaisuus ei ole valmis. Luo PR:si klikkaamalla saadaksesi se nopeiten valmiiksi! \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/bedwars.properties b/configuration/i18n/fi_FI/official/bedwars.properties new file mode 100644 index 000000000..6bad074c3 --- /dev/null +++ b/configuration/i18n/fi_FI/official/bedwars.properties @@ -0,0 +1,4276 @@ +bedwars.click_to_play="KLIKKAA PELATAKSESI" +bedwars.1="Bed Wars Solo" +bedwars.2="Bed Wars Doubles" +bedwars.3="Bed Wars 3v3v3v3" +bedwars.4="Bed Wars 4v4v4v4" +bedwars.5="KLIKKAA AVATAKSESI" +bedwars.shopkeeper="Kauppias" +bedwars.7="Tasosi: %%format%%" +bedwars.8="Edistyminen: %%format%%" +bedwars.9="Tappoja yhteensä: %%total%%" +bedwars.10="Voittoja yhteensä: %%total%%" +bedwars.11="Profiilini " +bedwars.12="Kauppa & kosmeettiset esineeni " +bedwars.13="Bed Wars -profiilisi" +bedwars.14="Tasosi: %%format%%" +bedwars.15="Saavutukset: %%progress%%" +bedwars.16="Tämänhetkinen voittoputki: %%total%%" +bedwars.17="Bed Wars -taso" +bedwars.18="Lisää klikkaamalla!" +bedwars.19="Solo" +bedwars.20="Doubles" +bedwars.21="Bed Wars -kauppa" +bedwars.22="VIERAILE KAUPASSA" +bedwars.23="Ilotulitus-voitontanssi" +bedwars.24="%%color%%%%name%%" +bedwars.25="Zombikauppias" +bedwars.26="Tiilitalo-saarikoriste" +bedwars.27="%%rarity%%%%category%%" +bedwars.28="Tiilitalo" +bedwars.29="Valitse Tappoilmoituspaketti korvataksesi chat-ilmoituksia erilaisilla viesteillä kun tapat pelaajia ja tiimejä tai tuhoat sänkyjä!" +bedwars.30="Tappoilmoitukset" +bedwars.31="Valitse saarikoriste koristellaksesi saartasi! Doubles- ja Teams-pelimuodoissa saarikoriste valitaan satunnaisesti." +bedwars.32="Saarikoristeet" +bedwars.33="Valitse partikkelisymboli, joka näkyy pääsi yläpuolella kun aktivoit sen!" +bedwars.34="Vaihda ammusjälkesi!" +bedwars.35="Anna muiden tietää, miten suolaisia sinun kyyneleesi ovat joka kerta, kun kuolet huutaen!" +bedwars.36="Kuolinkirkaisut" +bedwars.37="Valikoima erilaisia efektejä, joista valitsemasi aktivoituu aina tappaessasi vihollisesi lopullisesti!" +bedwars.38="Valitse miltä tahdot kauppiaasi näyttävän pelissä! Doubles ja Teams -pelimuodoissa kauppiaan ulkonäkö valitaan satunnaisesti." +bedwars.39="Kauppiaat" +bedwars.40="Valitse suihke, jolla koristella tukikohtaasi!" +bedwars.41="Valitse %%clean%%." +bedwars.42="Valitsemalla tämän asetuksen, poistat käytöstä %%title%%." +bedwars.43="Juhli voittoasi ratsastamalla Witherillä - klikkaa ampuaksesi Witherin pääkalloja." +bedwars.44="Juhli voittoasi ratsastamalla Lohikäärmeellä, joka voi tuhota karttaa." +bedwars.45="Juhli voittoasi Alasinsateella." +bedwars.46="Juhli voittoasi valtavalla ilotulituksella!" +bedwars.47="Juhli voittoasi meteorisateella." +bedwars.48="Juhli voittoasi Vartijoiden kutsurituaalilla." +bedwars.49="Juhli voittoasi ilotulitteilla, jotka kirjoittavat nimesi taivaalle!" +bedwars.50="Keksejä lentelee ympäriinsä tappaessasi vihollisen." +bedwars.51="Valitse %%clean%%. Tämä muutos on kosmeettinen." +bedwars.52="Saatavilla kaupasta" +bedwars.53="Valitse %%clean%% saaresi päälle." +bedwars.54="Soittaa äänen %%title%% tappaessasi vihollisen." +bedwars.55="Valitse %%clean%% kauppiaaksesi!" +bedwars.56="Katsoja-asetukset " +bedwars.57="Pelaa uudestaan " +bedwars.58="Palaa lobbyyn " +bedwars.59="Puolusta sänkyäsi!" +bedwars.60="Timanttipäivitys" +bedwars.61="Valitse vaihtoehto tai Hiivi peruuttaaksesi." +bedwars.62="Pelattu aika" +bedwars.63="+%%amount%% Bed Wars -experienceä" +bedwars.64="%%tc%%%%name%% katkaisi yhteyden" +bedwars.65="%%player%% putosi tyhjyyteen." +bedwars.66="Esinekauppa" +bedwars.67="Vasenklikkaa selataksesi symboleita/suihkeita" +bedwars.68="Oikeaklikkaa: käytä Symboleita/Suihkeita" +bedwars.69="Klikkaa hankkiaksesi!" +bedwars.70="Suihkepullo" +bedwars.71="Lähitaistelu" +bedwars.72="Esineet:" +bedwars.73=" ? %%name%%" +bedwars.74="Hinta:" +bedwars.75="%%color%%10 rautaa" +bedwars.76="Sinulla ei ole tarpeeksi resurssia %%resource%%!" +bedwars.77="%%color%%7 kultaa" +bedwars.78="%%color%%4 smaragdia" +bedwars.79="%%color%%10 kultaa" +bedwars.80="Vasenklikkaa selataksesi symboleita ja suihkeita! Oikeaklikkaa käyttääksesi valittua symbolia tai suihketta!" +bedwars.81="Suihkepullo " +bedwars.82="Sprrrrr ..." +bedwars.83="Sinulla ei ole suihketta valittuna! Käytä smaragdia lobbyssa valitaksesi sellaisen!" +bedwars.84="Nyt valittuna: %%option%%" +bedwars.85="Et voi valita toista suihkepulloa, kun sinulla on jo yksi tavaraluettelossasi!" +bedwars.86="Jos yhteytesi katkeaa, käytä komentoa /rejoin liittyäksesi uudelleen peliin." +bedwars.87="Hyötyesineet" +bedwars.88="%%color%%1 Smaragdi" +bedwars.89="%%color%%3 kultaa" +bedwars.90="%%color%%50 rautaa" +bedwars.91="%%color%%150 rautaa" +bedwars.92="Tulipallo" +bedwars.93="%%color%%5 kultaa" +bedwars.94="Päivitykset" +bedwars.95="Saa Louhintauupumus I kahdeksan palikan etäisyydellä sängystä." +bedwars.96="Hinta: %%cost%%" +bedwars.97="Luo parantavan alueen tukikohtasi ympärille!" +bedwars.98="Sinun tiimilläsi tulee olemaan 2 lohikäärmettä yhden sijasta deathmatchin aikana!" +bedwars.99="Nopeuttaa raudan ja kullan syntymistä %%percent%%%." +bedwars.100="Kaikki pelaajat tiimissäsi saavat pysyvästi Kiire %%amplifier%% -vaikutuksen." +bedwars.101="Tiimisi saa Terävyys %%level%% -lumouksen kaikkiin miekkoihin!" +bedwars.102="Tiimisi saa Suojaus %%level%% -lumouksen kaikkiin panssarin osiin!" +bedwars.103="Seuraava tukikohtaasi saapuva vihollinen saa sokeuden ja hitauden!" +bedwars.104="Sinulla ei ole tarpeeksi resursseja avataksesi tätä päivitystä!" +bedwars.105="Panssari" +bedwars.106="Rengaspanssari" +bedwars.107="%%color%%40 rautaa" +bedwars.108="Et menetä tätä kuollessasi!" +bedwars.109="%%color%%12 kultaa" +bedwars.110="%%color%%6 smaragdia" +bedwars.111="Palikat" +bedwars.112="%%color%%4 rautaa" +bedwars.113="%%color%%12 rautaa" +bedwars.114="%%color%%24 rautaa" +bedwars.115="%%color%%4 kultaa" +bedwars.116="Sijoitusbonus" +bedwars.117="TIIMI ELIMINOITU > %%tc%%%%tname%% joukkue on eliminoitu!" +bedwars.118="%%tc%%%%tname%% tiimi on voittanut pelin!" +bedwars.119="Voitto" +bedwars.120="Ansaitsit %%amount%% Bed Wars -experienceä" +bedwars.121="Pitkän matkan aseet" +bedwars.122="%%color%%2 kultaa" +bedwars.123="%%color%%24 kultaa" +bedwars.124="Työkalut" +bedwars.125="%%color%%30 rautaa" +bedwars.126="%%color%%20 rautaa" +bedwars.127="%%color%%8 kultaa" +bedwars.128="Taikajuomat" +bedwars.129="Nopeuden taikajuoma II" +bedwars.130="Loikkaamisen taikajuoma V" +bedwars.131="%%name%% osti esineen %%item%%" +bedwars.132="Voit ainoastaan rikkoa pelaajien asettamia palikoita!" +bedwars.133="Et voi rikkoa omaa sänkyäsi!" +bedwars.134="SÄNKY TUHOTTU > Pelaaja %%tc%%%%player%% tuhosi sänkysi!" +bedwars.135="SÄNKY TUHOTTU > %%team%% Sänky tuhottiin pelaajan %%tc%%%%player%% toimesta!" +bedwars.136="Sänky tuhottu" +bedwars.137="SÄNKY TUHOTTU!" +bedwars.138="Et voi enää syntyä uudelleen!" +bedwars.respawn_progress="Synnyt uudelleen %%seconds%% sekunnin kuluttua!" +bedwars.you_died="SINÄ KUOLIT!" +bedwars.141="Synnyit uudelleen!" +bedwars.142="UUDELLEENSYNNYTTY!" +bedwars.143="%%killer%% tönäisi pelaajan %%player%% tyhjyyteen." +bedwars.144="%%resource%%generaattorit on päivitetty tasolle %%tier%%" +bedwars.145="Smaragdipäivitys" +bedwars.146="%%color%%+%%amount%% rautaa" +bedwars.147="%%color%%+%%amount%% kultaa" +bedwars.148="Viimeistely" +bedwars.149="Sinut on eliminoitu!" +bedwars.150="Peli valitsemassasi maailmassa on jo alkanut!" +bedwars.151="KLIKKAA PELATAKSESI" +bedwars.152="Valitse lokero" +bedwars.153="Tätä kosmeettista esinettä voi käyttää pelissä oikeaklikkaamalla kompassia!" +bedwars.154="Tallennettu %%name%% sijaintiin %%position%%!" +bedwars.155="Hakutulokset:" +bedwars.156="Hakutulokset: Creeper" +bedwars.157="Lähettimiehen palkinnot!" +bedwars.158="Bed Wars -lobbyn valinta" +bedwars.159="pelaamalla pelejä palvelimella!" +bedwars.160="Lohikäärmeensurmaaja" +bedwars.161="%%killer%% tappoi pelaajan %%player%%." +bedwars.162="%%tc%%%%player%% tuhosi sänkysi!" +bedwars.163="Viimeistelyt:" +bedwars.164="Pelaa Bed Wars" +bedwars.165="Klikkaa tästä päästäksesi takaisin peliin!" +bedwars.166="Klikkaa tästä liittyäksesi uudelleen Bed Wars -peliisi, mikäli yhteytesi katkesi." +bedwars.167="Suojele sänkyäsi yksin ja tuhoa vastustajiesi sängyt voittaaksesi." +bedwars.168="Kartan valinta" +bedwars.169="Suojele sänkyäsi tiimikaverin kanssa ja tuhoa vastustajien sängyt voittaaksesi." +bedwars.170="Suojele sänkyäsi kahden tiimikaverin kanssa ja tuhoa vastustajien sängyt voittaaksesi." +bedwars.171="Asetit taulukon näyttämään tilastot: %%name%%!" +bedwars.172="Tiimit" +bedwars.173="3v3v3v3" +bedwars.174="4v4v4v4" +bedwars.175="%%name%%" +bedwars.176="Ei mitään valittuna" +bedwars.177="Jäljitys & kommunikointi" +bedwars.178="Lähetä korostettuja chat-viestejä tiimikavereillesi!" +bedwars.179="Pikaviestit" +bedwars.180="Osta seurantapäivitys kompassiisi, ja voit jäljittää jokaista pelaajaa tietyssä tiimissä, kunnes kuolet." +bedwars.181="Jäljitinkauppa" +bedwars.182="Pikaviestit" +bedwars.183="Klikkaa lähettääksesi!" +bedwars.184="Osta vihollisenjäljitin" +bedwars.185="sängyt on tuhottu!" +bedwars.186="Hinta: %%cost%% smaragdia" +bedwars.187="Sinulla ei ole tarpeeksi smaragdeja!" +bedwars.188="Jäljitä tiimiä %%team%%" +bedwars.189="Jäljitetään tukikohtaa kompassilla!" +bedwars.190="TIIMI > %%player%%: %%message%%" +bedwars.191="Valitse vaihtoehto:" +bedwars.192="Klikkaa lähettääksesi viestin:" +bedwars.193="tiimikavereihisi!" +bedwars.194="Jäljitetään tiimiä %%team%% kompassilla!" +bedwars.195="Jäljitetään resurssia %%resource%% kompassilla!" +bedwars.196="Kaikkia vihollisten sänkyjä ei ole vielä tuhottu!" +bedwars.197="Rakentamisen korkeusraja saavutettu!" +bedwars.198="Kaikkia vihollisten sänkyjä ei ole vielä rikottu!" +bedwars.199="Ostit tiimin %%team%% jäljityksen" +bedwars.200="Kuoltuasi et voi enää jäljittää tätä tiimiä!" +bedwars.201="Kompassi – %%color%%Jäljitys %%name%% " +bedwars.202="%%magic%%MN TASON NOUSU! Olet nyt tasolla %%level%%! %%magic%%NM" +bedwars.203="Ansaitsit %%amount%% %%reward%%" +bedwars.204="Timanttisymboli" +bedwars.205="Näkymättömyyden taikajuoma -suihke" +bedwars.206="Leirinuotio-viimeistely" +bedwars.207="Soittaa äänen %%title%%, kun kuolet." +bedwars.208="Hakutulokset: asfasffs" +bedwars.209="Bed Wars -tilastot" +bedwars.210="Puolustus" +bedwars.211="Tuki" +bedwars.212="Hyökkäys" +bedwars.213="Tuli-tappoilmoitus" +bedwars.214="Gg-symboli" +bedwars.215="Gg" +bedwars.216="Ender-ammusjälki" +bedwars.217="Äreä kyläläinen -kuolinkirkaisu" +bedwars.218="Tnt-symboli" +bedwars.219="Äreä kyläläinen" +bedwars.220="Tnt" +bedwars.221="Bed Wars Solo" +bedwars.222="Bed Wars Doubles" +bedwars.223="Bed Wars 3v3v3v3" +bedwars.224="Bed Wars 4v4v4v4" +bedwars.225="KLIKKAA AVATAKSESI" +bedwars.226="Kauppias" +bedwars.227="Hei-symboli" +bedwars.228="Nuotit-ammusjälki" +bedwars.229="Rakastan sinua -suihke" +bedwars.230="GG WP -suihke" +bedwars.231="Rautasymboli" +bedwars.232="Peukut ylös -symboli" +bedwars.233="Hakutulokset: asfgag" +bedwars.234="Creeper-kauppias" +bedwars.235="Vihreä tähti -ammusjälki" +bedwars.236="Ding-kuolinkirkaisu" +bedwars.237="Ding" +bedwars.238="Hakutulokset: ads" +bedwars.239="Suojele sänkyäsi kolmen tiimikaverin kanssa ja tuhoa vastustajien sängyt voittaaksesi." +bedwars.240="Yhteisöpaneeli" +bedwars.241="Bed Wars -saavutukset" +bedwars.242="Tiimipelaaja" +bedwars.243="Vesi-ammusjälki" +bedwars.244="Timanttisuihke" +bedwars.245="Golemratsastus-suihke" +bedwars.246="Sänkyjä rikottu" +bedwars.247="Sänkyjä menetetty" +bedwars.248="Lopulliset kuolemat" +bedwars.249="Tappiot" +bedwars.250="Bed Wars Doubles" +bedwars.251="Joka päivä voit valita yhden kerran missä kartassa haluat pelata. Avaa loputon kartanvalinta ostamalla MVP+ kaupastamme!" +bedwars.252="Klikkaa tästä vieraillaksesi kaupassa!" +bedwars.253="Kartan valinta" +bedwars.254="Bed Wars Solo" +bedwars.255="Lima-saarikoriste" +bedwars.256="Miekka-saarikoriste" +bedwars.257="Pommi-saarikoriste" +bedwars.258="Kana-saarikoriste" +bedwars.259="Siisti kypärä -saarikoriste" +bedwars.260="Kalamalja-saarikoriste" +bedwars.261="Liekki-saarikoriste" +bedwars.262="Gongi-saarikoriste" +bedwars.263="Sydän-saarikoriste" +bedwars.264="Monokkeli-saarikoriste" +bedwars.265="Nuotti-saarikoriste" +bedwars.266="Sateenkaarilammas-saarikoriste" +bedwars.267="Rubikin kuutio -saarikoriste" +bedwars.268="Lammas-saarikoriste" +bedwars.269="Laiskiainen-saarikoriste" +bedwars.270="Hymynaama-saarikoriste" +bedwars.271="Aurinkolasit-saarikoriste" +bedwars.272="TNT-saarikoriste" +bedwars.273="Silinteri-saarikoriste" +bedwars.274="Vihaiset kasvot -symboli" +bedwars.275="Sänkysymboli" +bedwars.276="Pronssinen kilpi -symboli" +bedwars.277="Polte-symboli" +bedwars.278="Kanasymboli" +bedwars.279="Creeperin kirkaisu -symboli" +bedwars.280="Itkevät kasvot -symboli" +bedwars.281="Päivänkakkarasymboli" +bedwars.282="Smaragdisymboli" +bedwars.283="Kultasymboli" +bedwars.284="Kultakilpisymboli" +bedwars.285="Sydänsymboli" +bedwars.286="Lol-symboli" +bedwars.287="Nro. 1 -symboli" +bedwars.288="Ei-symboli" +bedwars.289="Satenkaarisymboli" +bedwars.290="Hakutulokset: ^^^^^^dfdsf" +bedwars.291="Oletus-tappoilmoitukset" +bedwars.292="Bbq-tappoilmoitukset" +bedwars.293="Rakkaus-tappoilmoitukset" +bedwars.294="Piraatti-tappoilmoitukset" +bedwars.295="Länkkäri-tappoilmoitukset" +bedwars.296="Seppäkauppias" +bedwars.297="Sikamieszombikauppias" +bedwars.298="Wither-luurankokauppias" +bedwars.299="Noitakauppias" +bedwars.300="Zombikyläläiskauppias" +bedwars.301="Luurankokauppias" +bedwars.302="Taikurikauppias" +bedwars.303="Sänkyjen kuningas -kauppias" +bedwars.304="Joulubaarimikkokauppias" +bedwars.305="Roihukauppias" +bedwars.306="Sänkykauppias" +bedwars.307="Sänkytutkijakauppias" +bedwars.308="Animoitu Paha silmä -kauppias" +bedwars.309="Animoitu Ender-pulssi -kauppias" +bedwars.310="Animoitu Astronauttikauppias" +bedwars.311="Musta savu -ammusjälki" +bedwars.312="Vihainen kyläläinen -ammusjälki" +bedwars.313="Valkoinen savu -ammusjälki" +bedwars.314="Lima-ammusjälki" +bedwars.315="Punainen pöly -ammusjälki" +bedwars.316="Satunnainen ammusjälki" +bedwars.317="Sateenkaariammusjälki" +bedwars.318="Violetti pöly -ammusjälki" +bedwars.319="Taikajuoma-ammusjälki" +bedwars.320="Taika-ammusjälki" +bedwars.321="Laava-ammusjälki" +bedwars.322="Sydänammusjälki" +bedwars.323="Ilotulite-ammusjälki" +bedwars.324="Tuli-ammusjälki" +bedwars.325="Sininen pöly -ammusjälki" +bedwars.326="Lohikäärmeratsastaja-voitontanssi" +bedwars.327="Alasinsade-voitontanssi" +bedwars.328="Wither-ratsastaja-voitontanssi" +bedwars.329="Erityinen ilotulitus -voitontanssi" +bedwars.330="Meteorisade-voitontanssi" +bedwars.331="Vartijat-voitontanssi" +bedwars.332="Aww-kuolinkirkaisu" +bedwars.333="Loiskahdus-kuolinkirkaisu" +bedwars.334="Surullinen koiranpentu -kuolinkirkaisu" +bedwars.335="Robottihiiri-kuolinkirkaisu" +bedwars.336="Plop-kuolinkirkaisu" +bedwars.337="Sian kuolinkirkaisu" +bedwars.338="Hirviöröyhtäys-kuolinkirkaisu" +bedwars.339="Karjaisu-kuolinkirkaisu" +bedwars.340="Tulipallo-kuolinkirkaisu" +bedwars.341="Energia-kuolinkirkaisu" +bedwars.342="Endermanin kuolinkirkaisu" +bedwars.343="Kuivat luut -kuolinkirkaisu" +bedwars.344="Dinosauruksen kuolinkirkaisu" +bedwars.345="Vinkulelu-kuolinkirkaisu" +bedwars.346="Bazinga-kuolinkirkaisu" +bedwars.347="Lepakon kuolinkirkaisu" +bedwars.348="Kyllä symboli" +bedwars.349="Vinkkaavat kasvot -symboli" +bedwars.350="Peukut alas -symboli" +bedwars.351="Miekkasymboli" +bedwars.352="Myrskysymboli" +bedwars.353="Tähtisymboli" +bedwars.354="Spektri-symboli" +bedwars.355="Hymynaama-symboli" +bedwars.356="Kallosymboli" +bedwars.357="Hopeakilpisymboli" +bedwars.358="Järkyttyneet kasvot -symboli" +bedwars.359="Huutavat kasvot -symboli" +bedwars.360="Rip-symboli" +bedwars.361="Valas-saarikoriste" +bedwars.362="Puu-saarikoriste" +bedwars.363="Aarrearkku-saarikoriste" +bedwars.364="Vip+-suihke" +bedwars.365="Vip-suihke" +bedwars.366="Kiitos-suihke" +bedwars.367="TNT-pudotus -suihke" +bedwars.368="Anteeksipyyntö-suihke" +bedwars.369="MVP+-suihke" +bedwars.370="MVP-suihke" +bedwars.371="Loot Chest -suihke" +bedwars.372="Loikkaamisen taikajuoma -suihke" +bedwars.373="Hypixel Logo -suihke" +bedwars.374="Enderman-suihke" +bedwars.375="Lohikäärmeentappaja-suihke" +bedwars.376="Creeper-suihke" +bedwars.377="Kannettu-suihke" +bedwars.378="Hei hei -suihke" +bedwars.379="Sänkykilpi-suihke" +bedwars.380="Sängyn rikkoja -suihke" +bedwars.381="Kokemuspallot-viimeistely" +bedwars.382="Tornado-viimeistely" +bedwars.383="TNT-viimeistely" +bedwars.384="Kalmariohjus-viimeistely" +bedwars.385="Hymynaama-viimeistely" +bedwars.386="Rekt-viimeistely" +bedwars.387="Piñata-viimeistely" +bedwars.388="Lit viimeistely" +bedwars.389="Sydänaura-viimeistely" +bedwars.390="Pääraketti-viimeistely" +bedwars.391="Ilotulite-viimeistely" +bedwars.392="Viimeinen isku -viimeistely" +bedwars.393="Keksisuihkulähde-viimeistely" +bedwars.394="Tulikengät-viimeistely" +bedwars.395="Veriräjähdys-viimeistely" +bedwars.396="Lepakko" +bedwars.397="Hirviöröyhtäys" +bedwars.398="Hakutulokset: asd" +bedwars.399="Plop" +bedwars.400="Robottihiiri" +bedwars.401="Tyhjentynyt lelu" +bedwars.402="Puu" +bedwars.403="Noita" +bedwars.404="Zombikyläläinen" +bedwars.405="Rakkaus" +bedwars.406="Kuivat luut" +bedwars.407="Bbq" +bedwars.408="Gongi" +bedwars.409="Wither-luuranko" +bedwars.410="Pussillinen kolikoita" +bedwars.411="Länkkäri" +bedwars.412="Dinosaurus" +bedwars.413="Saarikoriste" +bedwars.414="Pommi" +bedwars.415="Kauppias" +bedwars.416="Taikuri" +bedwars.417="Asettaa aakkosjärjestykseen Ö-A." +bedwars.418="Valas" +bedwars.419="Aarrearkku" +bedwars.420="Silinteri" +bedwars.421="Aurinkolasit" +bedwars.422="Laiskiainen" +bedwars.423="Rubikin kuutio" +bedwars.424="Sateenkaarilammas" +bedwars.425="Nuotti" +bedwars.426="Monokkeli" +bedwars.427="Kalamalja" +bedwars.428="Hieno kypärä" +bedwars.429="Rip" +bedwars.430="Lol" +bedwars.431="Valitse %%clean%% pelinsisäisiin chat-viesteihin!" +bedwars.432="Seppä" +bedwars.433="Sikamieszombi" +bedwars.434="Sänkyjen kuningas" +bedwars.435="Joulubaarimikko" +bedwars.436="Sänkykauppias" +bedwars.437="Sänkytutkija" +bedwars.438="Animoitu Paha silmä" +bedwars.439="Animoitu Ender-pulssi" +bedwars.440="Animoitu astronautti" +bedwars.441="Aww" +bedwars.442="Loiskahdus" +bedwars.443="Surullinen koiranpentu" +bedwars.444="Jyrinä" +bedwars.445="Energia" +bedwars.446="Bazinga" +bedwars.447="Kokemuspallo" +bedwars.448="Lit" +bedwars.449="Kauppa & kosmeettiset esineeni (Oikeaklikkaa)" +bedwars.450="Kuolinkirkaisu" +bedwars.game_start.normal_description="Suojaa sänkysi ja tuhoa vastustajien sängyt. Kerää rautaa, kultaa, smaragdeja ja timantteja generaattoreista voidaksesi päivittää itseäsi ja tiimiäsi aina vain vahvemmaksi." +bedwars.452="Voit käyttää Suihkepulloa esitelläksesi Suihkeita ja Symboleita nopeasti!" +bedwars.453="Sänkysi tuhottiin, joten olet nyt katsoja!" +bedwars.454="Timantit maksimoitu" +bedwars.455="Smaragdit maksimoitu" +bedwars.456="Sänkyjen tuho" +bedwars.457="Kaikki sängyt tuhoutuvat viiden minuutin kuluttua!" +bedwars.458=" ▪ %%item%%" +bedwars.459="Näytetään symboli pääsi päällä!" +bedwars.460="Nyt valittuna: %%color%%%%option%%" +bedwars.461="Tähän palikkaan ei voi tehdä suihketta!" +bedwars.462="Et voi tehdä suihketta tähän!" +bedwars.463="Klikkaa palikkaa suihkepullollasi tehdäksesi suihkeen!" +bedwars.464="Et klikannut palikkaa!" +bedwars.465="%%color%%%%name%%" +bedwars.466="Paha silmä" +bedwars.467="Asettaa aakkosjärjestykseen A-Ö." +bedwars.468="Ei tiimejä jäljellä" +bedwars.469="En tiedä mihin maailmaan sinut tulisi asettaa!" +bedwars.470="Ei mitään asetettuna" +bedwars.471="Valitse symboli tai suihke tähän paikkaan kaupasta!" +bedwars.472="Et voi käyttää tätä täällä!" +bedwars.473="%%tc%%%%team%% - " +bedwars.474="1. Tappaja - %%player%% - %%kills%%" +bedwars.475="2. Tappaja - %%player%% - %%kills%%" +bedwars.476="VOITTO!" +bedwars.477="+%%amount%% Bed Wars -experienceä (%%reason%%)" +bedwars.478="Taso %%tier%%" +bedwars.479="Louhintauupumus " +bedwars.480="Louhintauupumus" +bedwars.481="Parantavat voimat" +bedwars.482="Lisää lohikäärmeitä" +bedwars.483="Rautauuni" +bedwars.484="Hullu kaivaja" +bedwars.485="Teroitetut miekat" +bedwars.486="Vahvempi varustus" +bedwars.487="Hinta: " +bedwars.488="Pysyvä" +bedwars.489="Rautahakku " +bedwars.490="Timanttihakku " +bedwars.491="Timanttikirves " +bedwars.492="Jousi " +bedwars.493="Tikku " +bedwars.494="Näkymättömyyden taikajuoma " +bedwars.495="Tikku (Raskas II)" +bedwars.496="Jousi (Voima I)" +bedwars.497="Jousi (Voima I, Isku I)" +bedwars.498="Kivihakku (Tehokkuus I)" +bedwars.499="Rautahakku (Tehokkuus II)" +bedwars.500="Timanttihakku (Tehokkuus III)" +bedwars.501="Timanttikirves (Tehokkuus II)" +bedwars.502="Nopeuden taikajuoma II (45 sekuntia)" +bedwars.503="Loikkaamisen taikajuoma V (45 sekuntia)" +bedwars.504="Näkymättömyyden taikajuoma (30 sekuntia)" +bedwars.505="Suihkepullo (%%option%%)" +bedwars.506="Aukeaa kun kaikki vihollissängyt on tuhottu!" +bedwars.507="Valikkoa ei pystytty käyttämään, koska vihollinen on lähellä!" +bedwars.508="Sinun täytyy olla maassa käyttääksesi valikkoa!" +bedwars.509="Kompassi - %%color%%Seurataan pelaajaa %%name%% (Vasen- ja oikeaklikkaa)" +bedwars.510="Tasapeli." +bedwars.511="ESINEKAUPPA" +bedwars.512="SOLO" +bedwars.513="TIIMI" +bedwars.514="PÄIVITYKSET" +bedwars.515="Kaikkien pelimuotojen tilastot" +bedwars.516="Syntyy %%seconds%% sekunnissa" +bedwars.517="Timantti" +bedwars.518="Smaragdi" +bedwars.519="Kompassi (Vasen- ja oikeaklikkaa)" +bedwars.quick_communication.have_resources="Minulla on resursseja!" +bedwars.quick_communication.thank_you="Kiitos!" +bedwars.quick_communication.get_back_to_base="Palatkaa tukikohtaan!" +bedwars.quick_communication.ask_defend="Suojaisitko, kiitos!" +bedwars.quick_communication.need_resources="Tarvitsemme resursseja!" +bedwars.quick_communication.hello="Hei ( ゚◡゚)/!" +bedwars.quick_communication.back_to_base="Palaan tukikohtaan!" +bedwars.quick_communication.defending="Minä puolustan!" +bedwars.quick_communication.attacking="Minä hyökkään!" +bedwars.quick_communication.collecting_resources="Kerään resursseja!" +bedwars.530="Järjestää yleisimmästä harvinaisimpaan." +bedwars.531="Järjestää harvinaisimmasta yleisimpään." +bedwars.532="Palaan takaisin tukikohtaan!" +bedwars.533="Minä puolustan!" +bedwars.534="Minä hyökkään!" +bedwars.535="Kerään resursseja!" +bedwars.536="Valitse vaihtoehto: " +bedwars.537="Klikkaa lähettääksesi viestin: " +bedwars.538="Tarvitsemme SMARAGDEJA" +bedwars.539="Tarvitsemme RAUTAA" +bedwars.540="Tarvitsemme KULTAA" +bedwars.541="Tarvitsemme TIMANTTEJA" +bedwars.542="Minulla on SMARAGDEJA" +bedwars.543="Minulla on RAUTAA" +bedwars.544="Minulla on KULTAA" +bedwars.545="Minulla on TIMANTTEJA" +bedwars.546="Kerään SMARAGDEJA" +bedwars.547="Kerään RAUTAA" +bedwars.548="Kerään KULTAA" +bedwars.549="Kerään TIMANTTEJA" +bedwars.550="Ei tähdättäviä tiimejä!" +bedwars.551="Odota hetki pikaviestien välissä!" +bedwars.552="Puolustaisitko, kiitos" +bedwars.553="Kiitos" +bedwars.554="Minä puolustan" +bedwars.555="Suihkepullo (Klikkaa palikkaa)" +bedwars.556="%%underline%%Chat-viestit:" +bedwars.557="Saarikoristeet (sivu 2)" +bedwars.558="Suihkeet (sivu 2)" +bedwars.559="Symbolit (sivu 2)" +bedwars.560="Klikkaa tästä liittyäksesi uudelleen peliin, mikäli yhteytesi katkesi." +bedwars.561="Pelaa Bed Wars 3v3v3v3" +bedwars.562="Pelaa Bed Wars 4v4v4v4" +bedwars.563="Pelaa Bed Wars Doubles" +bedwars.564="Pelaa Bed Wars Solo" +bedwars.565="Bed Wars 3v3v3v3" +bedwars.566="Bed Wars (3v3v3v3)" +bedwars.567="Bed Wars (4v4v4v4)" +bedwars.568="Bed Wars (Solo)" +bedwars.569="Bed Wars (Doubles)" +bedwars.570="Ei suosikkipalvelimia saatavilla!" +bedwars.571="Olet jo ostanut tämän esineen!" +bedwars.572="En tiedä mihin maailmaan sinut tulisi asettaa (Pelaaja)!" +bedwars.573="%%killer%% %%kill_message%% %%player%%." +bedwars.574="Sinun täytyy odottaa %%seconds%% sekuntia ennen kuin voit käyttää komentoa /shout uudestaan!" +bedwars.575="Kultauuni" +bedwars.576="Aktivoi smaragdien syntymisen tiimisi tukikohtaan." +bedwars.577="Smaragdiuuni" +bedwars.578="Nostaa smaragdien, raudan ja kullan syntymisnopeutta %%percent%% prosentilla." +bedwars.579="Sulanut uuni" +bedwars.580="AVATTU" +bedwars.581="Olet jo päivittänyt tämän korkeimmalle tasolle!" +bedwars.582="Sinulla on jo tätä parempi esine." +bedwars.583="ANSA LAUENNUT!" +bedwars.584="Sinun ansasi on lauennut!" +bedwars.585="Sinun ansasi on lauennut!" +bedwars.586="Et voi asettaa palikoita tähän!" +bedwars.587="Et voi hajottaa palikoita täällä!" +bedwars.588="Et ottanut enempää kultaa, koska sinulla on jo sitä liikaa!" +bedwars.589="Rajoite on 2 Golemia pelaajalla!" +bedwars.590="Kaikki sängyt on tuhottu!" +bedwars.591="Kaikki sängyt on tuhottu!" +bedwars.592="Äkkikuolema" +bedwars.593="%%color%%+%%amount%% timanttia" +bedwars.594="%%color%%+%%amount%% smaragdia" +bedwars.595="Äkkikuolema" +bedwars.596="ÄKKIKUOLEMA: +%%num%% %%title%%!" +bedwars.597="Peli päättyy" +bedwars.598="3. Tappaja - %%player%% - %%kills%%" +bedwars.599="PELI PÄÄTTYI!" +bedwars.600="Ansaitsit %%coins%% Bed Wars -kolikkoa" +bedwars.601="Tiimipäivitykset" +bedwars.602="%%option%%!" +bedwars.603="Hei ( ゚◡゚)/" +bedwars.604="Ostit esineen %%item%%" +bedwars.605="Palaa tukikohtaan" +bedwars.606="Palaan takaisin tukikohtaan" +bedwars.607="Klikkaa lähettääksesi viestin: \"%%option%%\"" +bedwars.608="%%option%%" +bedwars.609="SÄNKY TUHOTTU > Sänkysi %%kill_message%% %%tc%%%%player%%!" +bedwars.610="Sänkysi %%kill_message%% %%tc%%%%player%%!" +bedwars.611="SÄNKY TUHOTTU > %%team%% Sänky %%kill_message%% %%tc%%%%player%%!" +bedwars.612=" VIIMEISTELYTAPPO!" +bedwars.613="Valikkoa ei voi käyttää, koska olet katsoja!" +bedwars.614="Kosmeettisten esineiden valikko suljettiin, koska otit vahinkoa!" +bedwars.615="Kosmeettisten esineiden valikko suljettiin, koska hyökkäsit jonkun kimppuun!" +bedwars.616="TIIMI ELIMINOITU > %%tc%%%%tname%% tiimi %%kill_message%%!" +bedwars.617="P" +bedwars.618="S" +bedwars.619="V" +bedwars.620="K" +bedwars.621="T" +bedwars.622="W" +bedwars.623="R" +bedwars.624="H" +bedwars.625="Voit valita %%type%%." +bedwars.626="Minulla on %%resources%%" +bedwars.627="%%choice%%!" +bedwars.628="Hyökätään tiimin %%option%% kimppuun" +bedwars.629="Tarvitsemme resurssia %%resources%%" +bedwars.630="Hyökkään tiimin %%option%% kimppuun" +bedwars.631="Kerään resurssia %%resources%%" +bedwars.632="resurssin" +bedwars.633="tiimin" +bedwars.634="Tulipallo" +bedwars.635="%%choice%%" +bedwars.636="%%name%%" +bedwars.637="Klikkaa lähettääksesi viestin: \"%%choice%%\"" +bedwars.638="1. tappaja" +bedwars.639="2. tappaja" +bedwars.640="3. tappaja" +bedwars.641="Tapot: " +bedwars.642="Viimeistelyt: " +bedwars.643="Sänkyjä rikottu: " +bedwars.644="Et voi käyttää /shout-komentoa katsojana." +bedwars.645="Et voi käyttää /shout-komentoa hiljennettynä." +bedwars.646="Peli on päättynyt, ei tarvita shoutia!" +bedwars.647="SHOUT" +bedwars.648="Pelaajalla %%player%% on %%health%% EP!" +bedwars.649="Et ottanut enempää rautaa, koska sinulla on jo sitä liikaa!" +bedwars.650="Ruoka: %%val%%" +bedwars.651="%%entry%% - %%player%% - %%kills%%" +bedwars.652="Airshow" +bedwars.653="Akvaario" +bedwars.654="Archway" +bedwars.655="Ashore" +bedwars.656="Boletum" +bedwars.657="Chained" +bedwars.658="Crypt" +bedwars.659="Eastwood" +bedwars.660="Glacier" +bedwars.661="Hollow" +bedwars.662="Invasion" +bedwars.663="Lectus" +bedwars.664="Majakka" +bedwars.665="Lotus" +bedwars.666="Pernicious" +bedwars.667="Playground" +bedwars.668="Rooftop" +bedwars.669="Speedway" +bedwars.670="Stonekeep" +bedwars.671="Swashbuckle" +bedwars.672="Treenan" +bedwars.673="Waterfall" +bedwars.674="Doubles" +bedwars.675="4v4v4v4" +bedwars.676="Solo" +bedwars.677="3v3v3v3" +bedwars.678="KLIKKAA AVATAKSESI" +bedwars.679="Hypixel" +bedwars.680="Lisää tulostaulukoita" +bedwars.681="NETTISIVUT" +bedwars.682="TULOSTAULUKOT" +bedwars.683="Nettisivuilta voit löytää vielä lisää tulostaulukoita ja muita siistejä juttuja!" +bedwars.tracking_player="Jäljitetään: - Etäisyys: " +bedwars.685="Odota %%cooldown%% käyttääksesi sitä uudelleen" +bedwars.686="Pelimuodon %%mode%% tilastot" +bedwars.687="Ryhmäbonus" +bedwars.688="Ansaitsit %%exp%% Bed Wars -experienceä (Ensimmäinen liittyminen)" +bedwars.689="Hyökätään!" +bedwars.690="[KATSOJA]" +bedwars.691="Et voi käyttää /shout -komentoa ennen pelin alkamista." +bedwars.692="Voit käyttää /shout -komentoa vain tiimipelimuodoissa." +bedwars.693="Pikaviestit" +bedwars.694="Et voi käyttää pikaviestintää Solo-pelimuodossa!" +bedwars.695="Et voi käyttää pikaviestintää Solo-pelimuodossa!" +bedwars.696="Et voi tehdä tuota juuri nyt!" +bedwars.697="En löytänyt sinulle peliä!" +bedwars.698="Et voi avata tätä arkkua, sillä tiimiä %%team%% ei ole vielä eliminoitu!" +bedwars.699="Otit vahinkoa ja menetit näkymättömyytesi!" +bedwars.700="Ei symbolia" +bedwars.701="Vihollisen tappaminen sytyttää hänet tuleen." +bedwars.702="Amazon" +bedwars.703="Puuhakku [Taso 1]" +bedwars.704="Kivihakku [Taso 2]" +bedwars.705="Rautahakku [Taso 3]" +bedwars.706="Timanttihakku [Korkein taso]" +bedwars.707="Puukirves [Taso 1]" +bedwars.708="Kivikirves [Taso 2]" +bedwars.709="Rautakirves [Taso 3]" +bedwars.710="Timanttikirves [Korkein taso]" +bedwars.711="Olentosi taistelee puolestasi %%timer%% sekunnin ajan." +bedwars.712="Tämä on päivitettävä esine." +bedwars.713="Tason 1 yläpuolella se palautuu" +bedwars.714="yhden heikommalle tasolle kuollessasi!" +bedwars.715="Tiimisi saa Tehokkuus %%level%% -lumouksen kaikkiin työkaluihin!" +bedwars.716="Lutikka" +bedwars.717="Lutikka" +bedwars.718="Unelmapuolustaja" +bedwars.719="Jäinen" +bedwars.720="Kiinteänä lumipallo-sarjan aseena, tämä lumiukko auttaa puolustamaan tukikohtaasi." +bedwars.721="Sinulla ei ole tarpeeksi resurssia %%resource%%! Tarvitaan %%amount%% lisää!" +bedwars.722="Pikavalinta" +bedwars.723="Alku" +bedwars.724="Keskivaihe" +bedwars.725="Loppu" +bedwars.726="Esineet tällä linjalla ovat suositeltuja pelin vaiheessa %%stage%%." +bedwars.727="%%stage%%" +bedwars.728="Esine tallennettu paikalle %%slot%%!" +bedwars.729="Suosikit" +bedwars.730="Suosikit" +bedwars.731="Suositellut esineet" +bedwars.732="Suositellut esineet" +bedwars.733="Klikkaa asettaaksesi suosikkiesineesi tähän lokeroon!" +bedwars.734="Klikkaa %%choice%%!" +bedwars.735="korvataksesi" +bedwars.736="asettaaksesi" +bedwars.737="Suihkepulloa voi käyttää" +bedwars.738="esitelläksesi Suihkeita ja" +bedwars.739="Symboleita nopeasti!" +bedwars.740="Vasenklikkaa: Vaihda valittua" +bedwars.741="Oikeaklikkaa: Käytä suihkepulloa" +bedwars.742="Klikkaa tarkastellaksesi joitain suositeltuja esineitä pelin alku- ja loppuvaiheissa!" +bedwars.743="Oikeaklikkaa laukaistaksesi!" +bedwars.744="Kohtalaisen ärsyttäviä. Nämä" +bedwars.745="pienet elukat voidaan heittää" +bedwars.746="vihollisien harhauttamiseksi." +bedwars.747="Kohtalaisen motivoitunut." +bedwars.748="Joskus se auttaa sinua puolustamaan" +bedwars.749="tukikohtaasi." +bedwars.750="Melko hyödyllisiä vihollistukikohtien" +bedwars.751="valtaamiseen." +bedwars.752="Tämä muna luo sillan" +bedwars.753="perässään, kun heität sen." +bedwars.754="Shift-klikkaa esinettä kaupassa asettaaksesi sen suosikiksesi!" +bedwars.755="Klikkaa nähdäksesi suosikkiesineesi. Voit asettaaa esineen suosikiksesi shift-klikkaamalla mitä tahansa esinettä!" +bedwars.756="Louhintauupumusansa" +bedwars.757="Seuraava tukikohtaasi saapuva vastustaja saa louhintauupumuksen 10 sekunniksi!" +bedwars.758="Räjähdyksenkestävä lasi" +bedwars.759="Immuuni räjähdyksille" +bedwars.760="Lutikka (Hajoamaton I)" +bedwars.761="Hypixelin Karmiva Halloween" +bedwars.762="Soittaa kuolinkirkaisun %%title%%, kun kuolet." +bedwars.763="Valitse %%clean%% kauppiaaksesi!" +bedwars.764="Saatavilla Halloweenina!" +bedwars.765="Et ole tuntenut pelkoa ennen kuin olet ollut yksin pimeässä ja ajatellut tätä voitontanssia." +bedwars.766="Paina välilyöntiä Ghast-hypätäksesi!" +bedwars.767="Avataan erikoistehtävästä!" +bedwars.768="Vihollisesi katoaa todellisuudesta tappaessasi hänet." +bedwars.769="Vihollisen sielu muuttuu seitsemäksi lepakoksi tappaessasi hänet." +bedwars.770="Kurpitsanaattorin kurpitsa" +bedwars.771="Toit %%count%% kurpitsaa takaisin kauppiaalle!" +bedwars.772="Toit %%count%% kurpitsan takaisin kauppiaalle!" +bedwars.773="Anna tämä mille tahansa kauppiaalle suorittaaksesi Kurpitsanaattoritehtävän!" +bedwars.774="pelaajan %%who%% Lepakko #%%no%%" +bedwars.775="Kauhukauppias" +bedwars.776="Halloween-tapahtuma" +bedwars.777="Klikkaa avataksesi Bed Wars -kaupan" +bedwars.778="KARMIVAA HALLOWEENIA" +bedwars.779="7. marraskuuta asti" +bedwars.780="Erikoisuudet:" +bedwars.781="Valitse '%%category%%: %%name%%'. Tämä muutos on kosmeettinen." +bedwars.782="Valitse %%name%% kauppiaaksesi!" +bedwars.783="Soittaa äänen '%%category%%: %%name%%' kun kuolet." +bedwars.784="Valitse '%%category%%: %%name%%' pelinsisäisiin chat-viesteihin!" +bedwars.785="Batcrux" +bedwars.786="Musta merkki" +bedwars.787="Doot Doot" +bedwars.788="Noidan keitos" +bedwars.789="Groovy Kummitus" +bedwars.790="Defenestraatio" +bedwars.791="Diskokurpitsa" +bedwars.792="Tähtivihannes" +bedwars.793="Sir von Mewrtimer" +bedwars.794="Paha kissanpentu" +bedwars.795="Silmämuna" +bedwars.796="Aavemainen aave" +bedwars.797="Hall-o-ween" +bedwars.798="Kynttilä" +bedwars.799="Hra Pergamentti Luiseva" +bedwars.800="Pahaenteinen pata" +bedwars.801="Noitahattu" +bedwars.802="Toonywise" +bedwars.803="Valitse '%%category%%: %%name%%' saaresi päälle." +bedwars.804="Kirjaimellisesti pelottava" +bedwars.805="Taikalelukeppi" +bedwars.806="Älä jätä vartioimattoman taikurin haltuun" +bedwars.807="Viimeinen kynttilä" +bedwars.808="pelaajan %%who%% kynttilä" +bedwars.809="pelaajalle %%who%%" +bedwars.810="Soihtu ilmestyy maahan tappaessasi vihollisen." +bedwars.811="Vihollisen tappaminen luo musikaalisen pyrypallon, joka soittaa yhden kuudesta joulusävelestä" +bedwars.812="Lumähdys" +bedwars.813="Lumipalloja lentelee ympäriinsä tappaessasi vihollisen." +bedwars.814="Lumiukko" +bedwars.815="Joulupukki" +bedwars.816="Sinä!" +bedwars.817="Valitse itsesi omaksi kauppiaaksesi! Oma skinisi näytetään." +bedwars.818="Poissa" +bedwars.819="Ihme" +bedwars.820="Taikatuuli" +bedwars.821="Karkkitanko" +bedwars.822="Hype-tonttu" +bedwars.823="Lahja" +bedwars.824="Superlumigolemi" +bedwars.825="Aatto" +bedwars.826="Sinun täytyy odottaa %%cooldown%% sekuntia suihkekäyttöjen välillä!" +bedwars.827="Suihkeet aktivoidaan nyt valmiiksi määritellyiltä paikoilta kartalla!" +bedwars.828="Symbolit ilmestyvät automaattisesti resursseja poimiessa!" +bedwars.829="Suihkepullo poistetaan" +bedwars.830="pian, sillä Symboleita" +bedwars.831="ja Suihkeita muutettiin." +bedwars.832="Vanha Suihkepullo" +bedwars.833="Valitse Symboli, joka ilmestyy aina kun keräät timantteja tai smaragdeja generaattoreista!" +bedwars.834="Valitse suihke, jota voit esitellä kaikkialla! Suihkekohtia löytyy jokaiselta kotisaarelta ja joiltain keskussaarilta." +bedwars.835="Tuo tämä esine takaisin sille, joka sitä etsii." +bedwars.836="Lahjaa ei voi avata tavaraluettelon ollessa täynnä!" +bedwars.837="Maito täyttyy kun juot, et tunne vaikutusta..." +bedwars.838="En ole etsimässä tämänkaltaista esinettä!" +bedwars.839="Tuo minulle: %%item%%!" +bedwars.840="Sinä toit %%amount%% esineen takaisin henkilölle %%name%%!" +bedwars.841="Sinä toit %%amount%% esinettä takaisin henkilölle %%name%%!" +bedwars.842="Haluaa esineen %%item%%" +bedwars.843="Lucas-tonttu" +bedwars.844="Sammy-keksi" +bedwars.845="Komeetta-poro" +bedwars.846="Joe-pingviini" +bedwars.847="Kompassi - %%color%%Seurataan pelaajaa %%name%% (Vasenklikkaa)" +bedwars.848="L" +bedwars.849="Suunnaton joulukuusi" +bedwars.850="Hieno joulupukin lakki" +bedwars.851="Siivetön enkeli" +bedwars.852="Paljon lahjoja" +bedwars.853="Maaginen pyrypallo" +bedwars.854="Hei, mitäpä jos toisit minulle ämpäreitä, joissa on maitoa?" +bedwars.855="Joitko... maidon?" +bedwars.856="L" +bedwars.857="Meemit" +bedwars.858="Joulupukin paja" +bedwars.859="Avaa ostamalla Loot Boxes!" +bedwars.860="Ender-pulssi" +bedwars.861="Kauppiaan ulkonäkö" +bedwars.862="Kaikki viimeistelyt" +bedwars.863="Viikoittaiset viimeistelyt" +bedwars.864="Kaikki voitot" +bedwars.865="Viikoittaiset voitot" +bedwars.866="HYVÄÄ JOULUA JA ONNELLISTA UUTTA VUOTTA" +bedwars.867="Oikeaklikkaa avataksesi tämän lahjan. Tuo lahja vastaanottajalleen saadaksesi experienceä ja kolikoita!" +bedwars.868="Paketoitu lahja (Oikeaklikkaa)" +bedwars.869="Lahjatoivelista" +bedwars.870="Maito" +bedwars.871="Sukka" +bedwars.872="Hieno huurteinen hattu" +bedwars.873="ÄKKIKUOLEMA: +%%num%% %%team%% lohikäärme!" +bedwars.874="Bao" +bedwars.875="Chen" +bedwars.876="Li" +bedwars.877="Wei" +bedwars.878="Xiu" +bedwars.879="Zhao" +bedwars.880="Blossom" +bedwars.881="Koira" +bedwars.882="Yin ja Yang" +bedwars.883="Kirsikankukka" +bedwars.884="Suihkulähdeilotulite" +bedwars.885="Kuulohikäärme" +bedwars.886="Tassunjälki" +bedwars.887="Hau hau" +bedwars.888="Onnen kissa" +bedwars.889="Söpö koiranpentu" +bedwars.890="Bed Wars 4v4v4v4" +bedwars.891="Astronautti" +bedwars.892="Olet jo avannut tämän päivityksen!" +bedwars.893="Sinun täytyy avata aiemmat tasot, ennen kuin avaat tämän!" +bedwars.894="Et voi käyttää siltamunaa rakentamisen korkeusrajan yläpuolella!" +bedwars.895="Pikaosto" +bedwars.896="Joukkueesi saa pysyvästi Terävyys %%level%% -lumouksen kaikkiin miekkoihin ja kirveisiin!" +bedwars.897="Pelimuoto: %%mode%%" +bedwars.898="v%%version%%" +bedwars.899="BETA %%version%%" +bedwars.900="Versio: %%version%%" +bedwars.901="Timantti II" +bedwars.902="Timantti III" +bedwars.903="Smaragdi II" +bedwars.904="Smaragdi III" +bedwars.905="ESINEKAUPPA" +bedwars.906="SOLO" +bedwars.907="TEAM" +bedwars.908="PÄIVITYKSET" +bedwars.909="Päivitykset & ansat" +bedwars.910="Tiimisi saa pysyvästi Suojaus-lumouksen panssareihinsa!" +bedwars.911="Kaikki tiimisi pelaajat saava pysyvästi Kiirevaikutuksen." +bedwars.912="Päivitä resurssien syntymistä saarellasi." +bedwars.913="Osta ansa" +bedwars.914="Ansajono täynnä!" +bedwars.915="Ostetut ansat asetetaan oikealle jonoon" +bedwars.916="Aseta ansa jonoon" +bedwars.917="Ansajono" +bedwars.918="Aiheuttaa sokeuden ja hitauden viideksi sekunniksi." +bedwars.919="Antaa 15 sekunnin Nopeus I -vaikutuksen tukikohtasi lähellä oleville tiimikavereille." +bedwars.920="Paljastaa näkymättömät pelaajat sekä heidän nimensä ja tiiminsä." +bedwars.921="Aiheuttaa louhintauupumuksen 10 sekunniksi." +bedwars.922="Taso: %%tier%%" +bedwars.923="+%%percent%%% resursseja" +bedwars.924="Suojaus %%tier%%" +bedwars.925="Kiire %%tier%%" +bedwars.926="Esineet" +bedwars.927="Tyhjä paikka!" +bedwars.928="Tämä on pikaostopaikka! Shift-klikkaa mitä vain esinettä kaupassa lisätäksesi sen tänne." +bedwars.929="Shift-klikkaa poistaaksesi pikaostosta!" +bedwars.930="Shift-klikkaa lisääksesi pikaostoon" +bedwars.931="Työkalupalkin hallinta" +bedwars.932="Muokkaa suosimiasi lokeroita esineillesi kategoriakohtaisesti." +bedwars.933="Palauta oletukseksi" +bedwars.934="Palauta työkalupalkki oletukseksi" +bedwars.935="Kategorian %%category%% esineet priorisoivat tämän lokeron!" +bedwars.936="Klikkaa poistaaksesi!" +bedwars.937="Klikkaa vetääksesi!" +bedwars.938="Vedä tämä siihen lokeroon, johon kompassi laitetaan uudelleen syntyessäsi." +bedwars.939="Jos yhdessäkään lokerossa ei ole kompassia, sinulle ei anneta sellaista." +bedwars.940="Vedä tämä johonkin alla olevan työkalupalkin lokeroon suosiaksesi lokeroa ostaessasi tavaroita tässä kategoriassa tai syntyessäsi." +bedwars.item.compass="Kompassi (Oikeaklikkaa)" +bedwars.942="%%color%%Taso %%tier%%: %%upgrade%%, %%cost%%" +bedwars.943="Ei ansaa!" +bedwars.944="Ansa #%%number%%: %%trap%%" +bedwars.945="%%nice%% tukikohtaasi kävelevä vihollinen aktivoi tämän ansan!" +bedwars.946="Ensimmäinen" +bedwars.947="Toinen" +bedwars.948="Kolmas" +bedwars.949="Asettanut jonoon: %%who%%" +bedwars.950="Ostettuasi ansan siirtyy se tähän jonoon. Sen hinta kasvaa jonossa olevien ansojen määrän mukaan." +bedwars.951="Vahvempi varustus I" +bedwars.952="Vahvempi varustus II" +bedwars.953="Vahvempi varustus III" +bedwars.954="Vahvempi varustus IV" +bedwars.955="Hullu kaivaja I" +bedwars.956="Hullu kaivaja II" +bedwars.957="Kontraoffensiivinen ansa" +bedwars.958="Hälytysansa" +bedwars.959="Seuraava ansa: %%cost%%" +bedwars.960="Ostettavissa" +bedwars.961="Syttyy heti, sopiva asioiden räjäyttelyyn!" +bedwars.962="Loistava saarten välisten siltojen rakentamisessa. Muuttuu tiimisi värin mukaan." +bedwars.963="Regashaarniskahousut ja -kengät, joiden kanssa synnyt aina." +bedwars.964="Hyvä palikka sänkysi puolustamiseen. Vahva hakkuja vastaan." +bedwars.965="Rautahousut ja -kengät, joiden kanssa synnyt aina." +bedwars.966="Loistava villan poistamisessa." +bedwars.967="Loistava villan poistamisessa. Synnyt aina näiden keritsimien kanssa." +bedwars.968="Täydellinen näkymättömyys (0:30)" +bedwars.969="Nopeus II (0:45)" +bedwars.970="Hyvä hyökkäävien vihollisten hidastamisessa. Suojaa myös TNT:ltä." +bedwars.971="Tavallinen palikka, jolla puolustaa sänkyäsi." +bedwars.972="Immuuni räjähdyksille." +bedwars.973="Kiinteä palikka, jolla voit puolustaa sänkyäsi." +bedwars.974="Hyödyllinen kissojen pelastamiseksi puista." +bedwars.975="Äärimmäinen suoja sängyllesi." +bedwars.976="Timanttihousut ja -kengät, joiden kanssa tulet aina tuhoamaan." +bedwars.977="Tämä on päivitettävä esine." +bedwars.978="Menettää yhden tason kun kuolet!" +bedwars.979="Tulet aina syntymään uudestaan vähintään heikoimman tason kanssa." +bedwars.980="Hyppytehostus V (0:45)" +bedwars.981="Pitää lääkärin loitolla." +bedwars.982="Luo sokeritoukan sinne, missä lumipallo osuu maahan ja harhauttaa vihollisiasi. Kestää 15 sekuntia." +bedwars.983="Oikeaklikkaa laukaistaksesi! Oivallinen työkalu vihollisten tönimiseksi alas kapeilta silloilta." +bedwars.984="Nopein tapa valloittaa vastustajiesi saaria." +bedwars.985="Tämä kananmuna luo sillan taaksensa heitettyäsi sen." +bedwars.986="Vältä ansojen laukaisemista 60 sekunnin ajan käytön jälkeen." +bedwars.987="Hyvä kuivaamaan vettä." +bedwars.988="MAKSIMOITU!" +bedwars.989="Puuhakku (Tehokkuus I)" +bedwars.990="Kultahakku (Tehokkuus III, Terävyys II)" +bedwars.991="Puukirves (Tehokkuus I)" +bedwars.992="Kivikirves (Tehokkuus I)" +bedwars.993="Rautakirves (Tehokkuus II)" +bedwars.994="Timanttikirves (Tehokkuus III)" +bedwars.995="Rautagolem joka auttaa tukikohtasi puolustuksessa. Kestää 4 minuuttia." +bedwars.996="Lisätään pikaostoon..." +bedwars.997="Tämä on tyhjä pikaostopaikka!" +bedwars.998="Shift-klikkaa kauppatavaraa täyttääksesi tämän paikan!" +bedwars.999="Lisätään esinettä pikaostoon!" +bedwars.1000="Taikamaitosi on kulunut loppuun!" +bedwars.1001="Taikamaito" +bedwars.1002="Klikkaa!" +bedwars.1003="Tikku (Raskas I)" +bedwars.1004="Klikkaat liian nopeasti!" +bedwars.1005="Luo smaragdeja" +bedwars.1006="Luo sokeritoukan sinne, missä lumipallo osuu maahan ja harhauttaa vihollisiasi." +bedwars.1007="Rautagolem auttaa sinua puolustamaan tukikohtaasi." +bedwars.1008="Kvaak" +bedwars.1009="Pupu" +bedwars.1010="Kukoistus" +bedwars.1011="Kuoriutuva muna" +bedwars.1012="Lihava kana" +bedwars.1013="Suklaa" +bedwars.1014="Tällä hetkellä saatavilla:" +bedwars.1015="Sängyn rikkominen herättää Thorin unestaan." +bedwars.1016="Sängyn rikkominen synnyttää pyörremyrskyn!" +bedwars.1017="Sängyn rikkominen laukaisee ilotulitteita." +bedwars.1018="Sängyn rikkominen räjäyttää sen laavaksi." +bedwars.1019="Uusi ystävä syntyy kun rikot sängyn." +bedwars.1020="Sängyn rikkominen vapauttaa sen sisällä olleet luteet." +bedwars.1021="Sängyntuhoamisefekti" +bedwars.1022="Sängyntuhoamisefektit" +bedwars.1023="Valitse erilaisista sängyntuhoamisefekteistä, jotka näkyvät rikkoessasi sängyn!" +bedwars.1024="Varas" +bedwars.1025="Näyttää efektin '%%category%%: %%name%%' kun rikot sängyn." +bedwars.1026="Laavaräjähdys" +bedwars.1027="Lutikat" +bedwars.1028="RAJOITETUN AJAN PELIMUOTO!" +bedwars.1029="Voittopisteet on asetettu pois päältä dream-pelimuodoissa." +bedwars.1030="RAJOITETUN AJAN PELIMUOTO: %%mode%%" +bedwars.1031="RUSH" +bedwars.1032="Rush Doubles" +bedwars.1033="Rush 4v4v4v4" +bedwars.1034="Yleisiä tilastoja, saavutuksia ja tehtäviä EI ansaita tässä pelimuodossa!" +bedwars.1035="ULTIMATE" +bedwars.1036="Ultimate Doubles" +bedwars.1037="Ultimate 4v4v4v4" +bedwars.1038="Dreams" +bedwars.1039="Hyppijä" +bedwars.1040="Miekkamies" +bedwars.1041="Parantaja" +bedwars.1042="Jäädyttäjä" +bedwars.1043="Tuplahyppy!" +bedwars.1044="Syöksy hiiren oikealla näppäimellä miekka kädessä ja vahingoita kaikkia tiellesi astuvia vihollisia!" +bedwars.1045="Paranna lähelläsi olevia liittolaisia nopeasti!" +bedwars.1046="Hidasta lähelläsi olevia vihollisia hetken ajan!" +bedwars.1047="Rakenna helposti seiniä ja siltoja villasta! Tuottaa jatkuvasti villaa." +bedwars.1048="Pelimuoto: %%mode%%" +bedwars.1049="Vasenklikkaa vaihtaaksesi tilan, aseta maahan aktivoidaksesi!" +bedwars.1050="Rakentajan työkalu - %%mode%%" +bedwars.1051="Seinä" +bedwars.1052="Tämä ultimaatti on tulossa pian!" +bedwars.1053="Psst, kokeile oikeaklikata sänkyäsi tällä!" +bedwars.1054="Odotusaika: %%time%% sekuntia" +bedwars.1055="Ultimaatit aktivoidaan %%seconds%% sekunnin kuluttua!" +bedwars.1056="Vaihdettiin ultimaatiksi %%ultimate%%!" +bedwars.1057="Valitse ultimaatti kaupassa! Ne aktivoidaan %%seconds%% sekunnin kuluttua!" +bedwars.1058="Ultimaatit on aktivoitu!" +bedwars.1059="Sinulla ei ollut ultimaattia valittuna, joten sinulle asetettiin %%ultimate%%!" +bedwars.1060="Sinulta loppui villa!" +bedwars.1061="Dream-tilastot" +bedwars.1062="Tarkastele Dream-pelimuodon tilastojasi!" +bedwars.1063="Rushin tilastoja ei seurattu!" +bedwars.1064="Voittoputki" +bedwars.1065="%%mode%%-tilastot" +bedwars.1066="Yleiset tilastot" +bedwars.1067="DREAM %%version%%" +bedwars.1068="Bed Wars %%mode%%" +bedwars.1069="Rush" +bedwars.1070="Ultimate" +bedwars.1071="Ultimaatit" +bedwars.1072="Vasenklikkaa vaihtaaksesi tilan, aseta maahan aktivoidaksesi!" +bedwars.1073="Nyt valittuna!" +bedwars.1074="Sänkyjen tuho" +bedwars.1075="%%event%% %%time%% kuluttua" +bedwars.1076="Jäädyttäjän ultimaatti" +bedwars.1077="Parantajan ultimaatti" +bedwars.1078="Taikamaito" +bedwars.1079="Unelmapuolustaja" +bedwars.1080="Et voi käyttää pikaviestintää tässä pelimuodossa!" +bedwars.1081="RAJOITETUN AJAN DREAMIT" +bedwars.1082="Castle" +bedwars.1083="Sarjapisteet: " +bedwars.1084="PANKKIIRI" +bedwars.1085="SARJAVOIMAT" +bedwars.1086="Sarjavoimat" +bedwars.1087="Näytä koko potentiaalisi sarjavoimilla!" +bedwars.1088="Kultainen ritari" +bedwars.1089="Antaa sinulle luotettavan hevosen ja Oikeuden miekan!" +bedwars.1090="Oikeuden saappaat" +bedwars.1091="Oikeuden housut" +bedwars.1092="Oikeuden rintapanssari" +bedwars.1093="Liidä halki taivaan majesteettisella witherilläsi ja tuhoa vastustajasi hirmuisilla tulipalloillasi!" +bedwars.1094="Yksinäinen susi" +bedwars.1095="Synnyttää uskollisia susia auttamaan sinua taistelussa ja pitämään muut pelaajat loitolla!" +bedwars.1096="Taas yksi susi liittyi laumaasi!" +bedwars.1097=" %%color%%%%player%% vapautti WITHERIN!" +bedwars.1098="%%color%%Witherillä on %%health%% EP!" +bedwars.1099="Tiimin rajoitus: %%amount%% samanaikaisesti" +bedwars.1100="Hinta: %%points%% sarjapistettä" +bedwars.1101="Käytät nyt sarjavoimia!" +bedwars.1102="Olet jo aktivoinut tämän sarjan!" +bedwars.1103="Sinun tulee olla tasolla %%level%% käyttääksesi tätä sarjaa!" +bedwars.1104="Tarvitset %%points%% sarjapistettä lisää!" +bedwars.1105="Tiimilläsi on jo suurin sallittu määrä tätä sarjaa aktivoituna. Palaa takaisin myöhemmin" +bedwars.1106="Sinun tulee odottaa %%cooldown%% sekuntia ennen kuin voit aktivoida toisen sarjavoiman!" +bedwars.1107="Lisää resursseja vetämällä niitä tähän. Kaupat käyttävät automaattisesti Pankkiirin resursseja, mikäli omasi eivät riitä." +bedwars.1108="Varastossa:" +bedwars.1109="%%color%%Lisää %%amount%%x %%resource%% pankkiin" +bedwars.1110="%%resource%% - Tiimiresurssi" +bedwars.1111="Taso 1" +bedwars.1112="Taso 2" +bedwars.1113="Et voi käyttää vastustajan laukaisualustoja!" +bedwars.1114="+%%amount%% sarjapistettä (%%reason%%)" +bedwars.1115="Sinulla ei ole tarpeeksi resurssia %%resource%%!" +bedwars.1116="Tiimisi resurssipankin %%resource%%varasto on tullut täyteen!" +bedwars.1117="Lisäsit %%amount%%x resurssia %%type%% tiimisi resurssipankkiin!" +bedwars.1118="Harkitse joidenkin resurssien jakamista tiimitovereidesi kanssa klikkaamalla Pankkiiria tukikohdassasi." +bedwars.1119="Klikkaa ostaaksesi tiimin resursseilla!" +bedwars.1120="Odota %%seconds%% sekuntia ennen kuin voit taas käyttää tiimin resursseja!" +bedwars.1121="Käytit %%amount%%x resurssia %%type%% tiimisi resurssipankista tässä ostoksessa!" +bedwars.1122="Sarjavoimia saatavilla! Vieraile NPC-hahmon luona tai klikkaa kompassiasi aktivoidaksesi niitä!" +bedwars.1123="%%tc%%%%player%% aktivoi %%streak%% -sarjavoiman!" +bedwars.1124="Pelaajan %%tc%%%%player%% sarjavoimat kuluivat pois." +bedwars.1125="%%color%%%%player%% vapautti WITHERIN!" +bedwars.1126="AIKA LOPPUI! %%streak%% -sarjavoimasi kului pois." +bedwars.1127="Käyttöjä jäljellä: %%amount%%" +bedwars.1128="Ivory Castle" +bedwars.1129="%%player%% kuoli." +bedwars.1130="Et voi rakentaa enää alemmas!" +bedwars.1131="Rush Solo" +bedwars.1132="Ultimate Solo" +bedwars.1133="Rush V2" +bedwars.1134="Ultimate V2" +bedwars.1135="Kaikki generaattorit on päivitetty korkeimmalle tasolle! Sängyssäsi on kaksinkertainen suojaus! Vasenklikkaa villalla aktivoidaksesi sillanrakennuksen!" +bedwars.1136="SILLANRAKENNUS DEAKTIVOITU" +bedwars.1137="SILLANRAKENNUS AKTIVOITU" +bedwars.1138="Voit aktivoida sillanrakennuksen vasenklikkaamalla villalla kädessäsi!" +bedwars.1139="%%team%% lohikäärme" +bedwars.1140="∙ Tuplahyppy!" +bedwars.1141="∙ Mahdollisuus pitää resurssit kuollessasi!" +bedwars.1142="∙ Maitoa rikkoessasi sängyn!" +bedwars.1143="∙ Hiiren oikealla miekka kädessä syöksyt eteenpäin!" +bedwars.1144="∙ Taas hiiren oikealla palataksesi!" +bedwars.1145="∙ Odotusajat nollautuvat tapoista!" +bedwars.1146="∙ Hiiren oikealla miekka kädessä parannat itseäsi!" +bedwars.1147="∙ Heitä taikajuomia parantaaksesi tovereita ympärilläsi!" +bedwars.1148="∙ Heitä taikajuomia hidastaaksesi vihollisia!" +bedwars.1149="∙ Lumipalloja tapoista! (max 16)" +bedwars.1150="∙ Rakenna siltoja!" +bedwars.1151="∙ Rakenna seiniä!" +bedwars.1152="∙ Suojaa sänkysi välittömästi!" +bedwars.1153="Purku" +bedwars.1154="∙ Polta villaa läheltäsi!" +bedwars.1155="∙ Pudota TNT:tä kuollessasi!" +bedwars.1156="∙ Saa creeperin muna rikkoessasi sängyn!" +bedwars.1157="∙ Mahdollisuus saada kaksinkertaisesti timantteja/smaragdeja generaattoreista!" +bedwars.1158="∙ Kannettava ender-arkku!" +bedwars.1159="∙ Kun oma sänkysi tuhotaan, saat ilmaisen tiimipäivityksen!" +bedwars.1160="Räjäytystyökalu" +bedwars.1161="Kannettava ender-arkku (Oikeaklikkaa)" +bedwars.1162="%%name%% avasi esineen %%item%%" +bedwars.1163="Velhon sauva - Oikeaklikkaa käyttääksesi" +bedwars.1164="Palikkavelho" +bedwars.1165="Antaa sinulle taikasauvan, jolla voit kutsua lähistön palikat avustamaan sinua taistelussa!" +bedwars.1166="Odotathan %%seconds%% sekuntia ennen kuin käytät tätä uudelleen!" +bedwars.1167="Kuuma lattia" +bedwars.1168="Sytyttää lattian tuleen!" +bedwars.1169="40v40 Castle V2" +bedwars.1170="Haluaisitko, että %%item%% lisätään lopullisesti Bed Warsiin?" +bedwars.1171="KYLLÄ" +bedwars.1172="EI" +bedwars.1173="Klikkaa tästä äänestääksesi KYLLÄ" +bedwars.1174="Klikkaa tästä äänestääksesi EI" +bedwars.1175="Olet jo käyttänyt tämän!" +bedwars.1176="Aseta kokoontaittuva puolustus!" +bedwars.1177="Pikatorni" +bedwars.1178="Kierrätettävä esine" +bedwars.1179="RAJOITETTU AIKA" +bedwars.1180="Tätä esinettä testataan Bed Warsissa palautteen keräämiseksi." +bedwars.1181="Ostotapahtuma epäonnistui! Ostorajoitus ylittyi!" +bedwars.1182="Ostorajoitus: %%limit%%" +bedwars.1183="Maksimoidut tiimipäivitykset" +bedwars.1184="Kaikki tiimit aloittavat maksimoiduilla tiimipäivityksillä." +bedwars.1185="Kiitos äänestämisestä!" +bedwars.1186="Jääsilta" +bedwars.1187="Luo jääsilta katseesi osoittamaan suuntaan, mutta varo, silta sulaa astellessasi sillä!" +bedwars.1188="Sinun tulee olla maassa käyttääksesi tätä!" +bedwars.1189="Luo lumipalloja ampuva vartiorobotti!" +bedwars.1190="Sokerikeksi" +bedwars.1191="Palikansekoittaja" +bedwars.1192="Tulisiko %%item%% lisätä pysyvästi Bed Warsiin?" +bedwars.1193="Onnenarkku" +bedwars.1194="Luo onnenarkun, josta voi löytää satunnaisia resursseja!" +bedwars.1195="Possuohjus" +bedwars.1196="Possahdus" +bedwars.1197="Sikaisku" +bedwars.1198="Klikkaa avataksesi Bed Wars -kaupan" +bedwars.1199="Sängyn rikkominen kokoaa kasan vauvapossuja." +bedwars.1200="Sika iskeytyy maahan tappaessasi pelaajan." +bedwars.1201="Et osallistunut Bed Wars -turnaukseen, joten \"Turnaussijoitus\"-saarikoristeesi on vain kasa ilmaa." +bedwars.1202="Sinun olisi tullut sijoittua 100 000 parhaan joukkoon Turnauksessa voidaksesi käyttää \"Turnaussijoitus\"-saarikoristettasi, mutta valitettavasti sijoituksesi oli #%%pos%%." +bedwars.1203="Jouluinen tukikohta" +bedwars.1204="Joulun airut" +bedwars.1205="Possun viikko" +bedwars.1206="Sian viikko -kykysi on jo aktiivinen!" +bedwars.1207="Aktivoit Sian viikko -kykysi!" +bedwars.1208="Tuhoajajousi" +bedwars.1209="Aseta kompakti kokoontaittuva puolustus!" +bedwars.1210="Kompakti pikatorni" +bedwars.1211="4v4 Capture BETA" +bedwars.1212="BED WARS BETA" +bedwars.1213="Versio: v%%version%%" +bedwars.1214="Beta on sinulle tapa muokata Bed Warsin tulevaisuutta." +bedwars.1215="Pelaa, koe tulevien päivitysten muutokset ja anna palautetta." +bedwars.1216="ANNA PALAUTETTA" +bedwars.1217="Mikä on Bed Wars BETA?" +bedwars.1218="Pelaa Bed Wars Capture (BETA)" +bedwars.1219="Uudessa Capture-pelimuodossa tarkoitus on vallata ja hallita pisteitä." +bedwars.1220="Voittopisteet on asetettu pois päältä kun Capture on beta-tilassa." +bedwars.1221="Capture" +bedwars.1222="DNA" +bedwars.1223="Sielunrepijä" +bedwars.1224="Tappolaskuri" +bedwars.1225="Alkukantainen" +bedwars.1226="Mahtava" +bedwars.1227="Dramaattinen" +bedwars.1228="Todella ilkeä kurpitsa" +bedwars.1229="Ilkeä kurpitsa" +bedwars.1230="Kurpitsaräjähdys" +bedwars.1231="Epäilyttävä puu" +bedwars.1232="Mini Herobrinen kartano" +bedwars.1233="Gargoili" +bedwars.1234="SÄNKY TUHOTTU > " +bedwars.1235="Päivitetty: Suojaus %%level%%" +bedwars.1236="Päivitetty: Terävyys %%level%%" +bedwars.1237="Löit jotakuta ja menetit haavoittumattomuutesi!" +bedwars.1238="Sinulle annettiin vihollistiimin jäljitin!" +bedwars.1239="Resurssi-info" +bedwars.1240="Lisää pankkiin" +bedwars.1241="Tappo" +bedwars.1242="Tavoitteen suorittaminen" +bedwars.1243="Resurssien kerääminen" +bedwars.1244="Resurssien jakaminen" +bedwars.1245="Sängyn tuhoaminen" +bedwars.1246="Lucky Doubles" +bedwars.1247="Lucky 4v4v4v4" +bedwars.1248="Kaikki generaattorit on päivitetty korkeimmalle tasolle! Sängyssäsi on kolminkertainen suojaus! Vasenklikkaa villalla aktivoidaksesi sillanrakennuksen!" +bedwars.1249="Kerää Lucky Blockeja resurssigeneraattoreista saadaksesi satunnaista tavaraa! Hajota ne paljastaaksesi sisällön!" +bedwars.1250="Osta ja aseta sänkyjä kaappauspisteille kuluttaaksesi vihollisen elinvoimaa tai tuhoa kaikki vihollistiimin sängyt ja eliminoi sitten kaikki pelaajat ennen kuin he voivat asettaa uusia sänkyjä." +bedwars.1251="Voittaaksesi Bed Wars Capture -pelin" +bedwars.1252="Käyttämäsi kannettava ender-arkku katosi!" +bedwars.1253="Sängyn rikkominen kasvattaa kauniita kukkia sen muistoksi." +bedwars.1254="Kalaisa" +bedwars.1255="Sängyn rikkominen kutsuu kaloja, jotka yrittävät epätoivoisesti etsiä lähellä olevaa järveä." +bedwars.1256="Röyhtäys" +bedwars.1257="Raivo" +bedwars.1258="Draaman kuningatar" +bedwars.1259="Suunnittelemassa kostoa" +bedwars.1260="Kultaomena" +bedwars.1261="Mestarin pikari" +bedwars.1262="Kallomiekka" +bedwars.1263="Ylhäinen" +bedwars.1264="murskasi pelaajan" +bedwars.1265="dominoi pelaajan" +bedwars.1266="palautti maan pinnalle pelaajan" +bedwars.1267="salamurhasi pelaajan" +bedwars.1268="solvasi pelaajaa" +bedwars.1269="Jääkylmä" +bedwars.1270="Kultainen" +bedwars.1271="Aalto" +bedwars.1272="Peittää kartan lumella ja luo sinulle seuraksi lumiukkoystäviä!" +bedwars.1273="Fanikunta" +bedwars.1274="Oma kannattajakuntasi ilmestyy ympärillesi, ja jokainen haluaa nimikirjoituksen otsaansa!" +bedwars.1275="Toinen ulottuvuus" +bedwars.1276="Luo portaalin uuteen ulottuvuuteen! Ehkä se on seuraava peli..?" +bedwars.1277="resurssit" +bedwars.1278="Hyökätään tiimin %%option%% kimppuun" +bedwars.1279="Jäljellä ei ole tiimejä, joihin tämän voisi kohdistaa!" +bedwars.1280="Ei tähdättäviä tiimejä!" +bedwars.1281="Paketoitu lahja" +bedwars.1282="Ei löydy kompassilla jäljitettäviä kohteita!" +bedwars.1283="Ei jäljitettäviä tiimejä!" +bedwars.1284="Tavallinen Lucky Block" +bedwars.1285="Lupaava Lucky Block" +bedwars.1286="Onnekas Lucky Block" +bedwars.1287="Aseistuksen Lucky Block" +bedwars.1288="Ihmeellinen Lucky Block" +bedwars.1289="Terävä lusikka" +bedwars.1290="Mausteinen miekka" +bedwars.1291="Linkojousi" +bedwars.1292="Sotakirves" +bedwars.1293="Viikate" +bedwars.1294="Kanajousi" +bedwars.1295="PAHOLAINEN!" +bedwars.1296="Timanttilammas" +bedwars.1297="Pudottaa timantin viiden sekunnin välein yhteensä 30 sekunnin ajan" +bedwars.1298="Timanttilammas" +bedwars.1299="Diskosavi" +bedwars.1300="Aseta väriä vaihtava savikuutio!" +bedwars.1301="Räjähtävä kana" +bedwars.1302="Räjähtävä kana" +bedwars.1303="Ampuu räjähtäviä munia vastustajiasi kohti!" +bedwars.1304="Ansajonosi on täynnä!" +bedwars.1305="Ansajonosi täytettiin: %%traps%%!" +bedwars.1306="Pika-ansajono" +bedwars.1307="Täyttää ansajonosi välittömästi satunnaisilla ansoilla" +bedwars.1308="Välitön seinämä" +bedwars.1309="Oikeaklikkaa luodaksesi välittömän obsidiaaniseinämän katseesi osoittamaan suuntaan!" +bedwars.1310="Sinulla on jo paras ase!" +bedwars.1311="Aseesi päivitettiin: %%material%%!" +bedwars.1312="Välitön asepäivitys" +bedwars.1313="Päivittää aseesi välittömästi" +bedwars.1314="Taaksepäin heittävä limapallo" +bedwars.1315="Laavariimu" +bedwars.1316="Oikeaklikkaa palikkaa asettaaksesi väliaikaisen laavan!" +bedwars.1317="Sinun täytyy käyttää tätä sängyllesi!" +bedwars.1318="Suojaava sängyn peite" +bedwars.1319="Maagisesti rakentaa kolminkertaisen suojauksen sänkysi päälle" +bedwars.1320="Sateenkaarivilla" +bedwars.1321="Asettaa satunnaisesti värjättyä villaa!" +bedwars.1322="Olet jo avannut kaikki saatavilla olevat tiimipäivitykset!" +bedwars.1323="Satunnainen tiimipäivitys" +bedwars.1324="Resurssimyyjä" +bedwars.1325="Uneksija" +bedwars.1326="Hyökkää pelaajien kimppuun sokaistaksesi heidät!" +bedwars.1327="Turvaton teleporttisijainti!" +bedwars.1328="Telejousi" +bedwars.1329="Söpöt housut" +bedwars.1330="Niin sööööpö! ❤" +bedwars.1331="Diskopanssari" +bedwars.1332="Juhli kuin huomista ei olisi!" +bedwars.1333="Elpyminen II (5s) lähitaistelu- tai nuoliosumasta" +bedwars.1334="Sammakkokypärä" +bedwars.1335="Hyppytehostus pidettäessä päällä" +bedwars.1336="Lämmönkestävät saappaat" +bedwars.1337="Kuumakalle" +bedwars.1338="Aina tulessa" +bedwars.1339="Ne, jotka sinua lyövät, syttyvät tuleen" +bedwars.1340="Mahtava majakka" +bedwars.1341="Mahtava merkkivalo vahvisti sinua!" +bedwars.1342="Tämä merkkivalo antaa Voimaa!" +bedwars.1343="Roihuratsastajan kykysi päättyy 10 sekunnin kuluttua!" +bedwars.1344="Roihuratsastajan kykysi on päättynyt!" +bedwars.1345="Roihulla on %%health%% EP!" +bedwars.1346="Painovoima-ase" +bedwars.1347="Lähetä vihollisesi lentoon!" +bedwars.1348="Supertähti" +bedwars.1349="Immuuni suurimalle osalle vahingosta 15 sekunnin ajan" +bedwars.1350="Et voi aktivoida omaa ansaasi!" +bedwars.1351="%%player%% laukaisi matkimisansasi!" +bedwars.1352="Laukaisit pelaajan %%player%% matkimisansan!" +bedwars.1353="Matkija!" +bedwars.1354="Muuttuu zombiksi, mikäli joku yrittää avata sitä!" +bedwars.1355="Mysteeriliha" +bedwars.1356="Voi syödä kylläisenä, antaa 3 satunnaista taikajuomavaikutusta, joista kukin kestää 15 sekuntia" +bedwars.1357="Possulaukaisin" +bedwars.1358="Ammu sikoja vihollisiasi päin!" +bedwars.1359="Kiirehelmi" +bedwars.1360="Ratsastat tällä helmellä heitettyäsi sen" +bedwars.1361="Oikeuden miekka: %%remaining%%s" +bedwars.1362="Odota aikahyppyhelmesi vanhentumista!" +bedwars.1363="Aikahyppyhelmesi on vanhentunut" +bedwars.1364="Sinut teleportataan takaisin %%seconds%% sekunnin kuluttua!" +bedwars.1365="Aikahyppyhelmi" +bedwars.1366="Taikavoimainen lelutikku" +bedwars.1367="Vesi-ilmapallo" +bedwars.1368="Asettaa vettä mihin osuu" +bedwars.1369="UUSI! Lucky Blocks" +bedwars.1370="Pelaa Bed Wars %%mode%%" +bedwars.1371="Et voi käyttää tätä vielä! Yritä uudelleen myöhemmin, kiitos." +bedwars.1372="Nopeus- ja voimaefektien päättymiseen %%seconds%% sekuntia!" +bedwars.1373="Heikkousefektin päättymiseen %%seconds%% sekuntia!" +bedwars.1374="Antaa sinulle nopeutta ja voimaa, mutta myös suuren heikkouden! Kestää %%seconds%% sekuntia." +bedwars.1375="Unikeon kahvipavut" +bedwars.1376="Prototyyppihirviö" +bedwars.1377="Iloinen kurpitsa" +bedwars.1378="Vältä ansojen laukaisemista 30 sekunnin ajan käytön jälkeen." +bedwars.1379="Synnyit uudelleen, koska sinulla on vielä sänky!" +bedwars.1380="Synnyit uudelleen, koska sänkyäsi ei ollut tuhottu kun sinut tapettiin!" +bedwars.1381="SÄNKY TUHOTTU > %%team%% sänky %%kill_message%% %%tc%%%%player%%!" +bedwars.1382="Voit valita %%resource%%." +bedwars.1383="%%time%% %%type%%haarniska" +bedwars.1384="Ei smaragdeja" +bedwars.1385="Eroon niistä smaragdeista" +bedwars.1386="Ei timantteja" +bedwars.1387="Menetkös siitä noiden kiiltävien juttujesi kanssa." +bedwars.1388="Poista palikkasuojaus" +bedwars.1389="Sallii pelaajien tuhota kaikkia palikoita muualla kuin generaattorien ja tukikohtien läheisyydessä." +bedwars.1390="Sänkyjen välitön tuho" +bedwars.1391="Sängyt tuhoutuvat yhdellä lyönnillä." +bedwars.1392="Tapahtuma-ajat" +bedwars.1393="Muokkaa tapahtumien ajankohtia." +bedwars.1394="0.5x - Hitaampi" +bedwars.1395="1x - Tavallinen" +bedwars.1396="2x - Nopeampi" +bedwars.1397="4x - Nopein" +bedwars.1398="Uudelleensyntymisaika" +bedwars.1399="Muokkaa pelaajien uudelleensyntymisaikaa." +bedwars.1400="1 sekunti" +bedwars.1401="5 sekuntia" +bedwars.1402="10 sekuntia" +bedwars.1403="%%team%% tiimi laukaisi hälytysansan!" +bedwars.1404="HÄLYTYS!!!" +bedwars.1405="Tiimin %%team%% pelaaja %%player%% laukaisi Hälytysansan!" +bedwars.1406="Lähistöllä on %%count%% tiimitoveria." +bedwars.1407="%%bed%% sänky " +bedwars.1408="%%bed%% sänky: " +bedwars.1409="talloi jalkoihinsa pelaajan" +bedwars.1410="heitti alas kuoppaan pelaajan" +bedwars.1411="heitti maahan pelaajan" +bedwars.1412="ampui pelaajan" +bedwars.1413="oli parempi kuin" +bedwars.1414="oli sänky #%%bed%% , jonka tuhosi" +bedwars.1415="Oikeuden miekka" +bedwars.1416=" - Luo hevonen oikeaklikkaamalla" +bedwars.1417="Sinulla on %%seconds%%s aikaa valita kumppanisi!" +bedwars.1418="Panssariisi kasvoi piikkejä!" +bedwars.1419="Vastaanotit uuden taistelupäivityksen! Lyöntisi ovat nyt vieläkin kuolettavampia!" +bedwars.1420="Vastaanotit uuden taistelupäivityksen! Lyöntisi ovat nyt kuolettavampia!" +bedwars.1421="Naamioiduit tiimin %%team%% pelaajaksi!" +bedwars.1422="Työkalusi %%tool%% päivitettiin!" +bedwars.1423="Sinulla on jo paras saatavilla oleva %%tool%%." +bedwars.1424="Vastaanotit ikuisen kirveen!" +bedwars.1425="Vastaanotit ikuisen hakun!" +bedwars.1426="MAAILMANLOPPU PELAAJALTA %%player%%" +bedwars.1427="Kopioit pelaajan %%player%% tavaraluettelon!" +bedwars.1428="%%player%% kopioi tavaraluettelosi!" +bedwars.1429="Aktivoit staasin kaikille pelaajille %%duration%% sekunnin ajaksi!" +bedwars.1430="sekuntia" +bedwars.1431="Edessäsi ei ole pelaajia!" +bedwars.1432="Käytit Voimaa!" +bedwars.1433="Staasi pelaajalta %%player%% %%time%% %%plural%% ajan!" +bedwars.1434="Pelaajan %%player%% voima työnsi sinua väkivaltaisesti!" +bedwars.1435="%%player%% KÄYTTI VOIMAA SINUA VASTAAN" +bedwars.1436="Sinun tulee tähdätä sopivaa kohdetta!" +bedwars.1437="Sijainti ei kelpaa, sotilas! Tähtää toisaalle!" +bedwars.1438="... VIESTI VASTAANOTETTU ... " +bedwars.1439="YDINISKU KOHDISTETTU SIJAINTIIN %%coords%%" +bedwars.1440="SUOSITELLAAN VÄLITÖNTÄ POISTUMISTA" +bedwars.1441="... VIESTI PÄÄTTYI ... " +bedwars.1442="☣ YDINKÄRJEN LAUKAISU HAVAITTU ☣" +bedwars.1443="PELAAJALTA %%player%%" +bedwars.1444="Räjähdit pelaajan %%player%% ydiniskussa!" +bedwars.1445="RAPORTTI YDINISKUSTA SIJAINNISSA %%coords%%" +bedwars.1446="EI KUOLONUHREJA! YRITÄ KOVEMPAA, SOTILAS!" +bedwars.1447="YKSI KUOLONUHRI. ENSI KERRALLA KOVEMMIN, SOTILAS!" +bedwars.1448="KAKSI KUOLONUHRIA. HIENOA TYÖTÄ, SOTILAS!" +bedwars.1449="USEITA VARMISTETTUJA KUOLONUHREJA. UPEAA TYÖTÄ, SOTILAS!" +bedwars.1450="VALTAVASTI VARMISTETTUJA KUOLONUHREJA. MAHTAVAA TYÖTÄ!" +bedwars.1451="Kuolit pelaajan %%player%% Rulettiblitzissä!" +bedwars.1452="Tapoit pelaajan %%player%% Rulettiblitzillä!" +bedwars.1453="Vampyyrin veri on ehtynyt!" +bedwars.1454="%%player%% TYHJENTÄÄ ELINVOIMAASI" +bedwars.1455="+%%size%% ep/s tyhjennetään: %%players%%" +bedwars.1456="Sinun tulee olla vähintään 20 palikan päässä tyhjentääksesi pelaajan elinvoimaa!" +bedwars.1457="Uskomatonta!" +bedwars.1458="HUOMIO! Voit valita vain yhden esineen! Valitse varoen!" +bedwars.1459="VAIN %%time%% SEKUNTIA JÄLJELLÄ USKOMATTOMASSA ARKUSSASI!" +bedwars.1460="Tämä ei ole sinun!" +bedwars.1461="%%player%% kirosi sinut!" +bedwars.1462="Lähistöllä ei ole vihollisten sänkyjä!" +bedwars.1463="%%time%% %%tool%%" +bedwars.1464="Kani puvussa" +bedwars.1465="Tammihalot" +bedwars.1466="Tammilankut" +bedwars.1467="Akaasiahalot" +bedwars.1468="Akaasialankut" +bedwars.1469="Koivuhalot" +bedwars.1470="Koivulankut" +bedwars.1471="Tummat tammihalot" +bedwars.1472="Tummat tammilankut" +bedwars.1473="Viidakkopuuhalot" +bedwars.1474="Viidakkopuulankut" +bedwars.1475="Kuusihalot" +bedwars.1476="Kuusilankut" +bedwars.1477="Puun tyyli" +bedwars.1478="Vaihda puun tyyliä pelissä." +bedwars.1479="Klassinen kaikkien tuntema ja rakastama 4v4 BedWars, mutta siinä on vain yksi vihollinen!" +bedwars.1480="Päivittäiset viimeistelyt" +bedwars.1481="Viimeistelyjen T/K-suhde" +bedwars.1482="Päivittäiset voitot" +bedwars.1483="Rush-tilastot" +bedwars.1484="Ultimate-tilastot" +bedwars.1485="Lucky-tilastot" +bedwars.1486="Voidless-tilastot" +bedwars.1487="Armed-tilastot" +bedwars.1488="Tiimin valinta (Oikeaklikkaa)" +bedwars.1489="Klikkaa valitaksesi tiimisi!" +bedwars.1490="Klikkaa ollaksesi katsoja" +bedwars.1491="Katsojat tällä hetkellä:" +bedwars.1492="Tiimin valinta" +bedwars.1493="Ei voi olla enemmän kuin 4 katsojaa!" +bedwars.1494="Sinusta tulee katsoja!" +bedwars.1495="Tämä tiimi on täynnä!" +bedwars.1496="%%color%% TIIMI" +bedwars.1497="Muumio" +bedwars.1498="Osto epäonnistui! Tavaraluettelosi on täynnä!" +bedwars.1499="Osta aseita Kaupoista tai Aselaatikosta!" +bedwars.1500="Ei löytynyt tiimiä sinulle!" +bedwars.1501="%%killer%% tuhosi sängyn" +bedwars.1502="VOITTOPUTKET POISSA KÄYTÖSTÄ" +bedwars.1503="Tässä aseessa ei ole ammuksia!" +bedwars.1504="Tällä tahdilla tasapeli tulee %%minutes%% minuutissa!" +bedwars.1505="Sinun sänkysi" +bedwars.1506="[Turnaus] Korkean sarjan pelejä pelataan tuntemattomana!" +bedwars.1507="%%color%%+%%amount%% timantti" +bedwars.1508="Ansajono on täynnä! Odota, että vihollispelaaja laukaisee ansan." +bedwars.1509="Aktivoi sarjavoima puolustaaksesi tiimisi tukikohtaa ja hyökätäksesi vihollistiimin kimppuun!" +bedwars.1510="Ei palautusoikeutta! Löydä äkkiä joku toinen, jolle antaa peruna!" +bedwars.1511="Et voi käyttää /shout -komentoa tässä pelimuodossa." +bedwars.1512="Sinun tulee kohdistaa pelaajaan! Loitsu tuhlattu!" +bedwars.1513="pelaajan %%killer%% viimeistelytappo #%%num%%" +bedwars.1514="Klikkaa vieraillaksesi Pankkiirin luona" +bedwars.1515="BED WARS -PANKKIIRI" +bedwars.1516="VASENKLIKKAA ladataksesi." +bedwars.1517="VALLATTU" +bedwars.1518="Hinta: %%cost%% smaragdi" +bedwars.1519="Käytä Pankkiiria varastoidaksesi resursseja koko tiimin käytettäväksi." +bedwars.1520="TURNAUS KÄYNNISSÄ!!!" +bedwars.1521="Voit kerätä sarjapisteitä tapoista sekä jakamalla resursseja." +bedwars.1522="Lue kaikki muutokset" +bedwars.1523="XP-kerroin: %%mult%%" +bedwars.1524="%%team%% voittaa %%time%% kuluttua" +bedwars.1525="En ymmärrä mihin maailmaan sinut tulisi asettaa (Pelaaja)!" +bedwars.1526="Turnaus" +bedwars.1527="Et voi vahingoittaa omaa sänkyäsi!" +bedwars.1528="Hyvää joulua! Lahjoja löytyy %%type%%generaattoreilta!" +bedwars.1529="Päivitetyt kaupat" +bedwars.1530="10s" +bedwars.1531="Tilastoja, saavutuksia ja tehtäviä EI ansaita yksityisissä peleissä!" +bedwars.1532="Bed Wars -voittoputkesi ei muutu tämän pelin aikana." +bedwars.1533="Voit käyttää sarjavoimia vain Castle-pelimuodossa!" +bedwars.1534="Laukaisit pelaajan %%owner%% %%type%%ansan!" +bedwars.1535="Olet jo lunastanut enimmäismäärän lahjoja tässä pelissä!" +bedwars.1536=" Bed Wars v1.4" +bedwars.1537="Kurpitsasi rekisteröitiin automaattisesti voittaessasi!" +bedwars.1538="Tätä ei voi asettaa maahan! Tuo se takaisin kauppiaalle!" +bedwars.1539="Jäljitetään: " +bedwars.1540="Sinut teleportattiin pelaajan %%name%% luo!" +bedwars.1541="Sinut lähetettiin lobbyyn, koska joku partystasi poistui!" +bedwars.1542="Valtaa piste, jotta voit syntyä uudelleen!" +bedwars.1543="Kaivospäivitys II" +bedwars.1544="%%reason%%Tapahtui virhe jaettaessa joitain Tribuuttejasi!" +bedwars.1545="Et voi asettaa tätä lumousta!" +bedwars.1546="%%team%% voittaa %%minutes%% minuutin kuluttua!" +bedwars.1547="Jokin meni vikaan! Ilmoita tästä ylläpidolle!" +bedwars.1548="Hälytysansa poisti näkymättömyytesi!" +bedwars.1549="Tasapeli %%time%% kuluttua" +bedwars.1550="%%player%% lunasti lahjoja!" +bedwars.1551="Pelaajan %%name%% Ender-arkun sisältö tiputettiin tämän suihkulähteeseen." +bedwars.1552="Joku laukaisi louhintauupumusansasi!" +bedwars.1553="Näyttää siltä, että olet tiputtanut esineen paikkaan, josta et saa sitä takaisin! Esine on palautettu tavaraluetteloosi!" +bedwars.1554="%%count%% elossa" +bedwars.1555="Creeper-armeija" +bedwars.1556="Myrkkynuoli" +bedwars.1557="Kaivokset tuottavat nyt smaragdeja!" +bedwars.1558="Halloweentapahtuma" +bedwars.1559="Teleporttaa lähistöllä olevat viholliset takaisin tukikohtiinsa!" +bedwars.1560="Palikat" +bedwars.1561="Tämä komento on poissa käytöstä, kun olet pelaaja." +bedwars.1562="Pelaajan %%killer%% viimeistely" +bedwars.1563="%%team%% tiimi menetti hallintapisteen!" +bedwars.1564="Tässä ei ole tarpeeksi tilaa!" +bedwars.1565="Voittoputket ovat toistaiseksi poissa käytöstä huoltokatkon ajan!" +bedwars.1566="Sielu revitty" +bedwars.1567="Voit käyttää Pankkiiria vain Castle-pelimuodossa!" +bedwars.1568="Viimeinen hallintapiste menetetty" +bedwars.1569="Sängyn tuhosi %%killer%%" +bedwars.1570="Kiitos!" +bedwars.1571="Olet jo tiimissä %%color%%%%colorname%%!" +bedwars.1572="Tällä pelaajalla on jo aktiivinen Kuuma peruna! Etsi joku toinen!" +bedwars.1573="Ei dream-pelimuotoja saatavilla juuri nyt!" +bedwars.1574="Tämä ase on... siis mikä?" +bedwars.1575="pelaajalta %%who%%" +bedwars.1576="Et voi lunastaa tätä vielä!" +bedwars.1577="(Oikeaklikkaa kohdetta)" +bedwars.1578="Tuo lahjoja mille tahansa kauppiaalle." +bedwars.1579="Sänkysi on hyökkäyksen kohteena!" +bedwars.1580="%%player%% lunasti lahjan!" +bedwars.1581="XP-kerroin: %%mult%%" +bedwars.1582="Voita kuluttamalla vihollistiimin elinvoimaa tai tappamalla pelaajia." +bedwars.1583="v1.4 Ominaisuudet:" +bedwars.1584="Sinulla on kuuma peruna! Äkkiä lyö jotakuta antaaksesi sen eteenpäin!" +bedwars.1585="UUDELLEENÄÄNESTYS!" +bedwars.1586="Chat on poissa käytöstä odotusaulassa tässä sarjassa!" +bedwars.1587="En löydä peliä kyseisestä maailmasta!" +bedwars.1588="Klikkaa tarkastellaksesi Sarjoja" +bedwars.1589="NÄYTÄ SARJAT" +bedwars.1590="Palaa kategorioihin!" +bedwars.1591="Takaisin" +bedwars.1592="Sinulla on jo ylimääräinen sänky!" +bedwars.1593="Uusia ansoja" +bedwars.1594="Pidä silmällä tiimisi elinvoimaa." +bedwars.1595="Yhteytesi katkaistiin, sillä et tehnyt mitään! " +bedwars.1596="Ammuit juuri PÄÄOSUMAN!" +bedwars.1597="%%trap%% -ansa on asetettu tiimillesi!" +bedwars.1598="Et voi tyhjentää ämpäreitä tässä!" +bedwars.1599="Lunastit lahjoja!" +bedwars.1600="Tiimi: %%team%%" +bedwars.1601="Lucky Blocks" +bedwars.1602="Taso: %%format%%" +bedwars.1603="Katso peliä" +bedwars.1604="En ymmärrä mihin maailmaan sinut tulisi asettaa (World)!" +bedwars.1605="VALLATAAN" +bedwars.1606="%%color%%%%colorname%% tiimi on täynnä!" +bedwars.1607="Ase #%%number%%" +bedwars.1608="Liityit tiimiin %%color%%%%colorname%%!" +bedwars.1609="Capture-pelimuodon betaversio." +bedwars.1610="Olet liittynyt käynnissä olevaan peliin! Bed Wars Castle tukee jatkuvaa liittymistä parhaan kokemuksen takaamiseksi!" +bedwars.1611="En löydä maailmaa johon sinut tulisi lähettää!" +bedwars.1612="Turnauspelin myöhäinen aloitus..." +bedwars.1613="Olit pelaaja ja katsoja, olet nyt katsoja." +bedwars.1614="Awww!" +bedwars.1615="Taikajuomat" +bedwars.1616="Bed Wars BETA (%%mode%%)" +bedwars.1617="Viimeinen piste menetetty" +bedwars.1618="%%count%% osumaa! Myrkytit pelaajat %%players%%!" +bedwars.1619="Bed Wars Capture on tällä hetkellä suljettu!" +bedwars.1620="%%color%%+ %%amount%% sänky" +bedwars.1621="Sarja: %%bracket%%" +bedwars.1622="Myrkytit pelaajan %%player%%!" +bedwars.1623="Voidaksesi syntyä uudelleen tarvitset ainakin yhden hallintapisteen." +bedwars.1624="(BETA)" +bedwars.1625="Saat hälytyksen vihollisten tunkeutuessa tukikohtaasi, kun vihollisesi sokeutuvat neljäksi sekunniksi!" +bedwars.1626="Hype: %%hype%%/%%maxHype%%" +bedwars.1627="Laukaise" +bedwars.1628="Kiitos kun pelaat betaversiota v1.4. Seuraavat ominaisuudet ovat käytössä kaikissa pelimuodoissa:" +bedwars.1629="Paranna itsesi" +bedwars.1630="%%team%% tiimi valtasi hallintapisteen!" +bedwars.1631="Tiimisi on päivittänyt tämän korkeimmalle tasolle!" +bedwars.1632="➜ %%count%%x %%name%%: %%rewards%%" +bedwars.1633="Bed Wars -voittoputkeasi ei nollattu käynnissä olevan huoltokatkon vuoksi!" +bedwars.1634="Bzzzzz!" +bedwars.1635="Tarvitset %%cost%% %%resource%%a! Sinulla on %%count%% %%resource%%a!" +bedwars.1636="Pelaajia nyt:" +bedwars.1637="Louhinnan tuottavuus kaksinkertaistui!" +bedwars.1638="Synnyt uudelleen kun tiimisi valtaa pisteen!" +bedwars.1639="%%team%% tiimi valtasi %%resource%%generaattorin!" +bedwars.1640="Aseet tekevät enemmän vahinkoa koko tiimissäsi" +bedwars.1641="Odottaa uudelleensyntymistä!" +bedwars.1642="Käytä sänkyjä vallataksesi pisteitä ja puolusta niitä." +bedwars.1643="Kuuma peruna räjähti!" +bedwars.1644="Ole hyvä!" +bedwars.1645="Oikeaklikkaa liittyäksesi tähän tiimiin!" +bedwars.1646="Saat sarjapisteitä resurssien jakamisesta (ja tietysti teet samalla tiimitoverisi onnellisiksi)" +bedwars.1647="%%team%% tiimi kaappasi %%resource%%generaattorin tiimitä %%from%%!" +bedwars.1648="Tuliaseet tekevät %%tier%%% enemmän vahinkoa" +bedwars.1649="NÄYTÄ PANKKIIRI" +bedwars.1650="Hypixelissä" +bedwars.1651="R.I.P. %%victim%%" +bedwars.1652="Turnauksen ensimmäinen voitto" +bedwars.1653="Voit jäljittää vihollistiimiä ostamalla jäljityskompassin!" +bedwars.1654="Työkalut" +bedwars.1655="[Turnaus] Tässä pelissä sinut tunnetaan nimellä: %%name%%" +bedwars.1656="Pelaaja %%player%% myrkytti sinut!" +bedwars.1657="Kaivospäivitys I" +bedwars.1658="%%player%% laukaisi %%type%%ansasi!" +bedwars.1659="TNT-suihkulähde" +bedwars.1660="%%team%% voittaa %%minutes%% minuutin kuluttua!" +bedwars.1661="Tätä asetta ei ole olemassa" +bedwars.1662="Et voi rakentaa enää alemmas!" +bedwars.1663="Wheee!" +bedwars.1664="TuplaXP Turnauksen ajan" +bedwars.1665="Aseta sänky vallataksesi!" +bedwars.1666="Bed Wars -voittoputkesi ei kasvanut käynnissä olevan huoltokatkon vuoksi!" +bedwars.1667="TULEVA TURNAUS!" +bedwars.1668="Pelaa Bed Wars v%%version%%" +bedwars.1669="Maailman rajat kutistuvat..." +bedwars.1670="Pankkiiri" +bedwars.1671="Louhinnan tuottavuus kasvoi 50%!" +bedwars.1672="Uusia karttoja" +bedwars.1673="Antaa 10 sekunnin Nopeus I ja Hyppytehostus II -vaikutukset tukikohtasi lähellä oleville tiimikavereille." +bedwars.1674="Sinut asetetaan AFK-tilaan 10 sekunnin kuluttua!" +bedwars.1675="Sinun tulee odottaa %%seconds%% sekuntia chat-viestien välissä Castle-pelimuodossa!" +bedwars.1676="%%color%%+%%amount%% sänkyä" +bedwars.1677="Ei löydetty peliä sinulle :(" +bedwars.1678="5% perkistä" +bedwars.1679="Laukaisit pelaajan %%player%% ilmaan!" +bedwars.1680="◼ 40+ kosmeettista esinettä" +bedwars.1681="Et osunut yhteenkään pelaajaan! Loitsu tuhlattu!" +bedwars.1682="Sinulla ei ole tarpeeksi smaragdeja!" +bedwars.1683="%%trap%% -ansa on asetettu tiimillesi!" +bedwars.1684=" HYVÄÄ PÄÄSIÄISTÄ" +bedwars.1685="VIHOLLISELLA EI OLE HALLINTAPISTEITÄ" +bedwars.1686="Tämä peli on pregame-vaiheessa! Käytä /tpto -f %%name%% sivuuttaaksesi tämän varoituksen!" +bedwars.1687="Maksimipäivitys!" +bedwars.1688="Joku laukaisi louhintauupumusansasi!" +bedwars.1689="Vihollissänky" +bedwars.1690="Imit jätin voimat väliaikaisesti!" +bedwars.1691="Lahja lunastettu!" +bedwars.1692="Ostit esineen %%ict%% %%name%% hintaan %%cost%% %%resource%%! Sinulla on %%count%% %%resource%%!" +bedwars.1693="%%distance%%m" +bedwars.1694="Villikorttisi pelasti sinut kuolemalta!" +bedwars.1695="Poimittiin joululahja!" +bedwars.1696="Klikkaa lähettääksesi viestin: \"%%option%%\"" +bedwars.1697="Tarvitset %%ct%% %%resource%% ostaaksesi tämän!" +bedwars.1698="Sinulla ei ole tätä lumousta tukevaa esinettä!" +bedwars.1699="Panssari" +bedwars.1700="Hämähäkin koti!" +bedwars.1701="Kaivospäivitys III" +bedwars.1702="Odotetaan uudelleensyntymistä" +bedwars.1703="Ei pelaajia elossa!" +bedwars.1704="Pelaaja %%player%% laukaisi sinut ilmaan!" +bedwars.1705="Tuplaosuma! Myrkytit pelaajat %%players%%!" +bedwars.1706="Et voi täyttää ämpäreitä!" +bedwars.1707="pelaajalta %%player%%" +bedwars.1708="Bed Wars beta on tällä hetkellä suljettu!" +bedwars.1709="Tapa kaikki pelaajat voittaaksesi!" +bedwars.1710="%%tc%%%%name%% liittyi takaisin." +bedwars.1711="Aiheuttaa sokeuden ja hitauden kahdeksaksi sekunniksi." +bedwars.1712="%%name%% -käärö" +bedwars.1713="SÄNKY LUOTU > %%player%% on asettanut ylimääräisen tiimin %%bed%% sängyn" +bedwars.1714="Tämä lobby on juuri nyt suljettu." +bedwars.1715="%%name%% potkittiin ulos, sillä hän oli AFK!" +bedwars.1716="Tällä tahdilla tasapeli tulee %%minutes%% minuutissa!" +bedwars.1717="Aaaauu!" +bedwars.1718="Jouset" +bedwars.1719="BED WARS -SARJAT" +bedwars.1720="Ei ole numero! Emme halua blockX määrää pelaajia. Olemme kyllästyneet algebraan." +bedwars.1721="Bed Wars 4v4 on tällä hetkellä suljettu!" +bedwars.1722="4v4" +bedwars.1723="Sinun tulee tähdätä johonkin! Loitsu tuhlattu!" +bedwars.1724="LAUKAISTU!" +bedwars.1725="Tämä palikka ei ole pelaajan asettama!" +bedwars.1726="Vihollispisteitä menetetty" +bedwars.1727="Tämä esine on jo asetettu suosikiksi!" +bedwars.1728="Vihollinen on tunkeutunut tukikohtaasi!" +bedwars.1729="%%color%%%%colorname%% tiimi" +bedwars.1730="Aseet" +bedwars.1731="Virhe! Ei löydetä BedGamea. Käytä komentoa /whereami ja ilmoita sen syöte ylläpidon jäsenelle!" +bedwars.1732="Tiimisi jaettiin tasapainotussyistä." +bedwars.1733="Pum!" +bedwars.1734="Sekalaiset" +bedwars.1735="Illuusioansa teleporttasi sinut takaisin saarellesi!" +bedwars.1736="Rakentamisen korkeusraja saavutettu!" +bedwars.1737="Bed Wars Capture" +bedwars.1738="Jokin meni vikaan joten sinut poistettiin pelistä! Ilmoitathan tästä ylläpidon jäsenelle! [PGS-SPEC]" +bedwars.1739="pelaajan %%player%% hevonen" +bedwars.1740="%%color%%+ %%amount%% smaragdi" +bedwars.1741="Klikkaa palikkaa asettaaksesi witherin!" +bedwars.1742="Enimmäispelaajamääräksi on nyt asetettu %%GameManager%%" +bedwars.1743="Sängyn elinvoima: %%health%%" +bedwars.1744="Virhe tapahtui istunnossasi!" +bedwars.1745="Olet parantanut itsesi täyteen elinvoimaasi!" +bedwars.1746="Et voi pudottaa lahjoja!" +bedwars.1747="Tadada!" +bedwars.1748="[Turnaus] Voit edelleen käyttää komentoa /wdr tuntemattomiin pelaajiin!" +bedwars.1749="OIKEAKLIKKAA ampuaksesi." +bedwars.1750="Pistooli" +bedwars.1751="Magnum" +bedwars.1752="Kivääri" +bedwars.1753="Ei-liekinheitin" +bedwars.1754="Haulikko" +bedwars.1755="Ylösalainen lumiukko" +bedwars.1756="Lahjaukko" +bedwars.1757="Virhe lunastettaessa lahjoja: Ei peliä!" +bedwars.1758="Virhe lunastettaessa lahjoja: Ei tiimiä!" +bedwars.1759="Pelaajan %%killer%% %%mob%% tappoi pelaajan %%player%%." +bedwars.1760="Sinun %%bed%% tuhottiin pelaajan %%killer%% toimesta!" +bedwars.1761="%%team%% %%bed%% tuhottiin pelaajan %%killer%% toimesta!" +bedwars.1762="%%killer%% ampui pelaajan %%player%%." +bedwars.1763="%%killer%% tönäisi pelaajan %%player%% alas kalliolta." +bedwars.1764="%%team%% on eliminoitu!" +bedwars.1765="%%killer%% iski maahan pelaajan %%player%%." +bedwars.1766="%%killer%% muutti pölyksi pelaajan %%player%%." +bedwars.1767="%%killer%% poltti tuhkaksi pelaajan %%player%%." +bedwars.1768="%%killer%% sulatti pelaajan %%player%%." +bedwars.1769="Pelaajan %%killer%% %%mob%% paistoi pelaajan %%player%%." +bedwars.1770="Sinun %%bed%% poltettiin pelaajan %%killer%% toimesta!" +bedwars.1771="%%team%% %%bed%% poltettiin pelaajan %%killer%% toimesta!" +bedwars.1772="%%killer%% täytti lyijyllä pelaajan %%player%%." +bedwars.1773="%%killer%% päätti pelaajan %%player%% elämän." +bedwars.1774="%%killer%% voitti juomapelin pelaajaa %%player%% vastaan." +bedwars.1775="%%killer%% räjäytti dynamiitilla pelaajan %%player%%." +bedwars.1776="Pelaajan %%killer%% %%mob%% voitti arvonnan pelaajaa %%player%% vastaan." +bedwars.1777="Sinun %%bed%% jäädytettiin pelaajan %%killer%% toimesta!" +bedwars.1778="%%team%% %%bed%% jäädytettiin pelaajan %%killer%% toimesta!" +bedwars.1779="%%killer%% antoi kylmää kättä pelaajalle %%player%%." +bedwars.1780="%%killer%% heitti rakkauspommilla pelaajaa %%player%%." +bedwars.1781="%%killer%% oli paljon parempi kuin pelaaja %%player%%." +bedwars.1782="%%killer%% ampui pelaajaa %%player%% Amorin nuolella." +bedwars.1783="Pelaajan %%killer%% %%mob%% päihitti pelaajan %%player%%." +bedwars.1784="Sinun %%bed%% hajotettiin osiin pelaajan %%killer%% toimesta!" +bedwars.1785="%%team%% %%bed%% hajotettiin osiin pelaajan %%killer%% toimesta!" +bedwars.1786="%%killer%% lähetti pelaajan %%player%% Ahdin valtakuntaan." +bedwars.1787="%%killer%% tykitti pelaajan %%player%% kuoliaaksi." +bedwars.1788="%%killer%% tappoi taialla pelaajan %%player%%." +bedwars.1789="%%killer%% ampui kylmäverisesti pelaajan %%player%%." +bedwars.1790="Pelaajan %%killer%% %%mob%% tappoi miekalla pelaajan %%player%%." +bedwars.1791="Sinun %%bed%% ammuttiin kanuunalla pelaajan %%killer%% toimesta!" +bedwars.1792="%%team%% %%bed%% ammuttiin kanuunalla pelaajan %%killer%% toimesta!" +bedwars.1793="%%killer%% maustoi grillikastikkeella pelaajan %%player%%." +bedwars.1794="%%player%% liukastui pelaajan %%killer%% läikyttämään grillikastikkeeseen." +bedwars.1795="%%killer%% maustoi vahvasti pelaajan %%player%%." +bedwars.1796="%%killer%% heitti chilijauhetta pelaajan %%player%% kasvoille." +bedwars.1797="Pelaajan %%killer%% %%mob%% viipaloi pelaajan %%player%%." +bedwars.1798="Sinun %%bed%% uppopaistettiin pelaajan %%killer%% toimesta!" +bedwars.1799="%%team%% %%bed%% uppopaistettiin pelaajan %%killer%% toimesta!" +bedwars.1800="%%killer%% säikäytti pelaajan %%player%% kuoliaaksi." +bedwars.1801="%%killer%% pelästytti pelaajan %%player%% alas kartan reunalta." +bedwars.1802="%%killer%% todella säikäytti pelaajan %%player%%." +bedwars.1803="%%killer%% melkein säikäytti pelaajan %%player%%." +bedwars.1804="Pelaajan %%killer%% %%mob%% säikäytti pelaajan %%player%%." +bedwars.1805="Sinun %%bed%% pelästytettiin rikki pelaajan %%killer%% toimesta!" +bedwars.1806="%%team%% %%bed%% pelästytettiin rikki pelaajan %%killer%% toimesta!" +bedwars.1807="%%killer%% paketoi pelaajan %%player%% lahjaksi." +bedwars.1808="%%killer%% iski pelaajan %%player%% kovalle puulattialle." +bedwars.1809="%%killer%% tönäisi pelaajan %%player%% mäkeä alas." +bedwars.1810="%%killer%% kirjoitti pelaajan %%player%% nimen tuhmien listaan." +bedwars.1811="Pelaajan %%killer%% %%mob%% muutti pelaajan %%player%% piparkakku-ukoksi." +bedwars.1812="Sinun %%bed%% vaihdettiin maitoon ja kekseihin pelaajan %%killer%% toimesta!" +bedwars.1813="%%team%% %%bed%% vaihdettiin maitoon ja kekseihin pelaajan %%killer%% toimesta!" +bedwars.1814="%%killer%% rektasi pelaajan %%player%%." +bedwars.1815="%%killer%% teki luuserin pelaajasta %%player%%." +bedwars.1816="%%killer%% roastasi pelaajan %%player%%." +bedwars.1817="%%killer%% läimäisi pelaajaa %%player%%." +bedwars.1818="Pelaajan %%killer%% %%mob%% hämäsi pelaajaa %%player%%." +bedwars.1819="Sinun %%bed%% muutettiin meemiksi pelaajan %%killer%% toimesta!" +bedwars.1820="%%team%% %%bed%% muutettiin meemiksi pelaajan %%killer%% toimesta!" +bedwars.1821="%%killer%% puraisi pelaajaa %%player%%." +bedwars.1822="%%killer%% ulvoi pelaajan %%player%% tyhjyyteen." +bedwars.1823="%%killer%% hämäsi pelaajaa %%player%% pienellä koiranpennulla." +bedwars.1824="%%killer%% heitti pallon pelaajalle %%player%%." +bedwars.1825="Pelaajan %%killer%% %%mob%% käsitteli liian rajusti pelaajaa %%player%%." +bedwars.1826="Sinun %%bed%% revittiin kappaleiksi pelaajan %%killer%% toimesta!" +bedwars.1827="%%team%% %%bed%% revittiin kappaleiksi pelaajan %%killer%% toimesta!" +bedwars.1828="%%player%% kuoli lähitaistelussa pelaajalle %%killer%%." +bedwars.1829="%%killer%% ajoi pelaajan %%player%% liian lähelle reunaa." +bedwars.1830="%%killer%% auttoi pelaajan %%player%% alas kielekkeeltä." +bedwars.1831="Pelaajan %%killer%% %%mob%% tanssi tangoa pelaajan %%player%% kanssa." +bedwars.1832="Sinun %%bed%% joutui antautumaan pelaajalle %%killer%%!" +bedwars.1833="%%team%% %%bed%% joutui antautumaan pelaajalle %%killer%%!" +bedwars.1834="%%killer%% metsästi pelaajan %%player%%." +bedwars.1835="%%killer%% asetti ansan pelaajalle %%player%%." +bedwars.1836="%%killer%% heitti pelaajan %%player%% tulivuoreen." +bedwars.1837="%%killer%% seivästi pelaajan %%player%%." +bedwars.1838="Pelaajan %%killer%% %%mob%% murjoi pelaajan %%player%%." +bedwars.1839="Sinun %%bed%% uhrattiin pelaajan %%killer%% toimesta!" +bedwars.1840="%%team%% %%bed%% uhrattiin pelaajan %%killer%% toimesta!" +bedwars.1841="%%killer%% puukotti traagisesti selkään pelaajaa %%player%%." +bedwars.1842="%%killer%% sydämettömästi murhasi pelaajan %%player%%." +bedwars.1843="%%killer%% lähetti pelaajan %%player%% olemattomuuteen." +bedwars.1844="Pelaajan %%killer%% %%mob%% teilasi pelaajan %%player%%." +bedwars.1845="Sinun %%bed%% korruptoitiin kammottavasti pelaajan %%killer%% toimesta!" +bedwars.1846="%%team%% %%bed%% korruptoitiin kammottavasti pelaajan %%killer%% toimesta!" +bedwars.1847="%%killer%% lukitsi pelaajan %%player%% ulos lumimyrskyn keskelle." +bedwars.1848="%%killer%% tönäisi pelaajan %%player%% lumipenkkaan." +bedwars.1849="%%killer%% työnsi pelaajan %%player%% jäistä rinnettä alas." +bedwars.1850="%%killer%% heitti lumipallolla pelaajaa %%player%%." +bedwars.1851="Pelaajan %%killer%% %%mob%% hukutti lumeen pelaajan %%player%%." +bedwars.1852="Sinun %%bed%% muutettiin lumiukoksi pelaajan %%killer%% toimesta!" +bedwars.1853="%%team%% %%bed%% muutettiin lumiukoksi pelaajan %%killer%% toimesta!" +bedwars.1854="%%killer%% röhkäisi pelaajalle %%player%%." +bedwars.1855="%%killer%% sai pelaajan %%player%% liukastumaan tyhjyyteen." +bedwars.1856="%%killer%% hämäsi pelaajaa %%player%% pikku possulla." +bedwars.1857="%%killer%% heitti porkkanalla pelaajaa %%player%%." +bedwars.1858="Pelaajan %%killer%% %%mob%% röhkäisi pelaajalle %%player%%." +bedwars.1859="Sinun %%bed%% nielaistiin pelaajan %%killer%% toimesta!" +bedwars.1860="%%team%% %%bed%% nielaistiin pelaajan %%killer%% toimesta!" +bedwars.1861="%%killer%% talloi jalkoihinsa pelaajan %%player%%." +bedwars.1862="%%killer%% heitti pelaajan %%player%% alas kuoppaan." +bedwars.1863="%%killer%% heitti maahan pelaajan %%player%%." +bedwars.1864="%%killer%% ampui pelaajan %%player%%." +bedwars.1865="Pelaajan %%killer%% %%mob%% oli parempi kuin %%player%%." +bedwars.1866="%%killer%% murskasi pelaajan %%player%%." +bedwars.1867="%%killer%% dominoi pelaajaa %%player%%." +bedwars.1868="%%killer%% palautti pelaajan %%player%% takaisin maan pinnalle." +bedwars.1869="%%killer%% salamurhasi pelaajan %%player%%." +bedwars.1870="Pelaajan %%killer%% %%mob%% solvasi pelaajaa %%player%%." +bedwars.1871="%%killer%% pureskeli pelaajan %%player%%." +bedwars.1872="%%killer%% säikäytti pelaajan %%player%% tyhjyyteen." +bedwars.1873="%%killer%% hämäsi pelaajaa %%player%% rotalla, joka raahaa pizzaa perässään." +bedwars.1874="%%killer%% asetti hiirenloukun pelaajalle %%player%%." +bedwars.1875="Pelaajan %%killer%% %%mob%% vikisi pelaajalle %%player%%." +bedwars.1876="Sinun %%bed%% vinkaistiin kappaleiksi pelaajan %%killer%% toimesta!" +bedwars.1877="%%team%% %%bed%% vinkaistiin kappaleiksi pelaajan %%killer%% toimesta!" +bedwars.1878="%%killer%% maalasi nätiksi pelaajan %%player%%." +bedwars.1879="%%killer%% teki täytetyn munan pelaajasta %%player%%." +bedwars.1880="%%killer%% käänsi pelaajan %%player%% alas reunalta." +bedwars.1881="%%killer%% löi paistinpannulla pelaajaa %%player%%." +bedwars.1882="Pelaajan %%killer%% %%mob%% paistoi pelaajan %%player%% vain yhdeltä puolelta." +bedwars.1883="Sinun %%bed%% paistettiin kaikilla mausteilla pelaajan %%killer%% toimesta!" +bedwars.1884="%%team%% %%bed%% paistettiin kaikilla mausteilla pelaajan %%killer%% toimesta!" +bedwars.1885="%%killer%% surisi kuoliaaksi pelaajan %%player%%." +bedwars.1886="%%killer%% bzzz pelaajan %%player%% tyhjyyteen." +bedwars.1887="%%killer%% pisti pelaajan %%player%% alas reunalta." +bedwars.1888="%%killer%% hätkähdytti pelaajan %%player%%." +bedwars.1889="Pelaajan %%killer%% %%mob%% muutti pelaajan %%player%% mehiläiseksi." +bedwars.1890="Sinun %%bed%% pistettiin hajalle pelaajan %%killer%% toimesta!" +bedwars.1891="%%team%% %%bed%% pistettiin hajalle pelaajan %%killer%% toimesta!" +bedwars.1892="%%killer%% mätki juhlailmapallolla kuoliaaksi pelaajan %%player%%." +bedwars.1893="%%killer%% pamautti pelaajan %%player%% tyhjyyteen." +bedwars.1894="%%killer%% räjäytti raketin lailla pelaajan %%player%%." +bedwars.1895="%%killer%% ampui roomalaisella kynttilällä pelaajaa %%player%%." +bedwars.1896="Pelaajan %%killer%% %%mob%% sytytti tuleen pelaajan %%player%%." +bedwars.1897="Sinun %%bed%% räjäytettiin raketilla pelaajan %%killer%% toimesta!" +bedwars.1898="%%team%% %%bed%% räjäytettiin raketilla pelaajan %%killer%% toimesta!" +bedwars.1899="%%killer%% paketoi pelaajan %%player%%." +bedwars.1900="%%killer%% kietoi rusetille pelaajan %%player%%." +bedwars.1901="%%killer%% heitti pelaajaa %%player%% lahjapaketilla." +bedwars.1902="%%killer%% liimasi pelaajan %%player%%." +bedwars.1903="Pelaajan %%killer%% %%mob%% teippasi pelaajan %%player%%." +bedwars.1904="Sinun %%bed%% täytettiin lahjapaperilla pelaajan %%killer%% toimesta!" +bedwars.1905="%%team%% %%bed%% täytettiin lahjapaperilla pelaajan %%killer%% toimesta!" +bedwars.1906="%%colorName%% tiimi" +bedwars.1907="SÄNKY TUHOTTU > %%killMessage%%" +bedwars.1908="TIIMI ELIMINOITU > %%killMessage%%" +bedwars.1909="viimeistelyjesi sekä rikkomiesi." +bedwars.1910="sänkyjen määrän." +bedwars.1911="Sinun %%bed%% oli #%%stat%% pelaajan %%killer%% tuhoama sänky!" +bedwars.1912="%%team%% %%bed%% oli #%%stat%% pelaajan %%killer%% tuhoama sänky!" +bedwars.1913="%%killer%% hankki viimeistelyn #%%stat%% pelaajasta %%player%%." +bedwars.1914="%%killer%% päihitti pelaajan %%player%%." +bedwars.1915="%%killer%% tönäisi pelaajan %%player%% tyhjyyteen." +bedwars.1916="%%killer%% työnsi pelaajan %%player%% alas reunalta." +bedwars.1917="%%killer%% ampui pelaajan %%player%%." +bedwars.1918="Pelaajan %%killer%% %%mob%% päihitti pelaajan %%player%%." +bedwars.1919="Klikkaa liittyäksesi tiimiin %%team%%." +bedwars.1920="Crosstiimaus ei ole sallittua! Ilmianna näin tekevät henkilöt komennolla /report." +bedwars.1921="Sänkyjen tila: %%beds%%" +bedwars.1922="Jokin meni vikaan sänkyä rikottaessa, ilmoitathan tästä osoitteessa https://hypixel.net/bugs! Sisällytä ilmoitukseesi seuraava virhekoodi: BW_BED_CASH" +bedwars.1923="%%tc%%%%team%% voitti!" +bedwars.1924="%%bed%%sänky %%team%% tiimi laukaisi hälytysansasi!" +bedwars.1925="%%bed%%sänky: Tiimin %%team%% pelaaja %%player%% laukaisi Hälytysansan!" +bedwars.1926=" Bed Wars XP" +bedwars.1927="Kenguru" +bedwars.1928=" Armed" +bedwars.1929="Vihollistiimi" +bedwars.1930="1. valtaus" +bedwars.1931="%%magic%%MN TASON NOUSU! Olet nyt kunniatasolla %%prestige%%! %%magic%%NM" +bedwars.1932="Seuraat jo tätä tiimiä!" +bedwars.1933="Voidless" +bedwars.1934="BED WARS COMP" +bedwars.1935="BED WARS CAPTURE" +bedwars.1936="Hyvää joulua ja onnellista uutta vuotta" +bedwars.1937="Pelaaja" +bedwars.1938="3. valtaus" +bedwars.1939="TASAPELI!" +bedwars.1940="Kunniataso" +bedwars.1941="Osta seurantapäivitys kompassiisi, ja voit jäljittää tietyn tiimin lähintä pelaajaa, kunnes kuolet." +bedwars.1942="2. valtaus" +bedwars.1943="SULJETTU" +bedwars.1944="4v4" +bedwars.1945=" Lucky Blocks V2" +bedwars.1946="Tiimisi" +bedwars.1947="Et menetä tätä kuollessasi!" +bedwars.1948="Se on ansa!" +bedwars.1949="Siltamuna" +bedwars.1950="Punainen tiimi" +bedwars.1951="Sininen tiimi" +bedwars.1952="Vihreä tiimi" +bedwars.1953="Keltainen tiimi" +bedwars.1954="Vaaleansininen tiimi" +bedwars.1955="Valkoinen tiimi" +bedwars.1956="Vaaleanpunainen tiimi" +bedwars.1957="Harmaa tiimi" +bedwars.1958="Sähikäinen" +bedwars.1959="Punainen kirjekuori" +bedwars.1960="%%killer%% murskasi kuupölyksi pelaajan %%player%%." +bedwars.1961="%%killer%% lähetti pelaajan %%player%% väärään suuntaan." +bedwars.1962="%%killer%% laukaisi pelaajan %%player%% kuuhun." +bedwars.1963="%%killer%% iski asteroidilla pelaajaa %%player%%." +bedwars.1964="Pelaajan %%killer%% %%mob%% räjäytti pelaajan %%player%%." +bedwars.1965="Sinun %%bed%% räjäytettiin tuhkaksi pelaajan %%killer%% toimesta!" +bedwars.1966="%%killer%% talloi pelaajan %%player%% jalkoihinsa." +bedwars.1967="%%killer%% potkaisi pelaajan %%player%% tyhjyyteen." +bedwars.1968="%%killer%% puski pelaajan %%player%% alas kalliolta." +bedwars.1969="%%killer%% lävisti kaukaa pelaajan %%player%%." +bedwars.1970="Pelaajan %%killer%% %%mob%% talloi pelaajan %%player%%." +bedwars.1971="Sinun %%bed%% lävistettiin pelaajan %%killer%% toimesta!" +bedwars.1972="%%team%% %%bed%% räjäytettiin tuhkaksi pelaajan %%killer%% toimesta!" +bedwars.1973="%%team%% %%bed%% lävistettiin pelaajan %%killer%% toimesta!" +bedwars.1974="Puun tyylit" +bedwars.1975="Valitse '%%category%%: %%name%%', jota käytät asettaessasi puupalikoita." +bedwars.1976="Noidan taikajuoma" +bedwars.1977="Siltamuna" +bedwars.1978="Kompakti pikatorni" +bedwars.1979="Rusettimuna" +bedwars.1980="Pääsiäispulla" +bedwars.1981="Pääsiäiskukka" +bedwars.1982="Suklaamuna" +bedwars.1983="Sininen lammaspyjama" +bedwars.1984="Violetti possupyjama" +bedwars.1985="Vaaleansininen ankkapyjama" +bedwars.1986="Punainen sammakkopyjama" +bedwars.1987="Vaaleanpunainen pupupyjama" +bedwars.1988="Vihreä lehmäpyjama" +bedwars.1989="Pinkki kani" +bedwars.1990="Sininen kani" +bedwars.1991="Myrskyinen sängyntuhoamisefekti" +bedwars.1992="Ei voitu asettaa sinua tiimiin %%team%%!" +bedwars.1993="Liityit tiimiin %%team%%!" +bedwars.1994="Olet jo tiimissä %%team%%!" +bedwars.1995="Practice" +bedwars.1996="Kehitä pelitaitojasi harjoittelemalla Bed Warsin eri osa-alueita!" +bedwars.1997="Klikkaa näyttääksesi pelimuodot!" +bedwars.1998="Ydinpelimuodot" +bedwars.1999="4 Team -pelimuodot" +bedwars.2000="Loputon!" +bedwars.2001="Tiimisi hakeminen ei onnistu?!" +bedwars.2002="Toisen mahdollisuuden tikku" +bedwars.2003="Taas yksi susi liittyi laumaasi!" +bedwars.2004="Toisen mahdollisuuden tikkusi pelasti sinut varmalta kuolemalta! Olet haavoittumaton %%time%% sekunnin ajan!" +bedwars.2005="Pitäessäsi tämän kepin tavaraluettelossasi voit paeta kuolemaa hetkeksi, kun elinvoimasi on alhainen!" +bedwars.2006="Practice-pelimuoto on tällä hetkellä poissa käytöstä, ole hyvä ja yritä myöhemmin uudelleen!" +bedwars.2007="Nopeus: " +bedwars.2008="Palikoita asetettu: " +bedwars.2009="Ota villa käyttöön" +bedwars.2010="Aloita %%amount%% kappaleella valittua esinettä." +bedwars.2011="%%prefix%%Mitä haluat?" +bedwars.2012="Tason sijainti: %%position%%" +bedwars.2013="%%prefix%%Okei, nyt voit lopettaa." +bedwars.2014="Armed" +bedwars.2015="UUSI HENKILÖKOHTAINEN ENNÄTYS" +bedwars.2016="Jokin meni vikaan sänkyä rikottaessa, ilmoitathan tästä osoitteessa https://hypixel.net/bugs! Sisällytä ilmoitukseesi seuraava virhekoodi: BW_BLANK_RAY" +bedwars.2017="Olet taistelussa etkä voi kutsua!" +bedwars.2018="Miten sinulla on villaa?!" +bedwars.2019="Castle BETA" +bedwars.2020="Teleporttaa kaikki tiimitoverit takaisin tukikohtaan 5 sekunnin jälkeen!" +bedwars.2021="Olet jo valinnut tämän." +bedwars.2022="Et voi mennä näin pitkälle!" +bedwars.2023="Lähetetään sinut uudelle palvelimelle päivityksen vuoksi!" +bedwars.2024="Tason paksuus: %%size%%" +bedwars.2025="Aloitat 32 villakuution kanssa." +bedwars.2026="Practice" +bedwars.2027="Aseta lopetussaaren kulmaksi %%angle%%." +bedwars.2028="Suoritettu! Kului %%time%% sekuntia, huippunopeus oli %%top%%" +bedwars.2029="Aseta lopetussaari %%blocks%% palikan päähän." +bedwars.2030="Kului %%time%% sekuntia, asetit %%placed%% palikkaa!" +bedwars.2031="Käyttäessäsi tätä miekkaa vahingoittaaksesi pelaajia annat Karkin tai kepposen!" +bedwars.2032="Lucky Blocks V2" +bedwars.2033="Karkki vai kepponen -miekka" +bedwars.2034="Tason koko: %%size%%" +bedwars.2035="%%prefix%%Miksi teet näin?" +bedwars.2036="%%prefix%%Okei, jos annan sinulle sieluja niin lopetatko?" +bedwars.2037="Laskeutumistaso asetetaan satunnaisesti." +bedwars.2038="Aseta lopetussaaren korkeudeksi %%elevation%%." +bedwars.2039="Esineitä ei sekoiteta." +bedwars.2040="4v4 -tilastoja ei enää lasketa ydinpelimuotojen pistetaulukoihin." +bedwars.2041="Kappas vain. Miten roolit ovat..." +bedwars.2042="Hinta: %%cost%% Sielua" +bedwars.2043="%%count%% %%item%% vaihtokauppana %%souls%% sielusta." +bedwars.2044="%%amount%% esinettä" +bedwars.2045="Et voi käyttää tätä esinettä vielä!" +bedwars.2046="%%blocks%% palikkaa" +bedwars.2047="%%count%%x %%resource%%" +bedwars.2048="Kutsu tiimitovereita" +bedwars.2049="Palaa lobbyyn" +bedwars.2050="%%prefix%%STOP!" +bedwars.2051="%%prefix%%Twerkkaatko... sinä?" +bedwars.2052="BED WARS PRACTICE" +bedwars.2053="Pelimuodon valinta" +bedwars.2054="Pelimuoto: " +bedwars.2055="Kerää sieluja tappamalla pelaajia ja olentoja sekä rikkomalla sänkyjä." +bedwars.2056="Voit valita pelimuodon vain 5 sekunnin välein!" +bedwars.2057="Et voi rakentaa näin kauas!" +bedwars.2058="Tason korkeus: %%height%%" +bedwars.2059="Et voi ostaa tätä vielä uudestaan!" +bedwars.2060="Sinulla ei ole kutsuttavia tiimitovereita!" +bedwars.2061="Synnyt uudelleen %%seconds%% sekunnin kuluttua!" +bedwars.2062="Chat on poistettu käytöstä Bed Wars Practicessa!" +bedwars.2063="Bed Wars BETA" +bedwars.2064="Sielusi: %%count%%" +bedwars.2065="TULIPALLO-/TNT-HYPPELY" +bedwars.2066="Työstäminen on poissa käytöstä!" +bedwars.2067="Villaa ei voi asettaa yli 2 palikan päähän tason reunasta." +bedwars.2068="Aloitat esineen %%item%% kanssa" +bedwars.2069="Käytä esineitä hypätäksesi mahdollisimman pitkälle!" +bedwars.2070="Aseta tason paksuudeksi %%blocks%% palikkaa." +bedwars.2071="Ei lopetussaarta, kokeile kuinka pitkälle pääset." +bedwars.2072="Voit vaihtaa ultimaattiasi vain 30 sekunnin välein!" +bedwars.2073="Sekoittaa esineen paikan hypättyäsi alas. Sinun tulee reagoida nopeasti ja ottaa esine käteesi voidaksesi käyttää sitä." +bedwars.2074="%%prefix%%Sanoin..." +bedwars.2075="KUTSU! Sinut teleportataan takaisin tukikohtaasi %%time%% sekunnin kuluttua!" +bedwars.2076="Olet jo valinnut tuon." +bedwars.2077="Poista villa käytöstä" +bedwars.2078="Oma ennätys: " +bedwars.2079="Asetuksesi päivitettiin." +bedwars.2080="Laskeutumistaso asetetaan aina suoraan saaresi eteen." +bedwars.2081="Hyödyllinen yrittäessäsi pelastaa itsesi tason kylkeen." +bedwars.2082="Selviydy kultapalikoille ottamatta putoamisvahinkoa." +bedwars.2083="Odotusaika: %%cooldown%% sekuntia" +bedwars.2084="%%prefix%%Hyvä on, mutta sinun on parempi lopettaa!" +bedwars.2085="Kerää sieluja ja vaihda niitä alamaailman resursseihin ja erityisesineisiin Esinekaupassa! Saat sieluja tappamalla pelaajia ja olentoja sekä rikkomalla sänkyjä." +bedwars.2086="Epäonnistui! Huippunopeutesi oli %%top%%" +bedwars.2087="%%prefix%%Älä suututa minua." +bedwars.2088="+%%count%% Sielua" +bedwars.2089="BAWK!" +bedwars.2090="Esine: %%item%%" +bedwars.2091="Sekoita esine hypättyäsi." +bedwars.2092="Klikkaa aktivoidaksesi!" +bedwars.2093="Kaikki sängyt voi nyt hajottaa!" +bedwars.2094="Aktivoit haasteen, mutta se täytyi ottaa pois käytöstä liityttyäsi tiimipelimuotoon ilman kokonaista partya!" +bedwars.2095="Et voi hyökätä käyttäessäsi tätä esinettä haasteen %%challenge%% aikana!" +bedwars.2096="VARO! Sade on myrkyllistä ja tyhjentää tavaraluettelosi esineistä" +bedwars.2097="Ansajono" +bedwars.2098="Aktiivisena nyt: %%challenge%%" +bedwars.2099="Saavutit tämän päivityksen enimmäistason tässä pelimuodossa!" +bedwars.2100="Et voi ostaa tätä haasteen %%challenge%% aikana." +bedwars.2101="Swappage" +bedwars.2102="Keskisaari on pudonnut, vain kehäsaarilta saa enää resursseja! Generaattorit luovat resursseja nopeammin!" +bedwars.2103="Sinulla ei ole valtaa rikkoa tätä sänkyä!" +bedwars.2104="Uusi kohde:" +bedwars.2105="Etsitkö uutta tapaa pelata Bed Warsia? Kehitä pelikokemustasi jännittävillä haasteilla!" +bedwars.2106="Et voi vahingoittaa pelaajia tällä esineellä haasteen %%challenge%% aikana" +bedwars.2107="Sinun tulee odottaa vielä %%time%% ennen kuin voit rikkoa tämän sängyn." +bedwars.2108="Klikkaa nähdäksesi haasteet!" +bedwars.2109="%%time%%" +bedwars.2110="Aktivoitiin haaste: %%challenge%%" +bedwars.2111="Et voi hyökätä tämän pelaajan kimppuun vielä! Kohteesi on: %%color%%%%target%%" +bedwars.swap_subtitle="Uusi tiimi: " +bedwars.2113="Epäonnistuit haasteessa %%challenge%%. Parempi onni ensi kerralla!" +bedwars.2114="%%playerWhoFailed%% astui vihollisen palikoille, joten tiimisi epäonnistui haasteessa %%challenge%%" +bedwars.2115="Hinta: ??" +bedwars.2116="Sänkyjä ei voi hajottaa ensimmäisten %%minutes%% minuutin ajan. Taistele resursseista ja valmistaudu taisteluun!" +bedwars.2117="Haaste lukittu!" +bedwars.2118="Ostettavissa" +bedwars.swap_team_changed="Tiimisi vaihtui ja olet nyt: " +bedwars.2120="PUNAINEN VALO" +bedwars.2121="Haasteet ovat ainutlaatuinen tapa kasvattaa pelin vaikeustasoa sekä sinulle että koko tiimillesi. Avataksesi uusia haasteita sinun tulee ensin suorittaa jo avatut haasteet." +bedwars.2122="Presidenttisi on %%name%%. Suojele johtajaasi hinnalla millä hyvänsä!" +bedwars.swap_title="%%magic%%bb VAIHTO %%magic%%bb" +bedwars.game_start.title="Bed Wars" +bedwars.game_start.swappage_title="Bed Wars Swappage" +bedwars.2124="SULJETTU BETA" +bedwars.2125="Haaste aktiivinen" +bedwars.2126="Lukittu paikka" +bedwars.2127="Keräsit tiimin %%color%%%%teamName%% villaa (%%size%%/%%need%%)" +bedwars.2128="Et voi pudottaa mitään haasteen %%challenge%% aikana" +bedwars.2129="Tapot: %%kills%% Viimeistelyt: %%finals%% Rikotut sängyt: %%beds%%" +bedwars.2130="Et voi käyttää tätä esinettä haasteen %%challenge%% aikana" +bedwars.2131=" - %%color%%%%reward%%" +bedwars.2132="%%name%% juoksi, joten tiimisi epäonnistui haasteessa %%challenge%%" +bedwars.2133="Haasteen säännöt:" +bedwars.2134="Purit sängyn onnistuneesti!" +bedwars.2135="Palkinnot lunastettu" +bedwars.2136="Ei aktiivista haastetta" +bedwars.2137="Et voi käyttää tätä esinettä haasteen %%challenge%% aikana" +bedwars.2138="????" +bedwars.2139="Niin, luulet siis olevasi aika hyvä, vai? Yritäpä olla ottamatta MITÄÄN vahinkoa" +bedwars.2140="Haastevoitot yhteensä: %%completed%%" +bedwars.2141="Avataan haasteista" +bedwars.2142="Et voi avata tätä arkkua haasteen %%challenge%% aikana" +bedwars.2143="Armo" +bedwars.2144="Bed Wars -haasteet" +bedwars.2145="Avasit: %%name%%" +bedwars.2146="%%num%%. %%line%%" +bedwars.2147="Tiimisi keräsi kaiken tarvittavan villan. Nyt voittakaa peli suorittaaksenne haasteen %%challenge%%!" +bedwars.2148="Synnyt uudelleen, koska sinulla on vielä sänky!" +bedwars.2149="Klikkaa poistaaksesi käytöstä!" +bedwars.2150="Ei keskustaa" +bedwars.2151="Tulostaulukon uudelleenlataus suoritettu!" +bedwars.2152="Presidenttisi kaatui, ja tiimisi epäonnistui haasteessa %%challenge%%" +bedwars.2153="Vain Presidenttisi voi rikkoa vihollisen sänkyjä." +bedwars.2154="Antaa 15 sekunnin Nopeus II ja Hyppytehostus II -vaikutukset tukikohtasi lähellä oleville tiimitovereille." +bedwars.2155="%%whoMoved%% liikkui punaisissa valoissa, joten tiimisi epäonnistui haasteessa %%challenge%%" +bedwars.2156="HAASTE AKTIIVINEN!" +bedwars.2157="Aktiivinen haaste: %%challenge%%" +bedwars.2158="%%challenge%%" +bedwars.2159="Tämä peli on pregame-vaiheessa! Käytä komentoa /tpto -f sivuuttaaksesi tämän varoituksen!" +bedwars.2160="Klikkaa poistaaksesi käytöstä!" +bedwars.2161="Et ole avannut tätä haastetta vielä!" +bedwars.2162="Voittoja haasteella: %%wins%%" +bedwars.2163="Haasteen tiedot" +bedwars.2164="Olet saavuttanut haasteen ostorajoituksen tälle esineelle" +bedwars.2165="Et voi enää ostaa tätä tässä pelissä!" +bedwars.game_start.swappage_description="Pelaajat vaihtavat tiimejä satunnaisin väliajoin! Pelaajat vaihtavat myös sijainteja toisten pelaajien kanssa!" +bedwars.2167="Näkymätön esinekauppa" +bedwars.2168="%%name%% otti vahinkoa, joten tiimisi epäonnistui haasteessa %%challenge%%!" +bedwars.2169="[ADMIN DEBUG] Tämä komento olisi estetty katsojana, mutta olet admin!" +bedwars.2170="Poista aktiivinen haaste käytöstä" +bedwars.2171="Haasteet" +bedwars.2172="VAROITUS! Sänkyjä voi rikkoa 1 minuutin kuluttua" +bedwars.2173="Haasteita suoritettu: %%completed%%/%%total%%" +bedwars.2174="Voit taas liikkua!" +bedwars.2175="Kohde: %%color%%%%target%%" +bedwars.2176="Et voi käyttää tätä esinettä haasteen %%challenge%% aikana!" +bedwars.2177="Et voi käyttää miekkoja haasteen %%challenge%% aikana" +bedwars.2178="Jäljellä olevat ostokset: %%remaining%%" +bedwars.2179="Epäonnistuit haasteessa %%challenge%%!" +bedwars.2180="C4 (Klikkaa REDSTONEA)" +bedwars.2181="Sinun tulee purkaa tämä sänky!" +bedwars.2182="Sinulla ei ole tarpeeksi Kestävyyttä tämän toiminnon suorittamiseksi!" +bedwars.2183="PUNAINEN VALO" +bedwars.2184="Uusi kohteesi on: %%color%%%%target%%" +bedwars.2185="Vartijavanhin %%name%%" +bedwars.2186="Et voi ostaa tätä esinettä tämän haasteen aikana" +bedwars.2187="Et voi käyttää tätä esinettä haasteen %%challenge%% aikana" +bedwars.2188="VIHREÄ VALO" +bedwars.2189="Deaktivoitiin haaste: %%challenge%%" +bedwars.2190="Klikkaa lunastaaksesi palkinnot!" +bedwars.2191="Et voi rikkoa tätä sänkyä vielä! Kohteesi on: %%color%%%%target%%" +bedwars.2192="Et voi asettaa tätä palikkaa haasteen %%challenge%% aikana" +bedwars.2193="Poista aktiivinen haaste käytöstä" +bedwars.2194="Olet Presidentti. Johdata tiimisi voittoon!" +bedwars.2195="Älä liiku!" +bedwars.2196="%%time%%" +bedwars.2197="%%color%%%%target%%" +bedwars.2198="Voit nyt liikkua vapaasti loppupelin ajan" +bedwars.2199="Epäonnistuit haasteessa %%challenge%%" +bedwars.2200="Onnea matkaan!" +bedwars.2201="Ostoja jäljellä: %%remaining%%" +bedwars.2202="TIIMIHAASTE AKTIIVINEN!" +bedwars.2203="Palkinnot:" +bedwars.2204="Tämä arkku on lukittu haasteen %%challenge%% aikana" +bedwars.2205="Kaikki ydinpelimuotojen tilastosi on nyt onnistuneesti ladattu uudelleen!" +bedwars.2206="%%name%%" +bedwars.2207="%%name%% meni kyykkyyn, joten tiimisi epäonnistui haasteessa %%challenge%%!" +bedwars.2208="Luopio" +bedwars.2209="Tiimipäivitykset ja ansat ovat poissa käytöstä" +bedwars.2210="Et voi poimia timantteja" +bedwars.2211="Sodanlietsoja" +bedwars.2212="Et voi ostaa tai käyttää hyötyesineitä taisteluissa" +bedwars.2213="Itsekäs" +bedwars.2214="Olet liian itsekäs etkä voi pudottaa esineitä muille pelaajille" +bedwars.2215="Tiimisi arkku ja Ender-arkku on lukittu" +bedwars.2216="Minimipalkka" +bedwars.2217="Saaresi resurssigeneraattori on 2x hitaampi" +bedwars.2218="Salamurhaaja" +bedwars.2219="Voit rikkoa vain kohteesi sängyn" +bedwars.2220="Muita sänkyjä ei voi rikkoa ennen kuin kohteesi koko tiimi on eliminoitu" +bedwars.2221="Eliminoituasi kohteesi tiimin onnistuneesti sinulle annetaan uusi kohde" +bedwars.2222="Kanta-asiakas" +bedwars.2223="Kaikki ostamasi panssaripäivitykset poistetaan kuollessasi" +bedwars.2224="Kaikki ostamasi työkalupäivitykset nollataan kuollessasi" +bedwars.2225="Näkymätön kauppa" +bedwars.2226="Kaikki esinepaikat Esinekaupassa ja Tiimipäivityksissä ovat satunnaisia ja piilotettuja" +bedwars.2227="Jokaisen esineen sijanti pysyy samana koko pelin ajan" +bedwars.2228="Keräilijä" +bedwars.2229="Kerää kaikki villavärit ja palauta ne kauppiaallesi" +bedwars.2230="Sinun tulee voittaa peli kaikkien tiimitovereidesi tuotua kaiken värisiä villoja" +bedwars.2231="Puuseppä" +bedwars.2232="Voit ostaa ja poimia vain puisia esineitä" +bedwars.2233="Et voi käyttää Ender-arkkuasi, sitä ei ole tehty puusta!" +bedwars.2234="Hölmöjen sillat" +bedwars.2235="Et voi ostaa muita palikoita kuin pesusientä" +bedwars.2236="Et voi poimia mitään palikoita" +bedwars.2237="Myrkkysade" +bedwars.2238="Koko pelin ajan sataa myrkyllistä vettä" +bedwars.2239="Sateessa seisominen tyhjentää tavaraluettelosi" +bedwars.2240="Mitä pidempään olet sateessa, sitä nopeammin tavaraluettelosi tyhjenee" +bedwars.2241="Pomminpurkaja" +bedwars.2242="Jokaisen tiimin sänky pitää ensin purkaa ennen kuin sen voi rikkoa" +bedwars.2243="Purettuasi vihollissängyn suojauksen se pysyy purettuna 2 minuuttia" +bedwars.2244="Laiska kaivaja" +bedwars.2245="Sinulla on pysyvä Louhintauupumus koko pelin ajan" +bedwars.2246="Jos aktivoit Louhintauupumusansan, saat voimakkaamman Louhintauupumusvaikutuksen" +bedwars.2247="TNT ja tulipallot ovat poissa käytöstä" +bedwars.2248="Ultimaattinen UHC" +bedwars.2249="Luonnollinen elinvoiman palautuminen on poissa käytöstä" +bedwars.2250="Kultaomenoista ei saa elinvoimaa" +bedwars.2251="Sorminäppäryys" +bedwars.2252="Sinulla on vain yksi työkalupalkin paikka käytössäsi" +bedwars.2253="Painavat esineet" +bedwars.2254="Jokainen esine painaa jonkin verran" +bedwars.2255="Painavien esineiden kantaminen hidastaa sinua" +bedwars.2256="Etäisyyden otto" +bedwars.2257="Voit käyttää vain Taaksepäin heittäviä tikkuja ja Isku-jousia hyökätäksesi pelaajien kimppuun" +bedwars.2258="Miekaton" +bedwars.2259="Et voi ostaa miekkoja kaupasta" +bedwars.2260="Et voi poimia miekkoja" +bedwars.2261="Kirveiden tai hakkujen käyttäminen tekee vain 1 vahinkoa pelaajiin" +bedwars.2262="Tarkka-ampuja" +bedwars.2263="Et voi lyödä pelaajia lähitaisteluaseilla, mukaan lukien nyrkilläsi" +bedwars.2264="Voit hyökätä pelaajien kimppuun vain jousella" +bedwars.2265="Patriootti" +bedwars.2266="Voit kävellä vain tiimisi asettamilla palikoilla" +bedwars.2267="Et voi poimia esineitä vihollispelaajilta" +bedwars.2268="Et saa esineitä tapettuasi pelaajan" +bedwars.2269="Voit poimia resursseja vain omasta generaattoristasi" +bedwars.2270="Jos kävelet vihollistiimin asettamilla palikoilla, haaste epäonnistuu" +bedwars.2271="Kestävyys" +bedwars.2272="Kaikki pelin toiminnot, kuten juokseminen tai palikoiden rikkominen, kuluttavat kestävyyttä" +bedwars.2273="Jos sinulla ei ole tarpeeksi kestävyyttä, et voi juosta tai rikkoa palikoita" +bedwars.2274="Kestävyytesi näkyy nälkäpalkissasi" +bedwars.2275="Kultaomenat kaksinkertaistavat kestävyytesi palautumisnopeuden 10 sekunnin ajaksi" +bedwars.2276="Vanhus" +bedwars.2277="Et voi juosta koko pelin aikana" +bedwars.2278="Jos juokset, haaste epäonnistuu" +bedwars.2279="Resurssirajoitukset" +bedwars.2280="Kaikilla kaupan esineillä on ostorajoitus koko tiimillesi" +bedwars.2281="Liikennevalot" +bedwars.2282="Liikennevalojen väri vaihtuu punaisen ja vihreän välillä satunnaisin väliajoin" +bedwars.2283="Jos liikut valon ollessa punainen, haaste epäonnistuu" +bedwars.2284="Hitaat refleksit" +bedwars.2285="Voit lyödä vihollisia vain 2 sekunnin välein" +bedwars.2286="Pasifisti" +bedwars.2287="Et voi käyttää jousta tehdäksesi vahinkoa" +bedwars.2288="Voit käyttää vain Hyötyesineitä tehdäksesi vahinkoa" +bedwars.2289="Mestarisalamurhaaja" +bedwars.2290="Voit vahingoittaa vain kohdetiimisi pelaajia" +bedwars.2291="Pystyssä päin" +bedwars.2292="Et voi mennä kyykkyyn tämän haasteen aikana" +bedwars.2293="Jos menet kyykkyyn, haaste epäonnistuu" +bedwars.2294="Suojelkaa Presidenttiä" +bedwars.2295="Yksi tiimin pelaajista valitaan Presidentiksi" +bedwars.2296="Vain Presidentillä on valta rikkoa vihollisten sänkyjä" +bedwars.2297="Jos Presidentti kuolee, haaste epäonnistuu" +bedwars.2298="Ei osumia tänään" +bedwars.2299="Sinun ei tule ottaa yhtään vahinkoa koko pelin aikana" +bedwars.2300="Jos otat vahinkoa tai putoat tyhjyyteen, haaste epäonnistuu" +bedwars.2301="Tiimisi tulee rikkoa ainakin 1 sänky haasteen suorittamiseksi" +bedwars.2302="%%killer%% hukutti pelaajan %%player%% joulun iloon." +bedwars.2303="%%killer%% karkotti pelaajan %%player%% tyhjyyteen joulun hengen nimessä." +bedwars.2304="%%killer%% julisti joulurauhaa pelaajalle %%player%%." +bedwars.2305="%%killer%% ampui pelaajan %%player%% jouluisella ohjuksella." +bedwars.2306="Pelaajan %%killer%% %%mob%% lauloi joululauluja pelaajalle %%player%%." +bedwars.2307="Sinun %%bed%% sulatettiin pelaajan %%killer%% jouluilon toimesta!" +bedwars.2308="%%team%% %%bed%% sulatettiin pelaajan %%killer%% jouluilon toimesta!" +bedwars.2309="Fai chun" +bedwars.2310="Kuukulta" +bedwars.2311="Penjing" +bedwars.2312="Ramen" +bedwars.2313="%%killer%% raastoi riekaleiksi pelaajan %%player%%." +bedwars.2314="%%killer%% syöksähti pelaajan %%player%% kimppuun tappaen hänet." +bedwars.2315="%%killer%% riepotteli pelaajan %%player%% hengiltä." +bedwars.2316="%%killer%% raateli pelaajan %%player%%." +bedwars.2317="Pelaajan %%killer%% %%mob%% raastoi riekaleiksi pelaajan %%player%%." +bedwars.2318="Sinun %%bed%% raastettiin riekaleiksi pelaajan %%killer%% toimesta." +bedwars.2319="%%team%% %%bed%% raastettiin riekaleiksi pelaajan %%killer%% toimesta." +bedwars.2320="Räjähdyksenkestävä lasi" +bedwars.2321="Sillanrakennus" +bedwars.2322="Harjoittele rakentamaan villasiltoja tyhjyyden yli." +bedwars.2323="MLG" +bedwars.2324="Harjoittele putoamista ilman putoamisvahinkoa vesiämpäreiden ja tikkaiden avulla." +bedwars.2325="Tulipallo-/TNT-hyppely" +bedwars.2326="Harjoittele loikkimista tyhjyyden yllä tulipalloilla ja TNT:llä." +bedwars.2327="Aseta vesi ennen kuin osut maahan." +bedwars.2328="Aseta tikkaat ja laskeudu niiden kylkeen." +bedwars.2329="Limasaappaat" +bedwars.2330="Aseta antaaksesi tiimillesi ylimääräisen sängyn" +bedwars.2331="Asetettava sänky" +bedwars.2332="POLTTAA! POLTTAA! POLTTAA!" +bedwars.2333="Nopein suoritus: %%time%% (#%%rank%%)" +bedwars.2334="%%tc%%%%name%% katkaisi yhteyden." +bedwars.2335="Voittoja haasteella: %%wins%% (#%%rank%%)" +bedwars.2336="POING!" +bedwars.2337="Aseta palikka aloittaaksesi!" +bedwars.2338="Oikeaklikkaa avataksesi nykyisen pelimuodonnasetukset. Asetuksia vaihtamalla avaat suurempia harjoittelumahdollisuuksia sekä erilaisia vaikeustasoja." +bedwars.2339="Oikeaklikkaa avataksesi pelimuotovalikon." +bedwars.2340="Onnistuit!" +bedwars.2341="Epäonnistui!" +bedwars.2342="%%killer%% oli älykkäämpi kuin pelaaja %%player%%." +bedwars.2343="%%killer%% päihitti nopeudessa pelaajan %%player%%." +bedwars.2344="%%killer%% kulutti loppuun kaikki pelaajan %%player%% palikat." +bedwars.2345="%%killer%% ampui pelaajan %%player%% tähtäämättä lainkaan." +bedwars.2346="Pelaajan %%killer%% %%mob%% tuhosi totaalisesti pelaajan %%player%%." +bedwars.2347="Sinun %%bed%% poistui pelistä nähtyään pelaajan %%killer%%!" +bedwars.2348="%%team%% %%bed%% poistui pelistä nähtyään pelaajan %%killer%%!" +bedwars.2349="Etäisyyden otto" +bedwars.2350="%%player%% oli liian ujo tavatakseen pelaajan %%killer%%." +bedwars.2351="%%player%% ei pitänyt tarvittavaa etäisyyttä pelaajaan %%killer%%." +bedwars.2352="%%player%% kompastui juostessa karkuun pelaajaa %%killer%%." +bedwars.2353="%%killer%% yski kohti pelaajaa %%player%%." +bedwars.2354="Pelaajan %%killer%% %%mob%% pääsi liian lähelle pelaajaa %%player%% ." +bedwars.2355="Sinun %%bed%% saastui pelaajan %%killer%% toimesta!" +bedwars.2356="%%team%% %%bed%% saastui pelaajan %%killer%% toimesta!" +bedwars.2357="%%killer%% huusi pelaajalle %%player%%." +bedwars.2358="%%killer%% heitti pelaajan %%player%% pois pihaltaan." +bedwars.2359="%%killer%% heitti tekohampailla pelaajaa %%player%%." +bedwars.2360="%%killer%% sylkäisi vahingossa pelaajan %%player%% päälle." +bedwars.2361="Pelaajan %%killer%% %%mob%% karkotti pelaajan %%player%%." +bedwars.2362="Sinun %%bed%% myytiin pihakirpputorilla pelaajan %%killer%% toimesta!" +bedwars.2363="%%team%% %%bed%% myytiin pihakirpputorilla pelaajan %%killer%% toimesta!" +bedwars.2364="%%killer%% ampui taidokkaasti pelaajan %%player%%." +bedwars.2365="Poltettu" +bedwars.2366="Muuta sängyt tuhkakasoiksi!" +bedwars.2367="Salamanisku-viimeistely" +bedwars.2368="Et voi aktivoida enempää sarjoja tältä tasolta!" +bedwars.2369="%%killer%% lävisti pelaajan %%player%% sydämen." +bedwars.2370="%%name%% laukesi!" +bedwars.2371="Kevyt" +bedwars.2372="Portaikko" +bedwars.2373="Kurkota taivaisiin" +bedwars.2374="Laskeutumistason koko on 5x5 palikkaa." +bedwars.2375="Laskeutumistason koko on 3x3 palikkaa." +bedwars.2376="Laskeutumistaso on yhden palikan kokoinen." +bedwars.2377="Laiskat puput" +bedwars.2378="Munakoristeet" +bedwars.2379="Pääsiäispusero" +bedwars.2380="Pupuparkour" +bedwars.2381="Kukkapenkki" +bedwars.2382="Kasvata kauniita kukkalaikkuja ympäri karttaa!" +bedwars.2383="Levitä kurpitsoja kaikkialle, missä kävelet!" +bedwars.2384="Soittaa jouluisen sävelen voittaessasi pelin!" +bedwars.2385="Räjähtävät puput" +bedwars.2386="Ydinpelimuotojen tulostaulukot" +bedwars.2387="Ratsasta lentävällä kanalla ja ammu räjähtäviä munia!" +bedwars.2388="Luo kyläläisiä ympärillesi vain infektoidaksesi ne kaikki!" +bedwars.2389="Lämpöaalto" +bedwars.quick_communication.player_incoming="Pelaaja tulossa!" +bedwars.2391="1. raja" +bedwars.2392="2. raja" +bedwars.2393="3. raja" +bedwars.2394="%%trap%%si on lauennut!" +bedwars.2395="%%bed%%-sänkysi %%trap%% on lauennut!" +bedwars.2396="Pelaa Bed Wars Solo -peli.\n\nTaistele 7 muuta pelaajaa vastaan!\nTuhoa vihollisten sängyt estääksesi heitä syntymästä uudelleen!\nSuojele sänkyäsi tuhoamiselta!" +bedwars.2397="Pelaa Bed Wars Doubles -peli.\n\nPelaa yhdessä toisen pelaajan kanssa päihittääksenne 7 vihollistiimiä!\nTuhotkaa vihollisten sängyt estääksenne heitä syntymästä uudelleen!\nSuojelkaa sänkyänne tuhoamiselta!" +bedwars.2398="Pelaa Bed Wars 3v3v3v3 -peli.\n\nPelaa yhdessä kahden muun pelaajan kanssa päihittääksenne 3 vihollistiimiä!\nTuhotkaa vihollisten sängyt estääksenne heitä syntymästä uudelleen!\nSuojelkaa sänkyänne tuhoamiselta!" +bedwars.2399="Pelaa Bed Wars 4v4v4v4 -peli.\n\nPelaa yhdessä kolmen muun pelaajan kanssa päihittääksenne 3 vihollistiimiä!\nTuhotkaa vihollisten sängyt estääksenne heitä syntymästä uudelleen!\nSuojelkaa sänkyänne tuhoamiselta!" +bedwars.2400="Pelaa Bed Wars 4v4 -peli.\n\n4v4 on klassinen kaikkien tuntema Bed Wars -pelimuoto, mutta siinä on vain yksi vihollinen!" +bedwars.2401="Pelaa Bed Wars %%mode%% -peli." +bedwars.2402="Bed Wars Dreams on valikoima useita vaihtelevia pelimuotoja." +bedwars.2403="Kaikki on päivitetty alussa! Taistele heti kuolemaan saakka!" +bedwars.2404="Valitse ultimaattikyky käyttääksesi sitä koska tahansa taistelun aikana!" +bedwars.2405="Saa nopeus III ja hyppytehostus IV %%seconds%% sekunnin ajaksi!" +bedwars.2406="Luo enderman sekoittaakesi suurin osa lähettyvillä olevista pelaajien asettamista palikoista!" +bedwars.2407="Aggressiivisilla possuilla on %%chance%%% mahdollisuus syntyä jokaisesta iskusta tämän porsaankyljyksen syömisen jälkeen! Kestää %%duration%% sekuntia." +bedwars.2408="Tekee jopa %%damage%%% vahinkoa lyönnistä! Enintään %%maxdamage%% sydäntä" +bedwars.2409="Tämä kannettava ender-arkku ei kuulu tiimillesi!" +bedwars.2410="Ota tämä ender-arkku mukaan minne menetkin! Se katoaa %%seconds%% sekunnin kuluessa kun asetat sen maahan." +bedwars.2411="Kannettava ender-arkku" +bedwars.2412="Teleporttaus peruttu!" +bedwars.2413="Et voi hävittää tätä palikkaa!" +bedwars.2414="Oikeaklikkaa villaa rikkoaksesi %%amount%% vieressä olevaa villakuutiota." +bedwars.2415="Sillanhävittäjä" +bedwars.2416="Klikkaa palikkaa käyttääksesi tätä esinettä!" +bedwars.2417="Loit olennon %%name%%!" +bedwars.2418="Luo automaattinen munatykki! Mutta varo, kun se ylikuumenee!" +bedwars.2419="Kanatykki" +bedwars.2420="Elä uudelleen päiväsi salamurhaajana laskeutumalla tämän heinäpaalin keskelle ottamatta yhtään putoamisvahinkoa." +bedwars.2421="Heinäpaali" +bedwars.2422="Tiimilläsi on jo käytössä %%name%%" +bedwars.2423="%%player%% käytti esineen %%name%%!" +bedwars.2424="Sinut teleportataan tukikohtaan %%delay%% sekunnin kuluttua." +bedwars.2425="Klikkaa peruaksesi %%name%%!" +bedwars.2426="Klikkaa tästä peruaksesi" +bedwars.2427="Joulun ihme" +bedwars.2428="Tähtien ihme" +bedwars.2429="Aivan tavallista jäätä. Sopii nopean reitin tekemiseen." +bedwars.2430="Et voi asettaa esinettä %%name%% tähän!" +bedwars.2431="Haluatko jutella kauppiaalle missä tahansa. Tämä %%name%% on vastaus siihen." +bedwars.2432="Kannettava kauppias" +bedwars.2433="Purit tämän läheisyysanturimiinan!" +bedwars.2434="Improvisoitu läheisyysanturiräjähde. Purettavissa ampumalla." +bedwars.2435="Jouluanturimiina" +bedwars.2436="Läheisyysanturimiina" +bedwars.2437="Laukaisit pelaajan %%player%% %%tnt%%:n!" +bedwars.2438="Ninjan paras ystävä! Oikeaklikkaa heittääksesi." +bedwars.2439="Sokerikenit" +bedwars.2440="Heittotähti" +bedwars.2441="Kuten tavallinen TNT, mutta kevyempi, joten voit heittää sen!" +bedwars.2442="Heitettävä TNT" +bedwars.2443="Sinut teleportataan takaisin alkuperäiseen sijaintiisi %%seconds%% sekunnin jälkeen." +bedwars.2444="Aktivoit Sian viikko -kykysi! Se kestää %%duration%% sekuntia." +bedwars.2445="Parantava kana" +bedwars.2446="Syö palauttaaksesi 1 sydämen." +bedwars.2447="Mitä ovat kiertävät esineet?" +bedwars.2448="Kiertävät esineet ovat saatavilla vain rajoitetun ajan. Ne saatetaan korvata toisilla väliaikaisilla esineillä aivan koska tahansa." +bedwars.2449="Ostoraja saavutettu!" +bedwars.2450="Ostoja jäljellä: %%limit%%" +bedwars.2451="Kammottava kirous" +bedwars.2452="Kiertävät esineet" +bedwars.2453="Haluatko jutella kauppiaalle missä tahansa. Tämä %%name%% on vastaus siihen. Katoaa %%seconds%% sekunnin jälkeen" +bedwars.2454="VAIN YKSITYISET PELIT" +bedwars.2455="Teleporttaa sinut ja tiimitoverisi takaisin tukikohtaanne %%delay%% sekunnin jälkeen. Poissa käytöstä Äkkikuoleman jälkeen." +bedwars.2456="Sinun täytyy olla poissa taistelusta vielä %%seconds%% sekunti(a) ennen tämän esineen käyttämistä." +bedwars.2457="Seitti" +bedwars.2458="Epävakaa teleportaatiolaite" +bedwars.2459="1/3 mahdollisuus seuraavista:" +bedwars.2460="- Teleporttaa sinut takaisin tukikohtaasi." +bedwars.2461="- Teleporttaa sinut täsmälleen kartan keskelle." +bedwars.2462="- Teleporttaa sinut täysin satunnaiseen sijaintiin." +bedwars.2463="Poissa käytöstä Äkkikuoleman jälkeen." +bedwars.2464="Viimeisen elvytyksen majakka" +bedwars.2465="Voidaan käyttää elvyttämään kaatuneet tiimitoverit sänkysi rikkoutumisen jälkeen. Kestää %%seconds%% sekuntia latautua. Rajoitettu yhteen käyttökertaan tiimiä kohden. Poissa käytöstä Äkkikuoleman jälkeen." +bedwars.2466="Mega-TNT" +bedwars.2467="Tämä supervoimakas TNT voi räjäyttää vahvimmankin lasin läpi." +bedwars.2468="Sadepilvi" +bedwars.2469="Verso" +bedwars.2470="Juhlalaiskiainen" +bedwars.2471="Hypixelin ritari" +bedwars.2472="Olet liian korkealla voidaksesi käyttää tätä!" +bedwars.2473="Et voi asettaa tuota tähän!" +bedwars.2474="Olet liian kaukana voidaksesi luoda tämän!" +bedwars.2475="Et voi käyttää tätä vielä! Ole hyvä ja odota vielä %%seconds%% s" +bedwars.2476="Klikkaa luodaksesi 3x3-seinän." +bedwars.2477="Terässeinä" +bedwars.2478="Olet liian korkealla voidaksesi heittää tämän!" +bedwars.2479="Pääosuma!" +bedwars.2480="Osuma!" +bedwars.2481="Napakymppi!" +bedwars.2482="Huti!" +bedwars.2483="Palauttaa liikkumisasetukset oletukseksi." +bedwars.2484="Nollaa liikkumisasetukset" +bedwars.2485="Nollaa tarkkuustilastot" +bedwars.2486="Nollaa laukaus- ja tarkkuustilastosi." +bedwars.2487="Kohteen etäisyys: %%distance%%" +bedwars.2488="Kohteen korkeus: %%height%%" +bedwars.2489="Kohteen nopeus: %%speed%%" +bedwars.2490="Vaatii liiketyypin valitsemisen." +bedwars.2491="Kohde on erittäin lähellä aloitussaarta." +bedwars.2492="Kohde on kaukana aloitussaaresta." +bedwars.2493="Kohde on erittäin kaukana aloitussaaresta." +bedwars.2494="Kohde on 15 palikkaa yläpuolellasi." +bedwars.2495="Kohde on samassa tasossa kanssasi." +bedwars.2496="Kohde on 15 palikkaa alapuolellasi." +bedwars.2497="Liikuttaa kohdetta ylös ja alas." +bedwars.2498="Liikuttaa kohdetta oikealle ja vasemmalle." +bedwars.2499="Liikuttaa kohdetta eteen ja taakse." +bedwars.2500="Saa kohteen hyppimään ylös ja alas." +bedwars.2501="Kohde liikkuu hitaasti." +bedwars.2502="Kohde liikkuu tavallisella nopeudella." +bedwars.2503="Kohde liikkuu nopeasti." +bedwars.2504="Liikkuminen: %%movement%%" +bedwars.2505="Klikkaa vaihtaaksesi kohteen tyyppiä." +bedwars.2506="Kohteen tyyppi" +bedwars.2507="Klikkaa \"aloita\" teleportataksesi tyhjyyteen, ja yritä sitten pelastaa itsesi helmellä!" +bedwars.2508="Onnistuit! Pelastit itsesi %%distance%% palikan päästä!" +bedwars.2509="Aloita" +bedwars.2510="Klikkaa teleportataksesi ilmaan ja aloittaaksesi!" +bedwars.2511="Helmellä pelastautumisen asetukset" +bedwars.2512="Katso aina tasoa kohti" +bedwars.2513="Katso satunnaiseen suuntaan" +bedwars.2514="Katsot aloittaessasi satunnaiseen suuntaan etkä tasoa kohti." +bedwars.2515="Etäisyys: %%distance%%" +bedwars.2516="Tämä arpoo helmen paikan työkalupalkissa. Sinun tulee siis reagoida nopeasti ottaaksesi helmen käteesi ja käyttääksesi sitä." +bedwars.2517="Sekoita helmi" +bedwars.2518="Älä sekoita helmeä" +bedwars.2519="Päivitä resurssien syntymistä ja kapasiteettia saarellasi." +bedwars.2520="Bed Wars -valikko & -kauppa (Oikeaklikkaa)" +bedwars.2521="Tämä ominaisuus ei ole tällä helkellä käytössä, yritä myöhemmin uudelleen!" +bedwars.2522="Tuota pelaajaa ei löytynyt lobbystasi!" +bedwars.2523="Et voi jakaa pikaostovalikkoasi itsesi kanssa!" +bedwars.2524="Jokin meni vikaan yrittäessä tehdä tuota, yritä myöhemmin uudelleen!" +bedwars.2525="Et voi jakaa pikaostoasi tämän pelaajan kanssa." +bedwars.2526="Virheellinen UUID. Komento: /openquickbuyshare " +bedwars.2527="JOUSELLA TÄHTÄÄMINEN/HELMELLÄ PELASTAUTUMINEN" +bedwars.2528="%%gametype%% -valikko & -kauppa" +bedwars.2529="Tämänhetkinen esineiden kierto" +bedwars.2530="Tyhjä paikka!" +bedwars.2531="Tämä on päivitettävä esine. Se menettää yhden tason, kun kuolet!" +bedwars.2532="Loistava villan poistamisessa. Synnyt aina näiden keritsimien kanssa." +bedwars.2533="Muokkaa pikaoston asettelua" +bedwars.2534="Muokkaa pikaostovalikkosi asettelua pelissä." +bedwars.2535="Kukaan ei voi jakaa pikaostoaan kanssasi." +bedwars.2536="Vain kaverit voivat jakaa pikaostonsa kanssasi." +bedwars.2537="Vain kaverit, guildin jäsenet ja partyn jäsenet voivat jakaa pikaostonsa kanssasi." +bedwars.2538="Kuka tahansa voi jakaa pikaostonsa kanssasi." +bedwars.2539="Muokkaa pikaoston asettelua" +bedwars.2540="Tämä on pikaostopaikka!" +bedwars.2541="Vasenklikkaa asettaaksesi esineen tälle paikalle." +bedwars.2542="Vasenklikkaa korvataksesi esineen tällä paikalla." +bedwars.2543="Oikeaklikkaa poistaaksesi tämän esineen." +bedwars.2544="Klikkaa lisätäksesi tämä esine pikaostoosi!" +bedwars.2545="Jaa pikaoston asettelu" +bedwars.2546="Klikkaa jakaaksesi tämän asettelun jonkun lobbyssasi olevan kanssa!" +bedwars.2547="Jokin meni vikaan yrittäessä avata tuota valikkoa, yritä myöhemmin uudelleen!" +bedwars.2548="Tämä pyyntö on vanhentunut." +bedwars.2549="Odota vielä %%cooldown%%s ennen kuin jaat pikaostosi tämä pelaajan kanssa uudestaan." +bedwars.2550="%%color%%%%sender%% jakoi oman pikaoston asettelunsa kanssasi. Klikkaa katsoaksesi!" +bedwars.2551="Klikkaa nähdäksesi pelaajan %%sender%% pikaoston asettelun" +bedwars.2552="Jaoit pikaoston asettelusi pelaajalle %%color%%%%name%%!" +bedwars.2553="Jaa pikaoston asettelu" +bedwars.2554="Ei pelaajia!" +bedwars.2555="Tässä lobbyssä ei ole ketään kenen kanssa voit jakaa." +bedwars.2556="Klikkaa jakaaksesi pikaoston asettelun pelaajan %%name%% kanssa" +bedwars.2557="Asetukset: " +bedwars.2558="Klikkaa asettaaksesi tilaan %%color%%%%option%%!" +bedwars.2559="Pikaoston jakamisen yksityisyys" +bedwars.2560="Odota hetki ennen kuin muutat asetuksiasi uudelleen." +bedwars.2561="Pikaoston jakamisen yksityisyydeksi asetettiin %%color%%%%name%%!" +bedwars.2562="pelaajan %%name%% asettelu" +bedwars.2563="Klikkaa kopioidaksesi pealajan %%name%% pikaoston asettelun." +bedwars.2564="VAROITUS: Tämä ohittaa tämänhetkisen asettelusi." +bedwars.2565="Kopioitiin pelaajan %%name%% pikaoston asettelu!" +bedwars.2566="Helmellä pelastautuminen" +bedwars.2567="Harjoittele helmillä itsesi pelastamista tyhjyydestä." +bedwars.2568="Harjoittele tarkkuuttasi erilaisten jousiammuntahaasteiden avulla." +bedwars.2569="Syntyy %%seconds%% sekunnin kuluttua" +bedwars.2570="Laskeutumistaso on ylhäällä, joten tiput lyhyemmän matkan." +bedwars.2571="Laskeutumistaso on alempana, joten tiput pidemmän matkan." +bedwars.2572="Laskeutumistaso on hyvin alhaalla, joten tiput todella pitkän matkan." +bedwars.2573="Vaihda puun tyyliä pelissä." +bedwars.2574="Poksahtelevat munat" +bedwars.2575="Sängyn rikkominen luo kuoriutuvia munia!" +bedwars.2576="Särkyvä jää" +bedwars.2577="Mikään ei ole parempaa kuin kiva viileä sänky." +bedwars.2578="Puraisu" +bedwars.2579="End" +bedwars.2580="Aura" +bedwars.2581="Näytä kuinka vahva aurasi on" +bedwars.2582="Kakkukävely" +bedwars.2583="Tämä on \"syö niin paljon kuin jaksat\" -buffet, joten ala syömään!" +bedwars.2584="Vartijavanhin" +bedwars.2585="Ratsasta lentävällä vartijavanhimmalla, joka tuohaa kartan." +bedwars.2586="Alasinmurskaus" +bedwars.2587="Alasin jysähtää maahan tappaessasi pelaajan." +bedwars.2588="Vartijaraketti" +bedwars.2589="Vihollisen tappaminen synnyttää muutamia vihaisia vartijoita." +bedwars.2590="Sataa kultaa" +bedwars.2591="Kultaa sataa yllesi tappaessasi vihollisen." +bedwars.2592="Salamurhaajan miekka" +bedwars.2593="Ballista" +bedwars.2594="Iso lahja" +bedwars.2595="Sinilintu" +bedwars.2596="Savupiippu" +bedwars.2597="Suklaapatukka" +bedwars.2598="Keräilijän arkku" +bedwars.2599="Demoni" +bedwars.2600="Paholainen" +bedwars.2601="Piparkakkutalo" +bedwars.2602="Verta vuotava sydän" +bedwars.2603="Näkymätön kyläläinen" +bedwars.2604="Leppäkerttu" +bedwars.2605="Suuri jänis" +bedwars.2606="Lehti" +bedwars.2607="Taikapupu" +bedwars.2608="Auringonvarjo" +bedwars.2609="Presidentin henkivartijat" +bedwars.2610="Vanukas" +bedwars.2611="Viikatemies" +bedwars.2612="Taimi" +bedwars.2613="Ostoskärry" +bedwars.2614="Pieni pupu" +bedwars.2615="Aavemainen lyhty" +bedwars.2616="Lainelauta" +bedwars.2617="Korkea porkkana" +bedwars.2618="Temppelimaja" +bedwars.2619="Ukkonen" +bedwars.2620="Liikennevalo" +bedwars.2621="Noidan mökki" +bedwars.2622="Zombikäsi" +bedwars.2623="Arcade" +bedwars.2624="Pimeä portaali" +bedwars.2625="Aaveen itku" +bedwars.2626="Suojelija" +bedwars.2627="Tonttu ja pyrypallo" +bedwars.2628="Tappaja" +bedwars.2629="Metsuri" +bedwars.2630="Kauppias" +bedwars.2631="Isänmaallinen kotka" +bedwars.2632="Laiskiaispresidentti" +bedwars.2633="Petteri" +bedwars.2634="Scarecrow" +bedwars.2635="Skeletori" +bedwars.2636="Soturi" +bedwars.2637="%%killer%% heitti chilijauhetta pelaajan %%player%% kasvoille." +bedwars.2638="Vesipatsas" +bedwars.2639="Rapu" +bedwars.2640="Hiekkalinna" +bedwars.2641="Vesimeloni" +bedwars.2642="Karmiva Hypixel" +bedwars.2643="Musta kissa" +bedwars.2644="Hauta" +bedwars.2645="Männynkäpy" +bedwars.2646="Bundlattu lumiukko" +bedwars.2647="Luminen mökki" +bedwars.2648="Voit asettaa Minion Skinin tähän ja muuttaa minionisi ulkonäköä." +bedwars.2649="Seikkailijan koristeellinen lumottu rautavasara" +bedwars.2650="Mihinhän tätä voi käyttää? Hotellin vastaanottovirkailija antaa näitä silloin tällöin, kun on auttanut tarpeeksi ihmisiä." +bedwars.2651="Anna Jimmylle %%amount%% horroslippua" +bedwars.2652="Voitko hankkia minulle hieman Nether-tähtiä? Niiden maagiset ja unenomaiset ominaisuudet saattaisivat auttaa minua muistamaan tämän unen." +bedwars.2653="Anna minulle %%iron%% %%item%%s ja %%coins%% Hopeakolikkoa." +bedwars.2654="Sinun täytyy ostaa Ikuiset sakset ensin!" +bedwars.2655="???" +bedwars.2656="TEHTÄVÄ ALOITETTU" +bedwars.2657="Määrä muutettu lompakon koon takia." +bedwars.2658="Ei sen väliä. Tarvitsen nipun %%item%% materiaaleihini." +bedwars.2659="Tämä kerroin koskee vain peleissä ansaittuja lippuja. " +bedwars.2660="Smaragdisiru" +bedwars.2661="Et voi käyttää tätä esinettä enää!" +bedwars.2662="%%current%%/%%max%% horroslippua" +bedwars.2663="Puhu Hämmentyneelle kaverille" +bedwars.2664="• Bed Wars -experience - %%chance%%% mahdollisuus" +bedwars.2665="Auta tarkastaja Mayaa löytämään viides murhan johtolanka." +bedwars.2666="Mutta ensin, ota tämä %%name%%, ja tämä Horrostavaraluettelo." +#bedwars.2667="" # No translation available +bedwars.2668="Osta ilotulitusnäytös" +#bedwars.2669="" # No translation available +#bedwars.2670="" # No translation available +bedwars.2671="Lippukone hyrrää..." +bedwars.2672="Säästä %%amount%% rautahippua" +bedwars.2673="Tein tämän seikkailijan lompakon sinulle. Se on isompi kuin sinun tämänhetkinen." +#bedwars.2674="" # No translation available +bedwars.2675="Pahoittelut, horrostehtävät ovat väliaikaisesti poissa käytöstä!" +bedwars.2676="Hei! Olen Horroshotellin ovimies." +#bedwars.2677="" # No translation available +bedwars.2678="%%amount%% figuriinia" +bedwars.2679="Löysit tähdet!" +bedwars.2680="Salaperäinen pirtelö" +bedwars.2681="[NPC] Lester Brody: Hei äijääää" +#bedwars.2682="" # No translation available +#bedwars.2683="" # No translation available +bedwars.2684=" %%line%%" +bedwars.2685="Klikkaa näyttääksesi!" +bedwars.2686="Hinta: 100 horroslippua" +bedwars.2687="Omenapirtelö" +bedwars.2688="Klikkaa tästä nähdäksesi horrosesineesi!" +bedwars.2689="%%cosmeticName%%" +bedwars.2690="Puhu Hämmentyneelle kaverille" +bedwars.2691="Kerää sytytystulppa" +bedwars.2692="Horroshotellin sisäänkäynti" +bedwars.2693="[Nah ei juuri nyt]" +#bedwars.2694="" # No translation available +bedwars.2695="Voit vaihtaa %%emeralds%% smaragdia %%tickets%% horroslippuun!" +bedwars.2696="Hanki keitaan vettä" +#bedwars.2697="" # No translation available +bedwars.2698="Horrostehtävämuistio" +bedwars.2699="Löydä %%amount%% smaradgisirua Jeremylle" +#bedwars.2700="" # No translation available +bedwars.2701="Odotathan ennen kuin käytät tuota uudestaan!" +bedwars.2702="Pirtelö on niiiiiin hyvää." +bedwars.2703="Sinun lippusi: %%currentTickets%%/%%needed%%" +#bedwars.2704="" # No translation available +#bedwars.2705="" # No translation available +bedwars.2706="• Bed Wars -kosmeettiset esineet - %%chance%%% mahdollisuus" +#bedwars.2707="" # No translation available +#bedwars.2708="" # No translation available +#bedwars.2709="" # No translation available +bedwars.2710="Sinulla ei ole tarpeeksi horroslippuja tehdäksesi tätä!" +bedwars.2711="Pelaa Bed Warsia saadaksesi horroslippuja." +#bedwars.2712="" # No translation available +bedwars.2713="[Teleporttaa hotellille]" +#bedwars.2714="" # No translation available +#bedwars.2715="" # No translation available +bedwars.2716="[NPC] Lester Brody: Bruh" +bedwars.2717="Löydä %%amount%% rautahippua Jeremylle" +#bedwars.2718="" # No translation available +bedwars.2719="Sinulla ei ole varaa tähän!" +#bedwars.2720="" # No translation available +bedwars.2721="Liput: %%tickets%%/%%limit%%" +bedwars.2722="Julmuuden merkki" +bedwars.2723="Voita visailu!" +bedwars.2724="Vasaran muotti" +bedwars.2725="Pääosumat:" +#bedwars.2726="" # No translation available +#bedwars.2727="" # No translation available +#bedwars.2728="" # No translation available +bedwars.2729="Sinä! %%player%%! Tuo minulle uusi %%item%%!" +#bedwars.2730="" # No translation available +bedwars.2731="Eikö tämä kuulu Ratmanille?" +#bedwars.2732="" # No translation available +bedwars.2733="Jatka hotellissa olevien vieraiden auttamista, kunnes saat esineen %%wallet%%, tule sitten luokseni." +bedwars.2734="Kerää rautahippuja" +bedwars.2735="Laitoit pelaajan %%name%% nukkumaan!" +bedwars.2736="Hinta: %%count%% horroslippua" +#bedwars.2737="" # No translation available +bedwars.2738="Klikkaa teleportataksesi ovimies Daven luo" +#bedwars.2739="" # No translation available +bedwars.2740="Klikkaa poistuaksesi!" +#bedwars.2741="" # No translation available +#bedwars.2742="" # No translation available +#bedwars.2743="" # No translation available +bedwars.2744="Aktivoit Sian viikko -kykysi! Se kestää %%duration%% sekuntia." +bedwars.2745="+%%amount%% horroslippua!" +#bedwars.2746="" # No translation available +bedwars.2747="tiimi" +#bedwars.2748="" # No translation available +#bedwars.2749="" # No translation available +bedwars.2750="TOISTETTAVA TEHTÄVÄ" +bedwars.2751="Klikkaa \"Kerää kaikki\" alapuolelta kerätäksesi esineesi!" +bedwars.2752="Sian viikko -kykysi on jo aktiivinen!" +#bedwars.2753="" # No translation available +bedwars.2754="Ideaali sijoittelu" +#bedwars.2755="" # No translation available +#bedwars.2756="" # No translation available +#bedwars.2757="" # No translation available +bedwars.2758="Hopeaterä" +bedwars.2759="Keitaan vettä" +bedwars.2760="Poissa käytöstä" +#bedwars.2761="" # No translation available +#bedwars.2762="" # No translation available +#bedwars.2763="" # No translation available +bedwars.2764="Figuriini" +bedwars.2765="Horrosliput" +bedwars.2766="Ilmanraikastin" +#bedwars.2767="" # No translation available +bedwars.2768="Et voi asettaa tätä palikkaa tähän!" +#bedwars.2769="" # No translation available +#bedwars.2770="" # No translation available +#bedwars.2771="" # No translation available +#bedwars.2772="" # No translation available +bedwars.2773="Avasit: +20% horroslippukertoimen" +#bedwars.2774="" # No translation available +#bedwars.2775="" # No translation available +#bedwars.2776="" # No translation available +bedwars.2777="Bed Wars -experienceä!" +bedwars.2778="%%name%%" +#bedwars.2779="" # No translation available +bedwars.2780="Omistat tällä hetkellä %%emeralds%% smaragdia. Haluaisitko vaihtaa %%needed%% smaragdia %%tickets%% horroslippuun?" +#bedwars.2781="" # No translation available +bedwars.2782="Kadonnut aarre" +#bedwars.2783="" # No translation available +#bedwars.2784="" # No translation available +bedwars.2785="%%line%%" +#bedwars.2786="" # No translation available +#bedwars.2787="" # No translation available +bedwars.2788="Hanki %%amount%% rautahippua Sepälle" +bedwars.2789="Mustikkapirtelö" +bedwars.2790="Kerää %%amount%% lakanaa" +bedwars.2791="Tunnet olosi todella virkistyneeksi!" +bedwars.2792="Luettelo mahdollisista palkinnoista, joita saa lippukoneesta." +#bedwars.2793="" # No translation available +bedwars.2794="Voita %%amount%% Bed Wars -peliä putkeen." +bedwars.2795="Vasenklikkaa käyttääksesi tätä esinettä!" +#bedwars.2796="" # No translation available +bedwars.2797="Ahdistunut keltaisen tiimin wither" +#bedwars.2798="" # No translation available +#bedwars.2799="" # No translation available +bedwars.2800="Kultainen lippu" +#bedwars.2801="" # No translation available +#bedwars.2802="" # No translation available +#bedwars.2803="" # No translation available +bedwars.2804="Horroshotelli" +#bedwars.2805="" # No translation available +bedwars.2806="Hohtava hiekkapaperin pala" +bedwars.2807="Et voi nukuttaa tiimiäsi!" +#bedwars.2808="" # No translation available +#bedwars.2809="" # No translation available +#bedwars.2810="" # No translation available +bedwars.2811="Sähköinen painajainen" +#bedwars.2812="" # No translation available +bedwars.2813="Mansikkajäätelöä, kermavaahtoa, valkosuklaahippuja ja mansikkasiirappia ripoteltuna päällä. Suosituin vaihtoehtomme!" +bedwars.2814="UUSI TEHTÄVÄ" +#bedwars.2815="" # No translation available +bedwars.2816="Platinajäsenyys" +#bedwars.2817="" # No translation available +#bedwars.2818="" # No translation available +#bedwars.2819="" # No translation available +bedwars.2820="Limbo-tomu" +#bedwars.2821="" # No translation available +bedwars.2822="Klikkaa poistaaksesi käytöstä!" +bedwars.2823="Tämä minion on saavuttanut korkeimman tason." +bedwars.2824="Et voi avata tätä ovea vielä!" +bedwars.2825="Kerää %%amount%% villapalmikkoa" +bedwars.2826="Tuo %%count%%x esinettä %%item%% kauppiaalle, niin hän pitää ne tallessa Jeremyä varten." +bedwars.2827="Et voi pudottaa tuota!" +bedwars.2828="Harvinainen, hohtava ja yksilöllinen versio Horroslipusta. Pyykkäri kuulemma antaa näitä ihmisille." +bedwars.2829="Etsi %%amount%% timanttisirua Jeremylle" +bedwars.2830="<- Hissit ->" +bedwars.2831="Kasvata minionin tuotantonopeutta lisäämällä polttoaine tänne." +bedwars.2832="Aa, nyt tiedän! %%item%%! Kaksisataa milligrammaa sitä!" +bedwars.2833="Klikkaa nähdäksesi!" +bedwars.2834="Voit löytää tämän Bed Wars -pelistä." +bedwars.2835="Tuo Johnille jotain kevyttä ja puhdasta " +bedwars.2836="Edistyminen: %%current%%/%%required%%" +bedwars.2837="Oikeaklikkaa rikkoaksesi yhden pelaajan asettaman palikan." +bedwars.2838="Luo ilmavirran, joka työntää lähellä olevia vastustajia taaksepäin." +bedwars.2839="Klikkaa maksaaksesi %%amount%% horroslipulla" +bedwars.2840="Tämä sekava ovi vaatii vielä muutamia esineitä ennen kuin se voidaan avata. Sinun on jatkettava tehtävien suorittamista Horroshotellissa löytääksesi ne esineet." +bedwars.2841="Sinun täytyy olla poissa taistelusta vielä %%seconds%% sekunnin%%s%% ennen kuin voit käyttää tätä esinettä." +bedwars.2842="Lippukertoimet yhteensä: +%%amount%%%" +bedwars.2843="Ruoki Don Espressolle %%amount%% kultaharkkoa" +bedwars.2844="Suoritettu: %%completed%%" +bedwars.2845="Vau, olet tasolla %%level%%? Vaikuttavaa!" +#bedwars.2846="" # No translation available +bedwars.2847="[Lyön vetoa, että pystyn]" +bedwars.2848="Kuukivihippu" +bedwars.2849="Olet avannut tämän oven! Klikkaa tätä ovea milloin tahansa päästäksesi sisään." +#bedwars.2850="" # No translation available +bedwars.2851="Hanki vasaran muotti" +bedwars.2852="Ahdistunut punaisen tiimin wither" +#bedwars.2853="" # No translation available +#bedwars.2854="" # No translation available +#bedwars.2855="" # No translation available +bedwars.2856="Murhavihje, jonka voi löytää joissain Bed Wars -kartoissa sen jälkeen, kun olet jutellut tarkastaja Maya Sterlingille." +#bedwars.2857="" # No translation available +#bedwars.2858="" # No translation available +bedwars.2859="Klikkaa avataksesi" +bedwars.2860="%%item%% x%%amount%%" +bedwars.2861="Klikkaa" +bedwars.2862="+5% perkistä" +#bedwars.2863="" # No translation available +bedwars.2864="Päivityspaikka" +#bedwars.2865="" # No translation available +bedwars.2866="Kerää %%amount%% uneksijan sielunsirpaletta" +bedwars.2867="Auta Peteriä löytämään tiensä takaisin The Pitiin." +#bedwars.2868="" # No translation available +#bedwars.2869="" # No translation available +bedwars.2870="Ottaa prioriteetin tavallisten nuolten yli." +#bedwars.2871="" # No translation available +#bedwars.2872="" # No translation available +bedwars.2873="Säästä %%amount%% ylimääräistä kaapelia" +bedwars.2874="Seikkailijalla on aina tarvetta pätkälle luottoköyttä!" +bedwars.2875="Säästä %%amount%% smaragdisirua" +bedwars.2876="Rautahippu" +#bedwars.2877="" # No translation available +bedwars.2878="Avaa valikon, jossa näkyy kaikki vihjeet" +#bedwars.2879="" # No translation available +#bedwars.2880="" # No translation available +#bedwars.2881="" # No translation available +#bedwars.2882="" # No translation available +#bedwars.2883="" # No translation available +bedwars.2884="Voit käyttää tätä esinettä vain, kun sinulla ei ole sänkyä!" +bedwars.2885="[NPC] %%name%%: " +bedwars.2886="Ahdas tunneli..." +bedwars.2887="Jäisten mustikoiden, vanilja-mantelimaidon ja jäätelön täydellinen sekoitus." +bedwars.2888="Kun rikot sängyn, saat siitä palkinnoksi lakanan." +#bedwars.2889="" # No translation available +bedwars.2890="Avasit Kultaisen hiekkamiehen figuriinin!" +#bedwars.2891="" # No translation available +bedwars.2892="Kuka on omistaja?" +#bedwars.2893="" # No translation available +#bedwars.2894="" # No translation available +bedwars.2895="Olen varma, että löydät jotain." +bedwars.2896="Klikkaa kerätäksesi kaikki esineet!" +bedwars.2897="Kevyt ja puhdas puukko." +#bedwars.2898="" # No translation available +bedwars.2899="Peterin täytyy päästä pakenemaan" +#bedwars.2900="" # No translation available +#bedwars.2901="" # No translation available +bedwars.2902=" Kaikki tavoitteet saavutettu!" +#bedwars.2903="" # No translation available +#bedwars.2904="" # No translation available +bedwars.2905="Anna Jimmylle %%amount%% horroslippua." +bedwars.2906="Et voi laittaa tätä pelaajaa nukkumaan seuraavan %%time%%s aikana!" +bedwars.2907="Anna horroslippuja" +#bedwars.2908="" # No translation available +#bedwars.2909="" # No translation available +bedwars.2910="Aloitat ilman villaa." +#bedwars.2911="" # No translation available +#bedwars.2912="" # No translation available +bedwars.2913="%%item%%..." +#bedwars.2914="" # No translation available +bedwars.2915="LIPPUPALKINTO! %%display%%" +bedwars.2916="Voitetaan lippukoneesta " +bedwars.2917="75 horroslippua" +bedwars.2918="Lukittu esine" +bedwars.2919="Uhrin kuva" +bedwars.2920="Hanki %%amount%% keitaanhengen sielua" +bedwars.2921="Tapahtui virhe" +bedwars.2922="Omistettu" +#bedwars.2923="" # No translation available +bedwars.2924="+5% horrosbonuksesta" +bedwars.2925="Voit tehostaa minioniasi lisämäällä minionpäivityksen tähän." +bedwars.2926="Jokin meni vikaan, ilmoita tästä foorumeilla virhekoodilla REMOVE_TICKETS_NEGATIVE" +bedwars.2927="Tuo minulle %%tokens%% Julmuuden merkkiä todisteena taistelukyvystäsi." +#bedwars.2928="" # No translation available +bedwars.2929="Sinun täytyy maksaa %%tickets%% lippua avataksesi tämän huoneen." +#bedwars.2930="" # No translation available +bedwars.2931="Vastaanottovirkailija on pyytänyt sinua olemaan tekemättä tätä joksikin aikaa." +#bedwars.2932="" # No translation available +#bedwars.2933="" # No translation available +bedwars.2934="Mansikkapirtelö" +#bedwars.2935="" # No translation available +bedwars.2936="Korkein taso on saavutettu!" +bedwars.2937="Klikkaa lisätäksesi esittelyyn!" +bedwars.2938="Et voi palauttaa esineitä toisen joukkueen kauppiaalle!" +#bedwars.2939="" # No translation available +#bedwars.2940="" # No translation available +#bedwars.2941="" # No translation available +bedwars.2942="Sinulla ei ole varaa tähän näyttöön!" +bedwars.2943="Kyykkää noustaksesi pois - Aikaa jäljellä: %%time%%s" +bedwars.2944="Avataan Horroshotellista!" +#bedwars.2945="" # No translation available +#bedwars.2946="" # No translation available +bedwars.2947="Käytit %%name%%:n!" +#bedwars.2948="" # No translation available +#bedwars.2949="" # No translation available +bedwars.2950="%%name%% nukkuu!" +bedwars.2951="Todistus onnistumisesta" +bedwars.2952="Tarvitsen %%amount%% %%item%%." +#bedwars.2953="" # No translation available +#bedwars.2954="" # No translation available +#bedwars.2955="" # No translation available +#bedwars.2956="" # No translation available +#bedwars.2957="" # No translation available +#bedwars.2958="" # No translation available +#bedwars.2959="" # No translation available +#bedwars.2960="" # No translation available +#bedwars.2961="" # No translation available +bedwars.2962="+1 %%item%% kerätty! (%%current%%)" +bedwars.2963=" (Toistettava)" +bedwars.2964="Vadelmapirtelö" +bedwars.2965="Kerää %%amount%% rautahippua" +bedwars.2966="Laukaukset: " +#bedwars.2967="" # No translation available +#bedwars.2968="" # No translation available +#bedwars.2969="" # No translation available +#bedwars.2970="" # No translation available +bedwars.2971="Klikkaa oikeaa vastausta!" +#bedwars.2972="" # No translation available +#bedwars.2973="" # No translation available +bedwars.2974="Napakymppi: " +bedwars.2975="Blitz-tähti" +#bedwars.2976="" # No translation available +bedwars.2977="Näytä tämän minionin päivittämiseen tarvittavat esineet." +bedwars.2978="Muuttaa sinut näkymättömäksi %%time%%s ajaksi." +bedwars.2979="Klikkaa vaihtaaksesi!" +#bedwars.2980="" # No translation available +bedwars.2981="Haalistunut Blitz-tähti" +bedwars.2982="[Valitse murhaaja]" +bedwars.2983="Ender-tomu" +bedwars.2984="Julmuuden merkkejä annetaan pelaajan tappamisesta tai tapon avustuksesta." +#bedwars.2985="" # No translation available +#bedwars.2986="" # No translation available +bedwars.2987="%%item%%..." +bedwars.2988="SUORITETTU" +bedwars.2989="Suuri luolaseikkailu" +bedwars.2990="Puhu hotellin vastaanottovirkailijalle" +bedwars.2991="Ei voida vaihtaa!" +bedwars.2992="TEHTÄVÄ SUORITETTU" +#bedwars.2993="" # No translation available +#bedwars.2994="" # No translation available +bedwars.2995="Ilmoita tästä foorumeilla." +#bedwars.2996="" # No translation available +#bedwars.2997="" # No translation available +bedwars.2998="Mega Walls -obsidiaanipalikka" +#bedwars.2999="" # No translation available +bedwars.3000="Puhu Twitchy Joelle" +bedwars.3001="Horrostavaraluettelo (Oikeaklikkaa)" +bedwars.3002="Ender-tomu" +bedwars.3003="Limbo-tomu" +#bedwars.3004="" # No translation available +#bedwars.3005="" # No translation available +bedwars.3006="Tehtävämuistio" +bedwars.3007="Horroshotellin uloskäynti" +bedwars.3008="Klikkaa päästäksesi sisään!" +bedwars.3009="Suuret kiitokset!" +#bedwars.3010="" # No translation available +bedwars.3011="Ei tarpeeksi lippuja!" +#bedwars.3012="" # No translation available +bedwars.3013="Minionillasi ei ole mitään kerättävää!" +bedwars.3014="Kun sinua lyödään, kummitus tulee kummittelemaan sinulle." +bedwars.3015="Kerää %%amount%% ender-tomua" +bedwars.3016="Uneksijan sielunsirpale" +bedwars.3017="Tämä kerroin koskee kaikkia pelaajia Bed Warsissa ja kasvattaa heidän mahdollisuuttaan ansaita Horroslippuja peleistä." +bedwars.3018="Klikkaa poimiaksesi!" +bedwars.3019="Kerää %%amount%% %%item%% tappaen tai avustaen muita pelaajia tappamisessa." +bedwars.3020="TAVOITE SAAVUTETTU" +bedwars.3021="Jos hankit minulle %%amount%% Nether-tähteä, voin ehkä käyttää niiden voimia tämän unen muistamiseksi." +bedwars.3022="Taso %%tier%% on kiertävä esine!" +bedwars.3023="Omistaja on huomannut sinut. Puhu hotellin vastaanottovirkailijalle." +bedwars.3024="Edistyminen: %%current%%/%%required%%" +bedwars.3025="Amuletti, joka kuuluu King Flutille, suurelle... jonkin paikan faaraolle. Se unohdettiin oltuaan jonkin aikaa Oasiksella, ja se tulisi palauttaa hänelle. " +bedwars.3026="ONNISTUIT! Keräsit käytetyn parin %%item%%!" +bedwars.3027="Odotathan vielä %%seconds%% sekuntia ennen kuin tiimisi käyttää tätä esinettä uudelleen." +bedwars.3028="Olet herännyt ja voit taas liikkua!" +bedwars.3029="Kerää %%count%% ender-tomua kokki Buckylle. Ender-tomua saa ender-helmien käyttämisestä." +bedwars.3030="Klikkaa avataksesi!" +bedwars.3031="Lisää tähän Budjettisuppilo tai Lumottu suppilo , jotta kätyrisi voi automaattisesti myydä luotuja esineitä, kun sen tavaraluettelo on täynnä." +bedwars.3032="Mene portaaliin poistuaksesi" +bedwars.3033="Nether-tähti" +#bedwars.3034="" # No translation available +bedwars.3035="Ei avattu!" +#bedwars.3036="" # No translation available +#bedwars.3037="" # No translation available +bedwars.3038="Heitä pelaajaa nukuttaaksesi heidät! He jatkavat uniaan enintään %%duration%% sekuntia tai kunnes heidät herätetään." +bedwars.3039="Kerää %%count%% %%item%% SkyBlock-pelaajalle. Ender-tomua saa ender-helmien käyttämisestä." +bedwars.3040="Lompakko täynnä -varoitus" +bedwars.3041="Horrosliput: %%tickets%%/%%limit%%" +bedwars.3042="Olit %%rank%% pelaaja, joka tapasi hiekkamiehen!" +bedwars.3043="Hotellivirkailija viittaa sinut luokseen. Ehkäpä pitäisi puhua hänen kanssa?" +bedwars.3044="Figuriineja voi avata myös Lippukoneella." +bedwars.3045="Kuoleman enkelin miekka (Yksi käyttökerta)" +bedwars.3046="Murhan johtolanka #2" +bedwars.3047="Harvinaisuus: %%rarity%%" +bedwars.3048="Puhu NPC-hahmolle, jolta sait tämän tehtävän suorittaaksesi sen." +bedwars.3049="Murhan johtolanka #1" +bedwars.3050="Murhan johtolanka #4" +bedwars.3051="Murhan johtolanka #3" +#bedwars.3052="" # No translation available +bedwars.3053="Aseta luodaksesi witherin." +#bedwars.3054="" # No translation available +bedwars.3055="Klikkaa peruaksesi" +#bedwars.3056="" # No translation available +bedwars.3057="%%upgrade%% on kiertävä esine!" +bedwars.3058="Murhan johtolanka #5" +bedwars.3059="Esittelypalikassa ei ole tarpeeksi tilaa!" +bedwars.3060="+%%tickets%% horroslippua!" +#bedwars.3061="" # No translation available +bedwars.3062="• Horrosliput - %%chance%%% mahdollisuus" +bedwars.3063="Ender-tomua kerätty: %%amount%%" +bedwars.3064="Anteeksi, tämä tehtävä on toistaiseksi poissa käytöstä!" +#bedwars.3065="" # No translation available +bedwars.3066="Mitä?" +bedwars.3067="Oikeaklikkaa palikkaa käyttääksesi tätä esinettä!" +bedwars.3068="TEHTÄVÄ SUORITETTU" +#bedwars.3069="" # No translation available +bedwars.3070="Vaihdoit %%emeralds%% smaragdia %%tickets%% horroslippuun!" +bedwars.3071="+%%amount%% %%itemClean%%!" +#bedwars.3072="" # No translation available +bedwars.3073="Minä lähden. Ota lippuni ja pukuni %%player%%, minulle riittää." +#bedwars.3074="" # No translation available +bedwars.3075="Et voi avata kauppaa nukkuessasi!" +#bedwars.3076="" # No translation available +bedwars.3077="Horrosliput" +bedwars.3078="Vanha aarrekartta" +bedwars.3079="Hanki horroslippuja" +#bedwars.3080="" # No translation available +#bedwars.3081="" # No translation available +#bedwars.3082="" # No translation available +bedwars.3083="Avaa omistajan toimisto ja esittele itsesi hiekkamiehelle." +bedwars.3084="+%%amount%%% pelaajan %%purchaser%% Network Booster" +bedwars.3085="Puhu hotellin vastaanottovirkailijalle" +#bedwars.3086="" # No translation available +bedwars.3087="Lakana" +bedwars.3088="Et voi käyttää tuota täällä!" +#bedwars.3089="" # No translation available +bedwars.3090="Timanttisiru" +bedwars.3091="Anteeksi, tämä tehtävä on toistaiseksi poissa käytöstä!" +bedwars.3092="Kerää %%amount%% ylimääräistä kaapelia" +#bedwars.3093="" # No translation available +bedwars.3094="Olen kuollut." +bedwars.3095="Oi siellä hän menee!" +bedwars.3096="Höyhenenkevyt %%tier%%" +bedwars.3097="Löydä %%amount%% kultaharkkoa Jeremylle" +bedwars.3098="A-Ö" +#bedwars.3099="" # No translation available +bedwars.3100="Hei %%player%%, Horroshotelli hyväksyy nyt varauksia!" +#bedwars.3101="" # No translation available +#bedwars.3102="" # No translation available +#bedwars.3103="" # No translation available +bedwars.3104="Älä peukaloi todistusaineistoa!" +#bedwars.3105="" # No translation available +bedwars.3106="Maksa %%amount%% lipulla?" +bedwars.3107="Auta tarkastaja Mayaa löytämään kolmas murhan johtolanka." +#bedwars.3108="" # No translation available +bedwars.3109="Voita visailu" +#bedwars.3110="" # No translation available +#bedwars.3111="" # No translation available +bedwars.3112="Sytytystulppa" +bedwars.3113="Tämä esine on saatavilla tiimipäivitykset-valikosta." +#bedwars.3114="" # No translation available +bedwars.3115="Sinulla on %%emeralds%% smaragdia. Tarvitset %%needed%% smaragdia vaihtaaksesi ne horroslippuihin!" +bedwars.3116="Hanki kultainen lippu" +#bedwars.3117="" # No translation available +bedwars.3118="Hyväksy veto" +bedwars.3119="TAVOITTEET SAAVUTETTU" +#bedwars.3120="" # No translation available +bedwars.3121="Horrossijoitus: #%%rank%%" +bedwars.3122="Banaanivanukasjäätelöä, pähkinävoita, suklaata ja kokonainen banaani sekoitettu täydellisesti." +bedwars.3123="Mukava tyyny" +#bedwars.3124="" # No translation available +#bedwars.3125="" # No translation available +#bedwars.3126="" # No translation available +bedwars.3127="Vahvista vaihtokauppa" +bedwars.3128="Hylkää veto" +#bedwars.3129="" # No translation available +#bedwars.3130="" # No translation available +bedwars.3131="Siellä he ovat! Odotas." +bedwars.3132="Auta tarkastaja Mayaa löytämään toinen murhan johtolanka." +bedwars.3133="Esineitä yhteensä: %%amount%%" +#bedwars.3134="" # No translation available +#bedwars.3135="" # No translation available +bedwars.3136="Horroslippuja voi ansaita tekemällä seuraavaa: " +#bedwars.3137="" # No translation available +bedwars.3138="väri" +bedwars.3139="Hopeakolikko" +#bedwars.3140="" # No translation available +bedwars.3141="Huomio: Et voi ottaa polttoainetta pois asetettuasi sen tähän!" +#bedwars.3142="" # No translation available +bedwars.3143="Klikkaa valitaksesi %%name%% murhaajaksi." +#bedwars.3144="" # No translation available +bedwars.3145="Tervetuloa!" +bedwars.3146="Tiimisi voi ostaa tämän ansan vain kerran!" +bedwars.3147="[Klikkaa katsellaksesi horrosesineitä]" +bedwars.3148="Avaa ovi" +bedwars.3149="Vaatimukset:" +bedwars.3150="Se kelpaa. Siirry kauemmas!" +#bedwars.3151="" # No translation available +bedwars.3152="Banaanipirtelö" +#bedwars.3153="" # No translation available +bedwars.3154="Tarvitsen %%pillowsCount%% %%itemOne%%ä, %%sheetsCount%% %%itemTwo%%a, %%barsCounts%% %%itemThree%%a, %%cablesCount%% %%itemFour%%a sekä auton Sytytystulpan." +bedwars.3155="Käytetyt hanskat" +#bedwars.3156="" # No translation available +#bedwars.3157="" # No translation available +#bedwars.3158="" # No translation available +bedwars.3159="Poimi minion" +#bedwars.3160="" # No translation available +#bedwars.3161="" # No translation available +#bedwars.3162="" # No translation available +#bedwars.3163="" # No translation available +bedwars.3164="Mitä? Ei! En minä ole epäilyttävä! %%playerName%% on epäilyttävä!" +bedwars.3165="Hiekkamiehelle puhuminen ei ole tällä hetkellä käytössä, yritä myöhemmin uudelleen!" +#bedwars.3166="" # No translation available +#bedwars.3167="" # No translation available +bedwars.3168="Käytetty murha-ase" +#bedwars.3169="" # No translation available +#bedwars.3170="" # No translation available +#bedwars.3171="" # No translation available +bedwars.3172="Tiimisi on jo käyttänyt %%name%%!" +#bedwars.3173="" # No translation available +bedwars.3174="%%tickets%% horroslippua" +bedwars.3175="%%tickets%% horroslippua" +#bedwars.3176="" # No translation available +bedwars.3177="Klikkaa herättääksesi heidät!" +#bedwars.3178="" # No translation available +bedwars.3179="Seuraava taso" +#bedwars.3180="" # No translation available +#bedwars.3181="" # No translation available +#bedwars.3182="" # No translation available +#bedwars.3183="" # No translation available +#bedwars.3184="" # No translation available +#bedwars.3185="" # No translation available +#bedwars.3186="" # No translation available +#bedwars.3187="" # No translation available +bedwars.3188="Järjestys: %%type%%" +#bedwars.3189="" # No translation available +#bedwars.3190="" # No translation available +bedwars.3191="Kallis parfyymi" +#bedwars.3192="" # No translation available +bedwars.3193="Suunnilleen yhtä hyödyllinen kuin puumiekka. Näyttää jopa puumiekalta. Se on käytännössä tylsä. Huonoa ammattitaitoa, jos minulta kysytään." +bedwars.3194="Et voi kantaa enempää mukavia tyynyjä!" +bedwars.3195="Löydätkö haudatun aarteen? Riko palikoita sieltä täältä joistain kartoista ja voit löytääkin!" +bedwars.3196="Klikkaa antaaksesi %%amount%% horroslippua" +bedwars.3197="Hylätty Kartin Rengas" +bedwars.3198="VAIHEEN NOUSU" +bedwars.3199="Hanki uusi lakana Saichi-rouvalle" +bedwars.3200="Kerää %%amount%% %%item%% tuhoamalla sänkyjä. " +bedwars.3201="Luottoköysi" +bedwars.3202="Et voi kantaa enempää!" +bedwars.3203="Sinun tulee päästä vaiheeseen %%phase%% suorittamalla lisää tehtäviä. " +bedwars.3204="Ahdistunut sinisen tiimin wither" +bedwars.3205="Sinulla ei ole tarpeeksi horroslippuja tehdäksesi tätä!" +bedwars.3206="Pahoittelut, vastaanottovirkailija on hetkellisesti estänyt Horroshotelliin pääsyn. " +bedwars.3207="Hanki %%amount%% Raivon Merkkiä tappamalla tai auttamalla tappamaan pelaajia." +bedwars.3208="Ostit %%item%% (+1 Hopeakolikko [[%%total%%])" +bedwars.3209="Klikkaa ottaaksesi käyttöön!" +#bedwars.3210="" # No translation available +bedwars.3211="sänky" +#bedwars.3212="" # No translation available +bedwars.3213="Käyttämättömät pommimateriaalit" +#bedwars.3214="" # No translation available +bedwars.3215="Et voi käyttää tätä taistellessasi! Yritä uudelleen %%seconds%% sekunnin kuluttua." +bedwars.3216="%%current%%/%%required%% horroslippua" +bedwars.3217="Odotathan vielä %%seconds%% sekunti ennen kuin tiimisi käyttää tätä esinettä uudelleen." +bedwars.3218="Maksimi ender-tomu-varasto: %%amount%%" +bedwars.3219="KESKENERÄISET TAVOITTEET:" +bedwars.3220="Näkymättömyys poistuu, kun olet rikkonut 5 palikkaa." +bedwars.3221="Auta Pyykkäriä" +#bedwars.3222="" # No translation available +bedwars.3223="LUKITTU" +#bedwars.3224="" # No translation available +bedwars.3225="Horroslippukone tarjoaa sinulle loistavia palkintoja, kuten horroslippuja, kosmeettisia esineitä, Bed Wars -experienceä ja muuta!" +bedwars.3226="Hanki hohtava amuletti" +#bedwars.3227="" # No translation available +#bedwars.3228="" # No translation available +bedwars.3229="Tuo minulle %%diamonds%% Diamond Fragmenttiä, niin annan sinulle jotain takaisin." +bedwars.3230="Vesi" +bedwars.3231="Hetkinen, sanotko siis, että sinulla ei vieläkään ole %%amount%% %%item%%?" +bedwars.3232="ONNISTUIT! Toit Bill Starrille esineen %%item%%takaisin!" +#bedwars.3233="" # No translation available +bedwars.3234="Hanki %%amount%% Julmuuden merkkiä" +bedwars.3235="Kuninkaallisille sopiva parfyymi. Rouva Saichi uskoo olevansa kuninkaallinen." +bedwars.3236="teamColor" +bedwars.3237="XP-kerroin:" +bedwars.3238="%%name%%, oletko valmis?" +#bedwars.3239="" # No translation available +#bedwars.3240="" # No translation available +bedwars.3241="Klikkaa tästä päivittääksesi minionisi seuraavalle tasolle." +bedwars.3242="Tuota pelaaja ei löytynyt!" +bedwars.3243="Kenraali Dakun ender-tomu" +bedwars.3244="Vaikuttaisi olevan todella mukava tyyny sängystä. Tiimien resurssigeneraattorit pudottavat tyynyn kerran pelissä." +#bedwars.3245="" # No translation available +bedwars.3246="Tehtävät & tavoitteet" +#bedwars.3247="" # No translation available +bedwars.3248="Maksa %%amount%% horroslipulla" +bedwars.3249="Hinta: 75 horroslippua" +#bedwars.3250="" # No translation available +#bedwars.3251="" # No translation available +#bedwars.3252="" # No translation available +bedwars.3253="Terävyys %%tier%%" +bedwars.3254="Kimpale kääpiöiden mithriliä" +#bedwars.3255="" # No translation available +bedwars.3256="Auta tarkastaja Mayaa löytämään ensimmäinen murhan johtolanka." +#bedwars.3257="" # No translation available +#bedwars.3258="" # No translation available +#bedwars.3259="" # No translation available +bedwars.3260="Jos omistat auton, voit ottaa sytytystulpan siitä." +#bedwars.3261="" # No translation available +#bedwars.3262="" # No translation available +bedwars.3263="Klikkaa ovea poistuaksesi" +#bedwars.3264="" # No translation available +bedwars.3265="Peruuta hakemus" +#bedwars.3266="" # No translation available +#bedwars.3267="" # No translation available +bedwars.3268="Klassinen vadelman makuinen pirtelö, jonka päällä on reilu kauhallinen vaniljajäätelöä." +bedwars.3269="Maksa %%amount%% lipulla?" +#bedwars.3270="" # No translation available +#bedwars.3271="" # No translation available +bedwars.3272="Et voi puhua hiekkamiehen kanssa vielä! Jatka vieraiden auttamista hotellissa, kiitos." +#bedwars.3273="" # No translation available +bedwars.3274="Sinulla ei ole enempää nuolia tavaraluettelossasi!" +#bedwars.3275="" # No translation available +#bedwars.3276="" # No translation available +bedwars.3277="Hanki %%item%% teleporttaamalla ympäriinsä Ender-helmillä Bed Wars -peleissä. Saat yhden mg:n Ender-tomua jokaisesta matkustetusta palikasta." +#bedwars.3278="" # No translation available +#bedwars.3279="" # No translation available +bedwars.3280="Peliäsi ei löytynyt!" +#bedwars.3281="" # No translation available +#bedwars.3282="" # No translation available +#bedwars.3283="" # No translation available +bedwars.3284="Pelaa lippukoneella!" +#bedwars.3285="" # No translation available +#bedwars.3286="" # No translation available +#bedwars.3287="" # No translation available +bedwars.3288="Bed Wars -experience" +bedwars.3289="MENEILLÄÄN" +bedwars.3290="Käyttämättömiä pommimateriaaleja, mikä sääli ettei näitä käytetty." +bedwars.3291="Kultaharkko" +bedwars.3292="Vaatii Ikuiset sakset" +#bedwars.3293="" # No translation available +#bedwars.3294="" # No translation available +bedwars.3295="Klikkaa päästäksesi sisään" +bedwars.3296="Maksimi lippuvarasto: %%amount%%" +bedwars.3297="Kerää kaikki" +#bedwars.3298="" # No translation available +bedwars.3299="Klikkaa katsoaksesi tiimipäivityksiä!" +bedwars.3300="Et voi laittaa tätä pelaajaa nukkumaan tyhjyyden yllä!" +#bedwars.3301="" # No translation available +#bedwars.3302="" # No translation available +#bedwars.3303="" # No translation available +#bedwars.3304="" # No translation available +#bedwars.3305="" # No translation available +#bedwars.3306="" # No translation available +#bedwars.3307="" # No translation available +bedwars.3308="Tämä pelaaja ei ole enään paikalla! Yritä myöhemmin uudelleen." +#bedwars.3309="" # No translation available +#bedwars.3310="" # No translation available +#bedwars.3311="" # No translation available +#bedwars.3312="" # No translation available +bedwars.3313="Horrosesineet" +bedwars.3314="Kerää %%amount%% mukavaa tyynyä" +#bedwars.3315="" # No translation available +#bedwars.3316="" # No translation available +bedwars.3317="Omistat tällä hetkellä %%emeralds%% smaragdia." +bedwars.3318="Tapaa Hiekkamies" +#bedwars.3319="" # No translation available +#bedwars.3320="" # No translation available +bedwars.3321="Sait %%amount%% experienceä" +#bedwars.3322="" # No translation available +#bedwars.3323="" # No translation available +bedwars.3324="Smaragdit" +bedwars.3325="[NPC] %%name%%: " +bedwars.3326="Murhaveitsi puhdistettu" +bedwars.3327="Hanki %%amount%% mukavaa tyynyä" +bedwars.3328="Tuo CEO:lle %%amount%% %%item%%, joita saa voittamalla Bed Wars -pelejä." +#bedwars.3329="" # No translation available +bedwars.3330="Voita veto" +#bedwars.3331="" # No translation available +bedwars.3332="Kerää %%amount%% nether-tähteä" +#bedwars.3333="" # No translation available +#bedwars.3334="" # No translation available +bedwars.3335="Keitaan siunaus" +bedwars.3336="TEHTÄVÄ" +#bedwars.3337="" # No translation available +#bedwars.3338="" # No translation available +#bedwars.3339="" # No translation available +#bedwars.3340="" # No translation available +#bedwars.3341="" # No translation available +bedwars.3342="AVATTU!" +#bedwars.3343="" # No translation available +#bedwars.3344="" # No translation available +bedwars.3345="Etkö osaa päättää, mitä tilata? Yritä Salaperäistä pirtelöä ja anna meidän tehdä päätös puolestasi!" +#bedwars.3346="" # No translation available +bedwars.3347="Horroslippuja voi saada näin: " +#bedwars.3348="" # No translation available +#bedwars.3349="" # No translation available +#bedwars.3350="" # No translation available +#bedwars.3351="" # No translation available +#bedwars.3352="" # No translation available +bedwars.3353="Auta John Indigosia" +#bedwars.3354="" # No translation available +#bedwars.3355="" # No translation available +bedwars.3356="Poistettiin Horroshotellin musiikki käytöstä." +#bedwars.3357="" # No translation available +bedwars.3358="Tarkkuus: " +bedwars.3359="[Näytä johtolangat]" +bedwars.3360="Etsi jotain, jolla voi korvata figuriinin" +#bedwars.3361="" # No translation available +#bedwars.3362="" # No translation available +bedwars.3363="Lähestyit ovea oikeiden esineiden kanssa!" +bedwars.3364="Sinulla ei ole tarpeeksi lippuja avataksesi tätä ovea." +#bedwars.3365="" # No translation available +#bedwars.3366="" # No translation available +#bedwars.3367="" # No translation available +bedwars.3368="Avasit: %%name%%" +#bedwars.3369="" # No translation available +bedwars.3370="Likaiset saappaat" +bedwars.3371="Avasit Hiekkamiehen figuriinin!" +#bedwars.3372="" # No translation available +#bedwars.3373="" # No translation available +#bedwars.3374="" # No translation available +#bedwars.3375="" # No translation available +#bedwars.3376="" # No translation available +#bedwars.3377="" # No translation available +bedwars.3378="Polttoaine" +bedwars.3379="Rauta" +bedwars.3380="Kulta" +bedwars.3381="Timantti" +bedwars.3382="Smaragdi" +bedwars.3383="Safiiri" +bedwars.3384="Rubiini" +bedwars.3385="Kristalli" +bedwars.3386="Opaali" +bedwars.3387="Ametisti" +bedwars.3388="Sateenkaari" +#bedwars.3389="" # No translation available +#bedwars.3390="" # No translation available +#bedwars.3391="" # No translation available +#bedwars.3392="" # No translation available +#bedwars.3393="" # No translation available +#bedwars.3394="" # No translation available +#bedwars.3395="" # No translation available +#bedwars.3396="" # No translation available +#bedwars.3397="" # No translation available +bedwars.3398="Peili" +bedwars.3399="Valo" +bedwars.3400="Aamunkoi" +bedwars.3401="Iltahämärä" +bedwars.3402="Ilma" +bedwars.3403="Tuuli" +bedwars.3404="Nebula" +bedwars.3405="Maa" +bedwars.3406="Vesi" +bedwars.3407="Tuli" +bedwars.3408="Auringonnousu" +bedwars.3409="Pimennys" +bedwars.3410="Gamma" +bedwars.3411="Majesteettinen" +#bedwars.3412="" # No translation available +bedwars.3413="Marine" +bedwars.3414="Elementti" +bedwars.3415="Galaksi" +bedwars.3416="Atomi" +bedwars.3417="Auringonlasku" +bedwars.3418="Aikaväli" +bedwars.3419="Talvi" +bedwars.3420="Obsidiaani" +bedwars.3421="Kevät" +bedwars.3422="Jää" +bedwars.3423="Kesä" +bedwars.3424="Spinelli" +bedwars.3425="Syksy" +bedwars.3426="Mystinen" +bedwars.3427="Ikuinen" +bedwars.3428="Smaragdi" +bedwars.3429="Timantti" +#bedwars.3430="" # No translation available +#bedwars.3431="" # No translation available +#bedwars.3432="" # No translation available +#bedwars.3433="" # No translation available +bedwars.3434="Hei, sinulla on figuriini! Loistavaa." +#bedwars.3435="" # No translation available +#bedwars.3436="" # No translation available +#bedwars.3437="" # No translation available +bedwars.3438="Et saa käyttää tuollaista väkivaltaa hotellissa." +bedwars.3439="Ystävien lyöminen on kiellettyä täällä." +bedwars.3440="Ainoastaan vastaanottovirkailija on lyömisen arvoinen hotellissa." +bedwars.3441="Lyöminen tässä pyhässä hotellissa on kiellettyä." +bedwars.3442="Ei. Jätä lyöminen peleihin." +bedwars.3443="Jaahas, mitäs täältä löytyy? Joku, joka luulee voivansa lyödä ystäviään!" +bedwars.3444="Vastaanottovirkailija ei ole tyytyväinen tällaiseen käytökseen." +bedwars.3445="Hei! Lopeta tuo." +bedwars.3446="Kunnioita kaikkia pelaajia hotellissa." +bedwars.3447="Okei, tuo on vain ilkeää." +bedwars.3448="Pirtelö-Mike" +bedwars.3449="Pirtelöiden rakastaja" +bedwars.3450="Valtaistuinovi" +bedwars.3451="Hotellin ovi" +bedwars.3452="Aavikko-ovi" +bedwars.3453="Sähköovi" +bedwars.3454="Ovi taivaasta" +bedwars.3455="Ovi telkkarissa" +bedwars.3456="Pilvenpiirtäjän ovi" +bedwars.3457="Arcade-ovi" +bedwars.3458="Monimutkainen ovi" +bedwars.3459="Avaruusovi" +bedwars.3460="0 v 1" +bedwars.3461="Autotallin ovi" +bedwars.3462="Omistajan toimisto" +bedwars.3463="Ei tarvitse painaa sitä niin monta kertaa olen tässä!" +bedwars.3464="Hillitse itsesi olen tulossa!" +bedwars.3465="MISSÄ PALAA?!" +bedwars.3466="Aa, sinä vain." +bedwars.3467="Voitko lopettaa?!?!" +bedwars.3468="Poistan tuon kellon." +bedwars.3469="Haahaa sillanrakennus ei tosiaan ole juttusi?" +#bedwars.3470="" # No translation available +#bedwars.3471="" # No translation available +bedwars.3472="Verinen ja kulunut veitsi." +#bedwars.3473="" # No translation available +#bedwars.3474="" # No translation available +#bedwars.3475="" # No translation available +#bedwars.3476="" # No translation available +#bedwars.3477="" # No translation available +#bedwars.3478="" # No translation available +#bedwars.3479="" # No translation available +#bedwars.3480="" # No translation available +#bedwars.3481="" # No translation available +#bedwars.3482="" # No translation available +#bedwars.3483="" # No translation available +#bedwars.3484="" # No translation available +#bedwars.3485="" # No translation available +#bedwars.3486="" # No translation available +#bedwars.3487="" # No translation available +#bedwars.3488="" # No translation available +#bedwars.3489="" # No translation available +#bedwars.3490="" # No translation available +#bedwars.3491="" # No translation available +bedwars.3492="Avaa ovi" +#bedwars.3493="" # No translation available +bedwars.3494="Horrostehtävämuistio" +#bedwars.3495="" # No translation available +bedwars.3496="Osta ilotulitusnäytös" +bedwars.3497="Horrostavaraluettelo" +#bedwars.3498="" # No translation available +bedwars.3499="Anna horroslippuja" +#bedwars.3500="" # No translation available +#bedwars.3501="" # No translation available +#bedwars.3502="" # No translation available +#bedwars.3503="" # No translation available +bedwars.3504="Näytä tehokkain kohta tälle minionille." +#bedwars.3505="" # No translation available +#bedwars.3506="" # No translation available +#bedwars.3507="" # No translation available +#bedwars.3508="" # No translation available +#bedwars.3509="" # No translation available +#bedwars.3510="" # No translation available +#bedwars.3511="" # No translation available +#bedwars.3512="" # No translation available +#bedwars.3513="" # No translation available +#bedwars.3514="" # No translation available +#bedwars.3515="" # No translation available +#bedwars.3516="" # No translation available +#bedwars.3517="" # No translation available +bedwars.3518="Useimmat ihmiset nukahtavat yöllä noin 10-15 minuutissa." +#bedwars.3519="" # No translation available +#bedwars.3520="" # No translation available +bedwars.3521="Miksi kutsut nukkuvaa pizzaa? Pizzzzzzzzzzzaksi!" +#bedwars.3522="" # No translation available +bedwars.3523="Rakastan ilotulitteita!" +bedwars.3524="Haluatko nähdä ilotulitusnäytöksen?" +#bedwars.3525="" # No translation available +#bedwars.3526="" # No translation available +bedwars.3527="Rakastan pirtelöitä!" +#bedwars.3528="" # No translation available +#bedwars.3529="" # No translation available +#bedwars.3530="" # No translation available +#bedwars.3531="" # No translation available +#bedwars.3532="" # No translation available +#bedwars.3533="" # No translation available +bedwars.3534="Hei! Tervetuloa Horroshotelliin!" +#bedwars.3535="" # No translation available +bedwars.3536="Ihanaa!" +#bedwars.3537="" # No translation available +#bedwars.3538="" # No translation available +#bedwars.3539="" # No translation available +#bedwars.3540="" # No translation available +#bedwars.3541="" # No translation available +#bedwars.3542="" # No translation available +#bedwars.3543="" # No translation available +#bedwars.3544="" # No translation available +#bedwars.3545="" # No translation available +#bedwars.3546="" # No translation available +#bedwars.3547="" # No translation available +#bedwars.3548="" # No translation available +#bedwars.3549="" # No translation available +#bedwars.3550="" # No translation available +#bedwars.3551="" # No translation available +bedwars.3552="... On aika mennä syvemmälle." +#bedwars.3553="" # No translation available +#bedwars.3554="" # No translation available +bedwars.3555="Hän tapaa sinut pian." +#bedwars.3556="" # No translation available +#bedwars.3557="" # No translation available +#bedwars.3558="" # No translation available +#bedwars.3559="" # No translation available +#bedwars.3560="" # No translation available +#bedwars.3561="" # No translation available +#bedwars.3562="" # No translation available +#bedwars.3563="" # No translation available +#bedwars.3564="" # No translation available +#bedwars.3565="" # No translation available +#bedwars.3566="" # No translation available +#bedwars.3567="" # No translation available +#bedwars.3568="" # No translation available +#bedwars.3569="" # No translation available +#bedwars.3570="" # No translation available +#bedwars.3571="" # No translation available +#bedwars.3572="" # No translation available +#bedwars.3573="" # No translation available +#bedwars.3574="" # No translation available +#bedwars.3575="" # No translation available +#bedwars.3576="" # No translation available +#bedwars.3577="" # No translation available +#bedwars.3578="" # No translation available +#bedwars.3579="" # No translation available +#bedwars.3580="" # No translation available +#bedwars.3581="" # No translation available +bedwars.3582="Lippukone" +#bedwars.3583="" # No translation available +#bedwars.3584="" # No translation available +bedwars.3585="Olen hiekkamies." +#bedwars.3586="" # No translation available +#bedwars.3587="" # No translation available +#bedwars.3588="" # No translation available +#bedwars.3589="" # No translation available +#bedwars.3590="" # No translation available +#bedwars.3591="" # No translation available +#bedwars.3592="" # No translation available +#bedwars.3593="" # No translation available +bedwars.3594="Hiekkamies" +#bedwars.3595="" # No translation available +#bedwars.3596="" # No translation available +#bedwars.3597="" # No translation available +#bedwars.3598="" # No translation available +#bedwars.3599="" # No translation available +#bedwars.3600="" # No translation available +#bedwars.3601="" # No translation available +#bedwars.3602="" # No translation available +#bedwars.3603="" # No translation available +bedwars.3604=":o" +#bedwars.3605="" # No translation available +#bedwars.3606="" # No translation available +#bedwars.3607="" # No translation available +#bedwars.3608="" # No translation available +#bedwars.3609="" # No translation available +#bedwars.3610="" # No translation available +#bedwars.3611="" # No translation available +#bedwars.3612="" # No translation available +#bedwars.3613="" # No translation available +#bedwars.3614="" # No translation available +#bedwars.3615="" # No translation available +#bedwars.3616="" # No translation available +#bedwars.3617="" # No translation available +#bedwars.3618="" # No translation available +#bedwars.3619="" # No translation available +#bedwars.3620="" # No translation available +#bedwars.3621="" # No translation available +#bedwars.3622="" # No translation available +#bedwars.3623="" # No translation available +#bedwars.3624="" # No translation available +#bedwars.3625="" # No translation available +#bedwars.3626="" # No translation available +#bedwars.3627="" # No translation available +#bedwars.3628="" # No translation available +#bedwars.3629="" # No translation available +#bedwars.3630="" # No translation available +#bedwars.3631="" # No translation available +#bedwars.3632="" # No translation available +#bedwars.3633="" # No translation available +#bedwars.3634="" # No translation available +#bedwars.3635="" # No translation available +#bedwars.3636="" # No translation available +#bedwars.3637="" # No translation available +#bedwars.3638="" # No translation available +#bedwars.3639="" # No translation available +#bedwars.3640="" # No translation available +#bedwars.3641="" # No translation available +#bedwars.3642="" # No translation available +#bedwars.3643="" # No translation available +#bedwars.3644="" # No translation available +#bedwars.3645="" # No translation available +#bedwars.3646="" # No translation available +#bedwars.3647="" # No translation available +#bedwars.3648="" # No translation available +#bedwars.3649="" # No translation available +#bedwars.3650="" # No translation available +#bedwars.3651="" # No translation available +#bedwars.3652="" # No translation available +#bedwars.3653="" # No translation available +#bedwars.3654="" # No translation available +#bedwars.3655="" # No translation available +#bedwars.3656="" # No translation available +#bedwars.3657="" # No translation available +#bedwars.3658="" # No translation available +#bedwars.3659="" # No translation available +#bedwars.3660="" # No translation available +#bedwars.3661="" # No translation available +#bedwars.3662="" # No translation available +#bedwars.3663="" # No translation available +#bedwars.3664="" # No translation available +#bedwars.3665="" # No translation available +#bedwars.3666="" # No translation available +#bedwars.3667="" # No translation available +#bedwars.3668="" # No translation available +#bedwars.3669="" # No translation available +#bedwars.3670="" # No translation available +#bedwars.3671="" # No translation available +#bedwars.3672="" # No translation available +#bedwars.3673="" # No translation available +#bedwars.3674="" # No translation available +#bedwars.3675="" # No translation available +#bedwars.3676="" # No translation available +#bedwars.3677="" # No translation available +#bedwars.3678="" # No translation available +#bedwars.3679="" # No translation available +#bedwars.3680="" # No translation available +#bedwars.3681="" # No translation available +#bedwars.3682="" # No translation available +#bedwars.3683="" # No translation available +#bedwars.3684="" # No translation available +#bedwars.3685="" # No translation available +#bedwars.3686="" # No translation available +#bedwars.3687="" # No translation available +#bedwars.3688="" # No translation available +#bedwars.3689="" # No translation available +#bedwars.3690="" # No translation available +#bedwars.3691="" # No translation available +#bedwars.3692="" # No translation available +#bedwars.3693="" # No translation available +#bedwars.3694="" # No translation available +#bedwars.3695="" # No translation available +#bedwars.3696="" # No translation available +#bedwars.3697="" # No translation available +bedwars.3698="Nimeni on Sally." +#bedwars.3699="" # No translation available +#bedwars.3700="" # No translation available +#bedwars.3701="" # No translation available +#bedwars.3702="" # No translation available +#bedwars.3703="" # No translation available +#bedwars.3704="" # No translation available +#bedwars.3705="" # No translation available +#bedwars.3706="" # No translation available +#bedwars.3707="" # No translation available +bedwars.3708="Tuo minulle lisää!" +#bedwars.3709="" # No translation available +#bedwars.3710="" # No translation available +#bedwars.3711="" # No translation available +#bedwars.3712="" # No translation available +#bedwars.3713="" # No translation available +#bedwars.3714="" # No translation available +#bedwars.3715="" # No translation available +#bedwars.3716="" # No translation available +bedwars.3717="OLETKO KUURO" +#bedwars.3718="" # No translation available +bedwars.3719="TYKKÄÄN METALLEISTA" +#bedwars.3720="" # No translation available +bedwars.3721="GOOGLASIN SEN" +#bedwars.3722="" # No translation available +#bedwars.3723="" # No translation available +#bedwars.3724="" # No translation available +#bedwars.3725="" # No translation available +#bedwars.3726="" # No translation available +#bedwars.3727="" # No translation available +#bedwars.3728="" # No translation available +#bedwars.3729="" # No translation available +#bedwars.3730="" # No translation available +#bedwars.3731="" # No translation available +#bedwars.3732="" # No translation available +#bedwars.3733="" # No translation available +#bedwars.3734="" # No translation available +#bedwars.3735="" # No translation available +bedwars.3736="Tulen Jupiterista." +#bedwars.3737="" # No translation available +#bedwars.3738="" # No translation available +#bedwars.3739="" # No translation available +#bedwars.3740="" # No translation available +#bedwars.3741="" # No translation available +#bedwars.3742="" # No translation available +#bedwars.3743="" # No translation available +#bedwars.3744="" # No translation available +#bedwars.3745="" # No translation available +#bedwars.3746="" # No translation available +#bedwars.3747="" # No translation available +#bedwars.3748="" # No translation available +#bedwars.3749="" # No translation available +#bedwars.3750="" # No translation available +#bedwars.3751="" # No translation available +#bedwars.3752="" # No translation available +#bedwars.3753="" # No translation available +#bedwars.3754="" # No translation available +#bedwars.3755="" # No translation available +#bedwars.3756="" # No translation available +#bedwars.3757="" # No translation available +#bedwars.3758="" # No translation available +bedwars.3759="Näetkö tämän ison holvin?" +bedwars.3760="Lyön vetoa, että he piilottelevat lippujansa siellä." +bedwars.3761="Luultavasti myös kolikoita." +bedwars.3762="Sinä haluat päästä sisään? Minä haluan päästä sisään." +bedwars.3763="Tehdään yhteistyötä!" +bedwars.3764="Tarvitsen useita materiaaleja tehdäkseni pommin ja harhautuksen." +bedwars.3765="Luota minuun. Se on sen arvoista... Toivottavasti." +bedwars.3766="Haluan todella tietää mitä tuolla on!" +bedwars.3767="Nämä ovat meidän pommia ja harhautusta varten." +bedwars.3768="No niin, peräänny hieman ja seuraa ammattilaista." +bedwars.3769="Hei vartija, smaragdeja!" +bedwars.3770="Nyt riitti, olet käyttäytynyt epäilyttävästi jo jonkin aikaa." +bedwars.3771="Tulet mukaani." +bedwars.3772="En olisi koskaan saanut tätä miestä kiinni, jos et olisi puhunut hänelle aikaisemmin." +bedwars.3773="Tässä palkinto, kansalainen." +bedwars.3774="Vuosisadan ryöstö!" +#bedwars.3775="" # No translation available +bedwars.3776="... Minulla oli nimi, mutta en enää muista sitä." +#bedwars.3777="" # No translation available +#bedwars.3778="" # No translation available +#bedwars.3779="" # No translation available +#bedwars.3780="" # No translation available +#bedwars.3781="" # No translation available +#bedwars.3782="" # No translation available +bedwars.3783="äijäääääääääääääääää" +bedwars.3784="kuinka kauan olet pelannut bed warsia?" +bedwars.3785="äijä, ÄIJÄ" +#bedwars.3786="" # No translation available +#bedwars.3787="" # No translation available +bedwars.3788="bruhhhh" +bedwars.3789="voitaks sä ees" +bedwars.3790="vaan voittajat saavat lippuja" +bedwars.3791="kiipee sitä tulostaulukkoa" +bedwars.3792="Taisin nähdä sut tulostaulukolla" +bedwars.3793="kiva" +#bedwars.3794="" # No translation available +#bedwars.3795="" # No translation available +#bedwars.3796="" # No translation available +#bedwars.3797="" # No translation available +#bedwars.3798="" # No translation available +#bedwars.3799="" # No translation available +#bedwars.3800="" # No translation available +#bedwars.3801="" # No translation available +bedwars.3802="Sen huomaa." +#bedwars.3803="" # No translation available +bedwars.3804="Vaikutat olevan hieman... sus." +bedwars.3805="Oletko murhaaja?" +#bedwars.3806="" # No translation available +#bedwars.3807="" # No translation available +#bedwars.3808="" # No translation available +bedwars.3809="Käytä tätä" +#bedwars.3810="" # No translation available +#bedwars.3811="" # No translation available +#bedwars.3812="" # No translation available +#bedwars.3813="" # No translation available +#bedwars.3814="" # No translation available +#bedwars.3815="" # No translation available +#bedwars.3816="" # No translation available +#bedwars.3817="" # No translation available +bedwars.3818="Nimeni on Bill Starr." +bedwars.3819="Olen selvinnyt kaikesta." +bedwars.3820="Pixelville, Thorin, Caelum, olen nähnyt kaiken." +bedwars.3821="Jotenkin se yksi asia, joka välttelee minua, on Blitz-tähti." +bedwars.3822="Vuosia Blitz-pelin parissa, eikä minulla veiläkään ole yhtä. Miten on mahdollista?" +#bedwars.3823="" # No translation available +bedwars.3824="Vuosia Blitz-pelin parissa, eikä minulla vieläkään ole tähteä." +#bedwars.3825="" # No translation available +bedwars.3826="Blitz-tähti?" +bedwars.3827="Löysit sellaisen!" +bedwars.3828="Ja jotenkin revit sen pelistä irti ja toit tänne minulle... miten." +bedwars.3829="Annatko sen minulle? Sepä mahtavaa. Ehkä jatkan Blitzin pelaamista." +bedwars.3830="Tämän tähden näkeminen saa minut uskomaan, että saan sellaisen lopulta." +#bedwars.3831="" # No translation available +#bedwars.3832="" # No translation available +#bedwars.3833="" # No translation available +#bedwars.3834="" # No translation available +#bedwars.3835="" # No translation available +#bedwars.3836="" # No translation available +#bedwars.3837="" # No translation available +#bedwars.3838="" # No translation available +#bedwars.3839="" # No translation available +#bedwars.3840="" # No translation available +#bedwars.3841="" # No translation available +#bedwars.3842="" # No translation available +#bedwars.3843="" # No translation available +bedwars.3844="Näyttää siltä, että tarvitset isomman lompakon astuaksesi tähän temppeliin." +#bedwars.3845="" # No translation available +bedwars.3846="Miten sinä... ihan sama." +#bedwars.3847="" # No translation available +#bedwars.3848="" # No translation available +#bedwars.3849="" # No translation available +#bedwars.3850="" # No translation available +#bedwars.3851="" # No translation available +#bedwars.3852="" # No translation available +#bedwars.3853="" # No translation available +#bedwars.3854="" # No translation available +#bedwars.3855="" # No translation available +#bedwars.3856="" # No translation available +#bedwars.3857="" # No translation available +#bedwars.3858="" # No translation available +#bedwars.3859="" # No translation available +#bedwars.3860="" # No translation available +#bedwars.3861="" # No translation available +#bedwars.3862="" # No translation available +#bedwars.3863="" # No translation available +bedwars.3864="Siinä se on - kultainen figuriini hiekkamiehestä." +#bedwars.3865="" # No translation available +#bedwars.3866="" # No translation available +#bedwars.3867="" # No translation available +#bedwars.3868="" # No translation available +#bedwars.3869="" # No translation available +#bedwars.3870="" # No translation available +#bedwars.3871="" # No translation available +#bedwars.3872="" # No translation available +#bedwars.3873="" # No translation available +#bedwars.3874="" # No translation available +#bedwars.3875="" # No translation available +#bedwars.3876="" # No translation available +#bedwars.3877="" # No translation available +#bedwars.3878="" # No translation available +#bedwars.3879="" # No translation available +#bedwars.3880="" # No translation available +#bedwars.3881="" # No translation available +bedwars.3882="Nähdään!" +bedwars.3883="Minun täytyy palata takaisin The Pitiin..." +bedwars.3884="Tämä paikka puistattaa minua..." +bedwars.3885="Haiskahtaa ihan... Bed Warsilta." +bedwars.3886="En tykkää Bed Warsista, the pit on juttuni." +bedwars.3887="Voitko näyttää minulle uloskäynnin?" +#bedwars.3888="" # No translation available +#bedwars.3889="" # No translation available +#bedwars.3890="" # No translation available +#bedwars.3891="" # No translation available +#bedwars.3892="" # No translation available +bedwars.3893="Peter" +#bedwars.3894="" # No translation available +#bedwars.3895="" # No translation available +bedwars.3896="Nääthän tämän myös?" +bedwars.3897="En ole hullu." +bedwars.3898="Tuolla ylhäällä on wither." +bedwars.3899="Se on karmiva ja tuijottaa meitä." +bedwars.3900="Jos emme hankkiudu siitä eroon, vihollistiimi jatkaa uudelleensyntymistä." +bedwars.3901="Ai mistä minä puhun? Sehän on yleistietoa, eikö?" +bedwars.3902="Joka tapauksessa, tarvitsen apuasi sen lähettämisessä takaisin sinne, mistä se tuli." +bedwars.3903="Me ansoitamme hänet ja käytämme nether-tähtiä teleportataksemme hänet takaisin Solaceen." +#bedwars.3904="" # No translation available +#bedwars.3905="" # No translation available +bedwars.3906="No niin, katsopa tätä!" +#bedwars.3907="" # No translation available +#bedwars.3908="" # No translation available +#bedwars.3909="" # No translation available +#bedwars.3910="" # No translation available +#bedwars.3911="" # No translation available +#bedwars.3912="" # No translation available +#bedwars.3913="" # No translation available +#bedwars.3914="" # No translation available +#bedwars.3915="" # No translation available +#bedwars.3916="" # No translation available +#bedwars.3917="" # No translation available +#bedwars.3918="" # No translation available +#bedwars.3919="" # No translation available +bedwars.3920="Ja maksan sinulle takaisin horroslipuilla." +#bedwars.3921="" # No translation available +#bedwars.3922="" # No translation available +#bedwars.3923="" # No translation available +#bedwars.3924="" # No translation available +#bedwars.3925="" # No translation available +#bedwars.3926="" # No translation available +#bedwars.3927="" # No translation available +#bedwars.3928="" # No translation available +#bedwars.3929="" # No translation available +#bedwars.3930="" # No translation available +bedwars.3931="Tässä ovat lippunne!" +#bedwars.3932="" # No translation available +#bedwars.3933="" # No translation available +#bedwars.3934="" # No translation available +#bedwars.3935="" # No translation available +#bedwars.3936="" # No translation available +bedwars.3937="Tässä ovat lippunne." +bedwars.3938="Yritän pyörittää keittiötä täällä!" +#bedwars.3939="" # No translation available +#bedwars.3940="" # No translation available +#bedwars.3941="" # No translation available +#bedwars.3942="" # No translation available +#bedwars.3943="" # No translation available +#bedwars.3944="" # No translation available +#bedwars.3945="" # No translation available +#bedwars.3946="" # No translation available +#bedwars.3947="" # No translation available +#bedwars.3948="" # No translation available +#bedwars.3949="" # No translation available +#bedwars.3950="" # No translation available +#bedwars.3951="" # No translation available +#bedwars.3952="" # No translation available +#bedwars.3953="" # No translation available +#bedwars.3954="" # No translation available +#bedwars.3955="" # No translation available +#bedwars.3956="" # No translation available +bedwars.3957="Olen nälkäinen." +#bedwars.3958="" # No translation available +#bedwars.3959="" # No translation available +#bedwars.3960="" # No translation available +#bedwars.3961="" # No translation available +#bedwars.3962="" # No translation available +#bedwars.3963="" # No translation available +#bedwars.3964="" # No translation available +bedwars.3965="Vasara" +#bedwars.3966="" # No translation available +#bedwars.3967="" # No translation available +#bedwars.3968="" # No translation available +#bedwars.3969="" # No translation available +#bedwars.3970="" # No translation available +bedwars.3971="Maksan sinulla takaisin, lupaan!" +bedwars.3972="Eikö sinulla ole vielä kolikot kasassa?" +bedwars.3973="Oletko täysin järjiltäsi?" +#bedwars.3974="" # No translation available +#bedwars.3975="" # No translation available +bedwars.3976="En osaa päättää..." +#bedwars.3977="" # No translation available +#bedwars.3978="" # No translation available +#bedwars.3979="" # No translation available +#bedwars.3980="" # No translation available +#bedwars.3981="" # No translation available +#bedwars.3982="" # No translation available +#bedwars.3983="" # No translation available +#bedwars.3984="" # No translation available +#bedwars.3985="" # No translation available +#bedwars.3986="" # No translation available +#bedwars.3987="" # No translation available +#bedwars.3988="" # No translation available +#bedwars.3989="" # No translation available +#bedwars.3990="" # No translation available +#bedwars.3991="" # No translation available +#bedwars.3992="" # No translation available +#bedwars.3993="" # No translation available +bedwars.3994="En tiedä mistä aloittaa!" +#bedwars.3995="" # No translation available +#bedwars.3996="" # No translation available +#bedwars.3997="" # No translation available +#bedwars.3998="" # No translation available +#bedwars.3999="" # No translation available +#bedwars.4000="" # No translation available +#bedwars.4001="" # No translation available +#bedwars.4002="" # No translation available +#bedwars.4003="" # No translation available +#bedwars.4004="" # No translation available +#bedwars.4005="" # No translation available +#bedwars.4006="" # No translation available +#bedwars.4007="" # No translation available +bedwars.4008="Minun ei olisi pitänyt haahuilla pois." +#bedwars.4009="" # No translation available +#bedwars.4010="" # No translation available +#bedwars.4011="" # No translation available +#bedwars.4012="" # No translation available +#bedwars.4013="" # No translation available +#bedwars.4014="" # No translation available +#bedwars.4015="" # No translation available +#bedwars.4016="" # No translation available +#bedwars.4017="" # No translation available +#bedwars.4018="" # No translation available +#bedwars.4019="" # No translation available +#bedwars.4020="" # No translation available +#bedwars.4021="" # No translation available +#bedwars.4022="" # No translation available +#bedwars.4023="" # No translation available +#bedwars.4024="" # No translation available +#bedwars.4025="" # No translation available +#bedwars.4026="" # No translation available +#bedwars.4027="" # No translation available +#bedwars.4028="" # No translation available +#bedwars.4029="" # No translation available +#bedwars.4030="" # No translation available +#bedwars.4031="" # No translation available +#bedwars.4032="" # No translation available +#bedwars.4033="" # No translation available +#bedwars.4034="" # No translation available +#bedwars.4035="" # No translation available +#bedwars.4036="" # No translation available +#bedwars.4037="" # No translation available +#bedwars.4038="" # No translation available +#bedwars.4039="" # No translation available +#bedwars.4040="" # No translation available +#bedwars.4041="" # No translation available +#bedwars.4042="" # No translation available +#bedwars.4043="" # No translation available +bedwars.4044="Älä tuhlaa sitä..." +bedwars.4045="Kiitos, siinä on kaikki tarvitsemani." +#bedwars.4046="" # No translation available +#bedwars.4047="" # No translation available +#bedwars.4048="" # No translation available +#bedwars.4049="" # No translation available +#bedwars.4050="" # No translation available +#bedwars.4051="" # No translation available +#bedwars.4052="" # No translation available +#bedwars.4053="" # No translation available +#bedwars.4054="" # No translation available +#bedwars.4055="" # No translation available +#bedwars.4056="" # No translation available +#bedwars.4057="" # No translation available +#bedwars.4058="" # No translation available +#bedwars.4059="" # No translation available +#bedwars.4060="" # No translation available +#bedwars.4061="" # No translation available +#bedwars.4062="" # No translation available +#bedwars.4063="" # No translation available +#bedwars.4064="" # No translation available +#bedwars.4065="" # No translation available +#bedwars.4066="" # No translation available +#bedwars.4067="" # No translation available +#bedwars.4068="" # No translation available +#bedwars.4069="" # No translation available +bedwars.4070="Murha on tapahtunut" +#bedwars.4071="" # No translation available +#bedwars.4072="" # No translation available +#bedwars.4073="" # No translation available +#bedwars.4074="" # No translation available +#bedwars.4075="" # No translation available +#bedwars.4076="" # No translation available +#bedwars.4077="" # No translation available +bedwars.4078="äijä sun täytyy voittaa" +bedwars.4079="Hei!" +#bedwars.4080="" # No translation available +#bedwars.4081="" # No translation available +#bedwars.4082="" # No translation available +#bedwars.4083="" # No translation available +#bedwars.4084="" # No translation available +#bedwars.4085="" # No translation available +bedwars.4086="Käytetyt hanskat" +#bedwars.4087="" # No translation available +#bedwars.4088="" # No translation available +bedwars.4089="Blitz-tähti" +bedwars.4090="Oletus" +#bedwars.4091="" # No translation available +#bedwars.4092="" # No translation available +#bedwars.4093="" # No translation available +bedwars.4094="Seikkailijan lompakko" +bedwars.4095="Hotellin henkilökunnan lompakko" +#bedwars.4096="" # No translation available +bedwars.4097="Tilastoja, saavutuksia, tehtäviä ja kolikoita EI ansaita tässä pelimuodossa!" +bedwars.4098="Tehtäviä suorittamalla voit avata ainutlaatuisia kosmeettisia esineitä, joita voi sitten ostaa Bed Wars -poleteilla." +bedwars.4099="• Bed Wars -poletit- %%chance%%% mahdollisuus" +bedwars.4100="Pesällinen tipuja" +bedwars.4101="Suklaapupu" +bedwars.4102="Herra muna" +#bedwars.4103="" # No translation available +#bedwars.4104="" # No translation available +bedwars.4105="Onkivapa" +bedwars.4106="Mansikka" +bedwars.4107="Palmu" +bedwars.4108="Kookospähkinä" +bedwars.4109="Liekki" +#bedwars.4110="" # No translation available +#bedwars.4111="" # No translation available +bedwars.4112="Kyklooppi" +bedwars.4113="Pöllö" +#bedwars.4114="" # No translation available +#bedwars.4115="" # No translation available +#bedwars.4116="" # No translation available +#bedwars.4117="" # No translation available +#bedwars.4118="" # No translation available +#bedwars.4119="" # No translation available +#bedwars.4120="" # No translation available +#bedwars.4121="" # No translation available +#bedwars.4122="" # No translation available +#bedwars.4123="" # No translation available +#bedwars.4124="" # No translation available +#bedwars.4125="" # No translation available +#bedwars.4126="" # No translation available +#bedwars.4127="" # No translation available +#bedwars.4128="" # No translation available +#bedwars.4129="" # No translation available +#bedwars.4130="" # No translation available +#bedwars.4131="" # No translation available +#bedwars.4132="" # No translation available +#bedwars.4133="" # No translation available +#bedwars.4134="" # No translation available +#bedwars.4135="" # No translation available +#bedwars.4136="" # No translation available +#bedwars.4137="" # No translation available +#bedwars.4138="" # No translation available +bedwars.4139="Piknik-kori" +bedwars.4140="Kastelukannu" +bedwars.4141="Erakkorapu" +bedwars.4142="Purjevene" +#bedwars.4143="" # No translation available +bedwars.4144="Simpukka" +bedwars.4145="Sateenvarjo" +#bedwars.4146="" # No translation available +#bedwars.4147="" # No translation available +#bedwars.4148="" # No translation available +#bedwars.4149="" # No translation available +#bedwars.4150="" # No translation available +#bedwars.4151="" # No translation available +#bedwars.4152="" # No translation available +#bedwars.4153="" # No translation available +#bedwars.4154="" # No translation available +#bedwars.4155="" # No translation available +#bedwars.bedwars.new_item_in_4="" # No translation available +#bedwars.bedwars.new_item_in_3="" # No translation available +#bedwars.bedwars.new_item_in_1="" # No translation available +#bedwars.4159="" # No translation available +#bedwars.4160="" # No translation available +#bedwars.4161="" # No translation available +#bedwars.4162="" # No translation available +#bedwars.4163="" # No translation available +#bedwars.4164="" # No translation available +#bedwars.4165="" # No translation available +#bedwars.4166="" # No translation available +#bedwars.4167="" # No translation available +#bedwars.4168="" # No translation available +#bedwars.4169="" # No translation available +#bedwars.4170="" # No translation available +#bedwars.4171="" # No translation available +#bedwars.4172="" # No translation available +#bedwars.4173="" # No translation available +#bedwars.4174="" # No translation available +#bedwars.4175="" # No translation available +#bedwars.4176="" # No translation available +#bedwars.4177="" # No translation available +#bedwars.4178="" # No translation available +#bedwars.4179="" # No translation available +#bedwars.4180="" # No translation available +#bedwars.4181="" # No translation available +#bedwars.4182="" # No translation available +bedwars.4183="Vaihtuu %%hours%% tunnin kuluttua!" +bedwars.4184="Vaihtuu tunnin kuluttua!" +bedwars.4185="Vaihtuu %%minutes%% minuutin kuluttua!" +bedwars.4186="Vaihtuu pian!" +#bedwars.4187="" # No translation available +#bedwars.4188="" # No translation available +#bedwars.4189="" # No translation available +#bedwars.4190="" # No translation available +#bedwars.4191="" # No translation available +bedwars.4192="Kuukausittaiset voitot" +#bedwars.4193="" # No translation available +#bedwars.4194="" # No translation available +bedwars.4195="Hakku" +bedwars.4196="Kirves" +bedwars.4197="Keritsimet" +#bedwars.4198="" # No translation available +#bedwars.4199="" # No translation available +#bedwars.4200="" # No translation available +#bedwars.4201="" # No translation available +#bedwars.4202="" # No translation available +#bedwars.4203="" # No translation available +#bedwars.4204="" # No translation available +#bedwars.4205="" # No translation available +#bedwars.4206="" # No translation available +#bedwars.4207="" # No translation available +#bedwars.4208="" # No translation available +#bedwars.4209="" # No translation available +#bedwars.4210="" # No translation available +#bedwars.4211="" # No translation available +#bedwars.4212="" # No translation available +#bedwars.4213="" # No translation available +#bedwars.4214="" # No translation available +#bedwars.4215="" # No translation available +#bedwars.4216="" # No translation available +#bedwars.4217="" # No translation available +#bedwars.4218="" # No translation available +#bedwars.4219="" # No translation available +#bedwars.4220="" # No translation available +#bedwars.4221="" # No translation available +#bedwars.4222="" # No translation available +#bedwars.4223="" # No translation available +#bedwars.4224="" # No translation available +#bedwars.4225="" # No translation available +#bedwars.4226="" # No translation available +#bedwars.4227="" # No translation available +#bedwars.4228="" # No translation available +#bedwars.4229="" # No translation available +#bedwars.4230="" # No translation available +#bedwars.4231="" # No translation available +#bedwars.4232="" # No translation available +#bedwars.4233="" # No translation available +#bedwars.4234="" # No translation available +#bedwars.4235="" # No translation available +#bedwars.4236="" # No translation available +#bedwars.4237="" # No translation available +#bedwars.4238="" # No translation available +#bedwars.4239="" # No translation available +#bedwars.4240="" # No translation available +#bedwars.4241="" # No translation available +#bedwars.4242="" # No translation available +#bedwars.4243="" # No translation available +#bedwars.4244="" # No translation available +#bedwars.4245="" # No translation available +#bedwars.4246="" # No translation available +#bedwars.4247="" # No translation available +#bedwars.4248="" # No translation available +#bedwars.4249="" # No translation available +#bedwars.4250="" # No translation available +#bedwars.4251="" # No translation available +#bedwars.4252="" # No translation available +#bedwars.4253="" # No translation available +#bedwars.4254="" # No translation available +#bedwars.4255="" # No translation available +#bedwars.4256="" # No translation available +#bedwars.4257="" # No translation available +#bedwars.4258="" # No translation available +#bedwars.4259="" # No translation available +#bedwars.4260="" # No translation available +#bedwars.4261="" # No translation available +#bedwars.4262="" # No translation available +#bedwars.4263="" # No translation available +#bedwars.4264="" # No translation available +#bedwars.4265="" # No translation available +#bedwars.4266="" # No translation available +#bedwars.4267="" # No translation available +#bedwars.4268="" # No translation available +#bedwars.4269="" # No translation available +#bedwars.4270="" # No translation available +bedwars.4271="Kristallipallo" +bedwars.4272="Ruumisarkku" +#bedwars.4273="" # No translation available diff --git a/configuration/i18n/fi_FI/official/bungee.properties b/configuration/i18n/fi_FI/official/bungee.properties new file mode 100644 index 000000000..71f7be76b --- /dev/null +++ b/configuration/i18n/fi_FI/official/bungee.properties @@ -0,0 +1,70 @@ +bungee_miscellaneous.0="Vanhentunut ohjelmisto!" +bungee_miscellaneous.1="Suoritamme huoltotoimenpiteitä, ole hyvä ja yritä uudelleen hetken kuluttua!" +bungee_miscellaneous.2="Lähettämäsi nimi oli virheellinen!" +bungee_miscellaneous.3="Sinut on jo yhdistettu tälle palvelimelle!" +bungee_miscellaneous.4="Yhteyttäsi ei voitu todentaa!" +bungee_miscellaneous.5="Kirjauduit sisään toisesta sijainnista!" +bungee_miscellaneous.6="Yhteydessäsi tapahtui virhe! Yritä kirjautua uudelleen sisään!" +bungee_miscellaneous.7="Sinut siirrettin Limboon, sillä yhdistämisesi epäonnistui: %%kickMessage%%" +bungee_miscellaneous.8="Palvelin, jolla olit, käynnistyy uudelleen! Ole hyvä ja liity uudelleen kohta!" +bungee_miscellaneous.9="Hypixel Network\n\nYhteyden muodostamisessa palvelimeen tapahtui virhe! :(\nYritä yhteyden muodostamista uudelleen. Jos ongelma jatkuu,\nota yhteyttä henkilökuntaan ja anna alla näkyvät tiedot!\n\n%%debug%%" +bungee_miscellaneous.10="Tätä komentoa suoritettaessa tapahtui virhe. Ole hyvä ja ilmoita tästä henkilökunnalle!" +bungee_miscellaneous.11="Sinulle ei ole oikeuksia suorittaa tätä komentoa!" +bungee_miscellaneous.12="Et ole kirjautunut Hypixeliin aikaisemmin, ja me olemme offline-tilassa!" +bungee_miscellaneous.13="Käyttäjänimesi on epäasiallinen. Vaihda nimesi osoitteessa minecraft.net ennen kuin yrität uudelleen.\nJos tämä on virhe, vieraile osoitteessa https://hypixel.net" +bungee_miscellaneous.14="Tämä palvelin on täynnä, ja VIP-etuoikeus on poissa päältä! Yritä myöhemmin uudelleen!" +bungee_miscellaneous.15="Tämä palvelin on täynnä! Yritä myöhemmin uudelleen!" +bungee_miscellaneous.16="Tämä palvelin on täynnä! Osta VIP osoitteessa http://store.hypixel.net voidaksesi liittyä." +bungee_miscellaneous.17="Höh, emme löydä tuota palvelinta listaltamme! Todennäköisesti vika on meidän pääsäämme. Ota yhteyttä henkilökuntaan." +bungee_miscellaneous.18="Tämä palvelin käyttää BungeeCordin versiota %%version%% henkilöltä md_5" +bungee_miscellaneous.19="Sinua ei voitu yhdistää edelliselle palvelimellesi, %%serverName%%" +bungee_miscellaneous.20="Otettiin debug-yhdistäminen käyttöön" +bungee_miscellaneous.21="Otettiin debug-yhdistäminen pois käytöstä" +bungee_miscellaneous.22="Olet tällä hetkellä Limbossa" +bungee_miscellaneous.23="Olet yhdistettynä palvelimelle %%serverName%%" +bungee_miscellaneous.24="Yhteytesi katkesi yllättäen, joten sinut siirrettin %%gameType%% -lobbyyn!" +bungee_miscellaneous.25="Yhteytesi katkesi yllättäen, joten sinut siirrettin Limboon!" +bungee_miscellaneous.26="Virhe ilmeni yhteydessäsi, joten sinut siirrettin %%gameType%% Lobbyyn!" +bungee_miscellaneous.27="Virhe ilmeni yhteydessäsi, joten sinut siirrettin limboon!" +bungee_miscellaneous.28="Sinut potkaistiin tältä palvelimelta lentämisen takia! Onko yhteytesi hidas?" +bungee_miscellaneous.29="Yhteytesi katkesi yllättäen, joten sinut siirrettin %%gameType%%-lobbyyn!" +bungee_miscellaneous.30="Potkaisu ilmeni yhteydessäsi, joten sinut siirrettin Limboon!" +bungee_miscellaneous.31="Olet jo tällä kanavalla!" +bungee_miscellaneous.32="Sinulla ei ole oikeutta liittyä henkilökunnan kanavalle!" +bungee_miscellaneous.33="Virheellinen käyttö! Oikea käyttö: /chat kanava" +bungee_miscellaneous.34="§cSinut on jo yhdistettu tälle palvelimelle" +bungee_miscellaneous.35="Sinut potkaistiin liittyessäsi palvelimelle, joten sinut uudelleenohjattiin päälobbyyn!" +bungee_miscellaneous.36="Sinun täytyy valita luokka ennen tuolle palvelimelle liittymistä!" +bungee_miscellaneous.37="Sinut potkaistiin liittyessäsi palvelimelle!" +bungee_miscellaneous.38="Ei voitu yhdistää sinua tuolle palvelimelle, joten sinut siirrettiin %%gameType%%-lobbyyn!" +bungee_miscellaneous.39="Tämä peli on jo alkanut! Ole hyvä ja yritä uudelleen!" +bungee_miscellaneous.40="Oikea syntaksi on /ochat ." +bungee_miscellaneous.41="ochat" +bungee_miscellaneous.42="SIHTEERI" +bungee_miscellaneous.43="Tämä palvelin käynnistyy pian uudelleen!" +bungee_miscellaneous.44="Yhdistä uudelleen palvelimelle mc.hypixel.net!" +bungee_miscellaneous.45="VAROITUS" +bungee_miscellaneous.46="Jokin meni vikaan lähettäessä sinua tuolle palvelimelle! Mikäli tämä tapahtuu jatkuvasti, ilmoitathan siitä ylläpidolle!" +bungee_miscellaneous.47="Sinua ei voitu yhdistää tuolle palvelimelle, joten sinut siirrettiin Limboon!" +bungee_miscellaneous.48="Sinua ei voitu yhdistää tuolle palvelimelle!" +bungee_miscellaneous.49="Pelaat tällä hetkellä palvelimella%%host%%, istunnossa %%instance%% (%%prefix%%)" +bungee_miscellaneous.50="Klikkaa laittaaksesi chattiin!" +bungee_miscellaneous.51="Klikkaa laittaaksesi palvelimen chattiin!" +bungee_miscellaneous.52="Lobby, johon yritit liittyä, on täynnä tai poissa päältä." +bungee_miscellaneous.53="Tämän vuoksi sinut ohjattiin Limboon, oman mielikuvituksesi syrjäisimpään osaan." +bungee_miscellaneous.54="Tätä paikkaa ei ole olemassakaan, voit pysyä täällä niin pitkään kuin haluat." +bungee_miscellaneous.55="Palataksesi \"todellisuuteen\", käytä komentoa /lobby PELI." +bungee_miscellaneous.56="Esimerkiksi: /lobby, /lobby skywars, /lobby arcade" +bungee_miscellaneous.57="Ole varovainen, Limbossa asuu joku." +bungee_miscellaneous.58="Olet AFK" +bungee_miscellaneous.59="Liiku palataksesi lobbyyn." +bungee_miscellaneous.60="Minecraft-versiosi (%%version%%) ei ole käytössä Hypixelissä yhteensopivuusongelmien vuoksi. Käytä versiota 1.8 tai 1.21 pelataksesi palvelimella.\n\nLisätietoa osoitteesta https://hypixel.net/versionnotice" +bungee_miscellaneous.61="Saatavilla olevat kanavat: all, party, guild, officer, skyblock-coop" +bungee_miscellaneous.62="Saatavilla olevat kanavat: all, party, guild, officer, skyblock-coop, staff" +bungee_miscellaneous.63="Virheellinen kanava! Saatavilla olevat kanavat: all, party, guild, officer, skyblock-coop" +bungee_miscellaneous.64="Virheellinen kanava! Saatavilla olevat kanavat: all, party, guild, officer, skyblock-coop, staff" +bungee_miscellaneous.65="Sinulla ei ole SkyBlock-dataa. Liity ensin SkyBlockiin osoitteessa mc.hypixel.net!" +bungee_miscellaneous.66="SkyBlock-datasi ei ole vielä siirtynyt. Liity ensin SkyBlockiin osoitteessa mc.hypixel.net!" +bungee_miscellaneous.67="SkyBlock-datasi käsittelyssä ilmeni ongelma." +bungee_miscellaneous.68="SkyBlock-datasi kloonaaminen epäonnistui: Odottamaton sisäinen virhe tapahtui." +bungee_miscellaneous.69="SkyBlock-datasi kloonaaminen epäonnistui: %%message%%" \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/challenges.properties b/configuration/i18n/fi_FI/official/challenges.properties new file mode 100644 index 000000000..7ff566ff7 --- /dev/null +++ b/configuration/i18n/fi_FI/official/challenges.properties @@ -0,0 +1,211 @@ +challenges.0="Voita yksi Build Battle -peli." +challenges.1="Tapa yksi Etsijä Farm Huntissa." +challenges.2="Tapa %%amount%% Zombia Blocking Deadissa." +challenges.3="Hanki vähintään %%amount%% pistettä Bounty Hunterissa." +challenges.4="Saavuta taso %%amount%% Creeper Attackissa." +challenges.5="Tapa pelaaja ratsastaessasi Lohikäärmeellä." +challenges.6="Aktivoi vahvistukset JÄTTIAMMUKSET ja KOLMOISLAUKAUS samanaikaisesti." +challenges.7="Tapa pelaaja lasermiekalla." +challenges.8="Tapa pelaaja, kun henkilökohtainen knockbackisi on vähintään 100." +challenges.9="Pääse finaaliin Hole in the Wallissa." +challenges.10="Saavuta vähintään %%amount%% pistettä Hypixel Says -pelissä." +challenges.11="Pääse finaaliin Pixel Paintersissa." +challenges.12="Voita vähintään %%amount%% kierrosta Party Gamesissa." +challenges.13="Tee %%amount%% maalia Footballissa." +challenges.14="Viimeistele pelaaja käyttäen nuolta Mini Wallsissa." +challenges.15="Nappaa Magical Key pelin aikana." +challenges.16="Tapa vähintään %%amount%% vihollista 4v4-pelissä." +challenges.17="Voita peli käyttämättä Ultimaattikykyäsi." +challenges.18="Käytä Blitz-tähteä." +challenges.19="Pue yllesi kokonainen rautapanssarisetti." +challenges.20="Voita peli ennen Deathmatchia." +challenges.21="Tapa pelaaja ensimmäisen minuutin sisällä." +challenges.22="Tapa %%amount%% vihollista ennen kuin Punaiset Seinät laskeutuvat." +challenges.23="Osta yksi jokaista erilaista Lucky Blockia pelin aikana." +challenges.24="Tapa %%amount%% pelaajaa jousipyssyllä yhdessä pelissä." +challenges.25="Aktivoi Super Lucky Block %%amount%% kertaa pelin aikana." +challenges.26="Tapa %%amount%% pelaajaa pistoolilla yhdessä pelissä." +challenges.27="Tapa pelaaja puukolla." +challenges.28="Tapa pelaaja kranaatilla." +challenges.29="Käytä %%amount%% tappoputkea yhdessä pelissä." +challenges.30="Tapa vähintään %%amount%% pelaajaa Nukella." +challenges.31="Saa pelin viimeinen tappo." +challenges.32="Hanki sekä pikatuli- että nopeustehovahvistus yhdessä pelissä." +challenges.33="Hanki %%amount%% eri tappoputkea yhdessä pelissä." +challenges.34="Pysäytä vihollispelaaja kesken tämän tappoputken." +challenges.35="Saa tuplatappo." +challenges.36="Tapa %%amount%% pelaajaa yhden pelin aikana lyömällä heidät tyhjyyteen." +challenges.37="Ole ensimmäinen pelaaja, joka avaa keskisaaren arkun." +challenges.38="Tapa %%amount%% pelaajaa yhdessä Ranked Mode -pelissä." +challenges.39="Kanna yhteensä %%amount%% Ender-helmeä tavaraluettelossasi." +challenges.40="Tapa kaikki viholliset vähintään kerran yhden pelin aikana." +challenges.41="Hanki Smash Crystal %%amount%% kertaa yhdessä pelissä." +challenges.42="Ole ensimmäinen pelaaja, joka aktivoi Smashin pelin aikana." +challenges.43="Voita peli kuolematta." +challenges.44="Hanki taikajuoma Speed UHC:ssa." +challenges.45="Lumoa timanttiesine Speed UHC:ssa." +challenges.46="Tapa %%amount%% pelaajaa jousipyssyllä yhdessä Speed UHC -pelissä." +challenges.47="Tapa %%amount%% pelaajaa Netherissä Speed UHC -pelin aikana." +challenges.48="Kerää ainakin %%amount%% kolikkoa yhden pelin aikana." +challenges.49="Saa osuma Sinisestä torpedosta." +challenges.50="Osu pelaajaan banaanilla." +challenges.51="Päätä peli olemalla kolmen parhaan joukossa." +challenges.52="Yritä pysytellä pelissä vähintään %%amount%% minuuttia." +challenges.53="Voita peli käyttämättä yhtään vahvistusta." +challenges.54="Jää kiinni vähintään %%amount%% eri kierroksella ja silti voita peli." +challenges.55="Osu viholliseen nuolella vähintään %%amount%% palikan päästä." +challenges.56="Älä ota yhtään vahinkoa Armonaikana." +challenges.57="Tapa vähintään %%amount%% pelaajaa ennen Deathmatchin alkua." +challenges.58="Aiheuta vähintään %%amount%% vahinkoa vihollisiin pelin aikana." +challenges.59="Tapa %%amount%% pelaajaa yhdessä pelissä käyttäen Alkuperäistä hammasta." +challenges.60="Voita peli selviytyjänä ostettuasi enintään %%amount%% kultaa." +challenges.61="Tapa vampyyri pyhällä vedellä." +challenges.62="Ole viimeinen selviytyjä pelissä." +challenges.63="Aiheuta vähintään %%amount%% vahinkoa Witheriin pelin aikana." +challenges.64="Saavuta top 3 Viimeistelijät -sijoitus pelin lopussa." +challenges.65="Voita peli, kun Witherisi ei ollut viimeinen elossa oleva Wither." +challenges.66="Pue päällesi lumottu panssarisetti." +challenges.67="Avaa salainen arkku pelin aikana." +challenges.68="Palauta vähintään %%amount%% EP tiimitovereillesi pelin aikana." +challenges.69="Saavuta Eniten vahinkoa -sijoitus pelin lopussa." +challenges.70="Valtaa lippu." +challenges.71="Hanki TDM-pelin loppuun mennessä vähintään %%amount%% kertaa enemmän tappoja kuin kuolemia." +challenges.72="Tapa %%amount%% pelaajaa peräkkäin." +challenges.73="Tapa %%amount%% pelaajaa %%time%% sisällä." +challenges.74="Tapa pelaaja." +challenges.75="Tapa %%amount%% pelaajaa." +challenges.76="Tapa toinen pelaaja ensimmäisenä koko pelin aikana." +challenges.77="Ole ensimmäinen pelaaja joka saavuttaa %%amount%% tappoa." +challenges.78="Voita peli, kun kaikki tiimitoverisi ovat vielä elossa." +challenges.79="Tapa vähintään %%amount%% pelaajaa puolustaessasi Witheriäsi." +challenges.80="Tukijoukot-haaste" +challenges.81="Raakalaishaaste" +challenges.82="Valtaushaaste" +challenges.83="Kantava voima -haaste" +challenges.84="Ender-arkkuhaaste" +challenges.85="Avaa Ender-arkku." +challenges.86="Tiimityöhaaste" +challenges.87="Taistelijahaaste" +challenges.88="Tapa 2 pelaajaa yhden pelin aikana." +challenges.89="Hirviönsurmaajahaaste" +challenges.90="Tapa 2 olentoa yhden pelin aikana." +challenges.91="MISSÄ SE ON -haaste" +challenges.92="Triplatappohaaste" +challenges.93="Ei ultimaattia -haaste" +challenges.94="Yhteistyöhaaste" +challenges.95="Tyhjyyden ruokkija -haaste" +challenges.96="Rush-haaste" +challenges.97="Ranked-haaste" +challenges.98="Enderman-haaste" +challenges.99="TNT Run -haaste" +challenges.100="Yritä pysytellä pelissä vähintään 3 minuuttia." +challenges.101="PVP Run -haaste" +challenges.102="Tapa pelaaja lyömättä tätä tyhjyyteen." +challenges.103="Bow Spleef -haaste" +challenges.104="Käytä kaikkia perkkejäsi." +challenges.105="TNT Tag -haaste" +challenges.106="Ota 5 pelaajaa kiinni." +challenges.107="Wither-haaste" +challenges.108="Suojelijahaaste" +challenges.109="Saa ainakin 10 tappoa/avustusta puolustaessasi Witheriäsi." +challenges.110="Berserkkihaaste" +challenges.111="Vastaiskuhaaste" +challenges.112="Raivohaaste" +challenges.113="Kokeiluhaaste" +challenges.114="Jousiampujahaaste" +challenges.115="Todella onnekas -haaste" +challenges.116="Build Battle -haaste" +challenges.117="Farm Hunt -haaste" +challenges.118="Blocking Dead -haaste" +challenges.119="Bounty Hunter -haaste" +challenges.120="Creeper Attack -haaste" +challenges.121="Dragon Wars -haaste" +challenges.122="Ender Spleef -haaste" +challenges.123="Galaxy Wars -haaste" +challenges.124="Throw Out -haaste" +challenges.125="Hole in the Wall -haaste" +challenges.126="Hypixel Says -haaste" +challenges.127="Pixel Painters -haaste" +challenges.128="Party Games -haaste" +challenges.129="Football -haaste" +challenges.130="Mini Walls -haaste" +challenges.131="Pistoolihaaste" +challenges.132="Puukkohaaste" +challenges.133="Kranaattihaaste" +challenges.134="Tappoputkihaaste" +challenges.135="Hammashaaste" +challenges.136="Kultahaaste" +challenges.137="Puhdistushaaste" +challenges.138="Viimeinen elossa -haaste" +challenges.139="Osuma kaukaa -haaste" +challenges.140="Täydellinen tähti -haaste" +challenges.141="Metsästäjähaaste" +challenges.142="Uhkahaaste" +challenges.143="Tappoputkihaaste" +challenges.144="Nuke-haaste" +challenges.145="Viimeistelyhaaste" +challenges.146="Kolikkohaaste" +challenges.147="Ensimmäinen sija -haaste" +challenges.148="Banaanihaaste" +challenges.149="Tulostaulukkohaaste" +challenges.150="Alkemistihaaste" +challenges.151="Velhohaaste" +challenges.152="Tarkka-ampujahaaste" +challenges.153="Nether-haaste" +challenges.154="Kristallihaaste" +challenges.155="Smash-haaste" +challenges.156="Virheetön-haaste" +challenges.157="Tähtihaaste" +challenges.158="Iron Man -haaste" +challenges.159="Blitz-haaste" +challenges.160="Vastarintahaaste" +challenges.161="Puolustus" +challenges.162="Puolusta sänkyäsi viittä hyökkääjää vastaan yhden pelin aikana." +challenges.163="Tukijoukot" +challenges.164="Kerää 10 timanttia yhden pelin aikana." +challenges.165="Hyökkäys" +challenges.166="Tuhoa 2 sänkyä yhden pelin aikana." +challenges.167="Vahvistushaaste" +challenges.168="Tappoputkihaaste" +challenges.169="Älä räpäytä silmiäsi -haaste" +challenges.170="Kombohaaste" +challenges.171="Ensiverihaaste" +challenges.172="Voimanpesähaaste" +challenges.173="Keräilijähaaste" +challenges.174="Tuplatappohaaste" +challenges.175="Puolusta sänkyäsi %%amount%% hyökkääjää vastaan yhden pelin aikana." +challenges.176="Kerää %%amount%% timanttia yhden pelin aikana." +challenges.177="Tuhoa %%amount%% sänkyä yhden pelin aikana." +challenges.178="Saa ainakin %%amount%% tappoa/avustusta puolustaessasi Witheriäsi." +challenges.179="Murhanhimo" +challenges.180="Sherlock" +challenges.181="Sankari" +challenges.182="Tapa %%amount%% pelaajaa murhaajana yhden pelin aikana." +challenges.183="Tapa murhaaja alle kahdessa minuutissa ollessasi etsivä." +challenges.184="Ryhdy sankariksi tappamalla murhaaja ollessasi viaton." +challenges.185="Sarjamurhaaja" +challenges.186="Ryhdy sankariksi tappamalla murhaaja ollessasi joko viaton tai etsivä." +challenges.187="Kerää %%amount%% timanttia genraattoreilta yhdessä pelissä." +challenges.188="Tyhjyyden ruokkija -haaste" +challenges.189="Osu 20 kertaa jousella." +challenges.190="Tapa 2 pelaajaa." +challenges.191="Tapa pelaaja lyömällä tämä tyhjyyteen." +challenges.192="Ampumaharjoitushaaste" +challenges.193="Tiimihaaste" +challenges.194="TNT Wizards -haaste" +challenges.195="Valtaa 4 pistettä yhdessä pelissä." +challenges.196="Zombies-haaste" +challenges.197="Tapa %%amount%% vihollista Zombiesissa." +challenges.198="Hide and Seek -haaste" +challenges.199="Voita Party pooper -peli etsijänä tappaen vähintään yhden pelaajan ja lyömättä NPC-hahmoa." +challenges.200="Tapa %%amount%% pelaajaa yhdessä pelissä." +challenges.201="Tapa %%amount%% olentoa yhdessä pelissä." +challenges.202="Capture the Wool -haaste" +challenges.203="Tapa vastustaja tiputtamalla tämä ongen avulla tyhjyyteen." +challenges.204="Rakentajahaaste" +challenges.205="Aseta %%amount%% palikkaa yhden kierroksen aikana." +challenges.206="Armoton tappaja -haaste" +challenges.207="Tapa %%amount%% pelaajaa yhdellä kierroksella." +challenges.208="Voita %%amount%% kierrosta peräkkäin." +challenges.209="Pixel Party -haaste" +challenges.210="Saavuta kierros 20 Pixel Partyssa" \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/chat_filter.properties b/configuration/i18n/fi_FI/official/chat_filter.properties new file mode 100644 index 000000000..b27a2a586 --- /dev/null +++ b/configuration/i18n/fi_FI/official/chat_filter.properties @@ -0,0 +1,6 @@ +chat_filter.speed_limit="Voit käyttää chattia vain %%expiry%% sekunnin välein! Pelaajat, joilla on ostettu rank, ohittavat tämän rajoituksen!" +chat_filter.discord_username="Viestisi estettiin, koska vaikutit olevan jakamassa Discord-käyttäjänimeäsi. Kokeile lisätä se someihisi käyttämällä komentoa /profile" +chat_filter.disallowed="Tämä viesti ei ole sallittu!" +chat_filter.hatred="Estimme viestisi \"%%in%%\", sillä se rikkoi sääntöjämme sisältämällä väkivallan tai vihan lietsomista muita pelaajia kohtaan. https://www.hypixel.net/rules/" +chat_filter.adult_theme="Estimme viestisi \"%%in%%\", sillä se rikkoi sääntöjämme sisältämällä sopimatonta ja aikuisille suunnattua sisältöä. https://www.hypixel.net/rules/" +chat_filter.advertising="Mainostaminen on sääntöjen vastaista. Saat rangaistuksen palvelimella, mikäli yrität mainostaa." \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/collectibles.properties b/configuration/i18n/fi_FI/official/collectibles.properties new file mode 100644 index 000000000..dad30f05f --- /dev/null +++ b/configuration/i18n/fi_FI/official/collectibles.properties @@ -0,0 +1,2286 @@ +collectibles.0="Suosikkikeräilyesineet" +collectibles.1="Keräilyesineiden asettaminen suosikeiksi tekee niiden käyttöönottamisesta helpompaa. Aseta suosikkeja oikeaklikkaamalla keräilyesinettä valikossa!" +collectibles.2="Nollaa suosikit" +collectibles.3="Nollaa suosikit napsauttamalla tätä." +collectibles.4="Keräilyesineet" +collectibles.5="Haku" +collectibles.6="Tämä ominaisuus on tällä hetkellä poistettu käytöstä tässä aulassa, pitäisi palata pian!" +collectibles.7="Avattu:" +collectibles.8="Poistettiin %%type%% suosikeistasi." +collectibles.9="Nollaa suosikkisi." +collectibles.10="Olet ylittänyt suosikkikeräilyesineiden enimmäisrajan. Oikeaklikkaa esinettä poistaaksesi sen suosikeista ja tehdäksesi tilaa muille esineille." +collectibles.11="Lisättiin %%type%% suosikkeihisi. Voit nyt valita sen suoraan tavaraluettelostasi!" +collectibles.12="Et voi asettaa suosikiksi esinettä, jota et omista" +collectibles.13="Keräilyesineet" +collectibles.14="Keräilyesineet (Oikeaklikkaa)" +collectibles.15="Sinun on odotettava vielä %%seconds%%s ennen kuin voit käyttää tätä!" +collectibles.16="Muodonmuutos nollattu" +collectibles.17="Pahoittelut, tämä tuote ei ole tällä hetkellä käytettävissä - palaa takaisin tulevaisuudessa saadaksesi tietää kuinka sen voi avata!" +collectibles.18="Tämän esineen voi avata vain osoitteesta store.hypixel.net!" +collectibles.19="Sinun on oltava %%rank%% tai korkeampi käyttääksesi tätä! Osta rankkeja osoitteessa https://store.hypixel.net" +collectibles.20="Tämä esine avautuu vain lähettämällä %%gifts%% giftiä! Tarkastellaksesi gifting-palkintoja, avaa Mystery Gift -tavaraluettelosi Mysteeriholvilla." +collectibles.21="%%color%%Avataan saavuttamalla\n%%number%% annetun lahjan palkinto%%color%%!" +collectibles.22="Tämän esineen voi saada vain SkyWars Ranked -palkintona." +collectibles.23="SkyWars Ranked -palkinto" +collectibles.24="Puhu Lähettimiehelle nähdäksesi kuinka voit avata tämän palkinnon." +collectibles.25="Löytyy Palkintokorteista!" +collectibles.26="Tämän esineen voi saada vain saavuttamalla Hypixel-level %%level%%!" +collectibles.27="Hypixel-level %%level%%%%color%% -palkinto!" +collectibles.28="%%color%%Avautuu saavuttamalla\nHypixel-level %%level%%%%color%%!" +collectibles.29="Klikkaa lunastaaksesi\nHypixel-leveling -valikossa" +collectibles.30="Tämä esine ei ole vielä saatavilla!" +collectibles.31="Avataan osoitteessa http://store.hypixel.net/!" +collectibles.32="Sinun täytyy olla %%rank%%!" +collectibles.33="Ei tarpeeksi Hypixel Creditejä!" +collectibles.34="Työstit esineen %%name%%" +collectibles.35="Muutu olennoksi %%cleanName%% 5 minuutin ajaksi. Muuntautuneena voit %%description%% oikeaklikkaamalla Limapalloa tavaraluettelossasi." +collectibles.36="vikistä" +collectibles.37="ammua" +collectibles.38="teleportata satunnaiseen sijaintiin" +collectibles.39="munia" +collectibles.40="ampua verkkoa ympärillesi" +collectibles.41="aktivoida sateenkaarilammastilan" +collectibles.42="räjäyttää lähistöllä olevat pelaajat kauemmaksi" +collectibles.43="ampua tulipalloja" +collectibles.44="tartuttaa muut pelaajat ja tehdä heistä zombeja" +collectibles.45="laukaista muut pelaajat ilmaan" +collectibles.46="heittää erityisiä taikajuomia" +collectibles.47="heittää lumipalloja" +collectibles.48="heittää hiiltä" +collectibles.49="ampua lasereita" +collectibles.50="Sikamuodonmuutos" +collectibles.51="Lehmämuodonmuutos" +collectibles.52="Enderman-muodonmuutos" +collectibles.53="Kanamuodonmuutos" +collectibles.54="Hämähäkkimuodonmuutos" +collectibles.55="Lammasmuodonmuutos" +collectibles.56="Creeper-muodonmuutos" +collectibles.57="Roihumuodonmuutos" +collectibles.58="Zombimuodonmuutos" +collectibles.59="Rautagolem-muodonmuutos" +collectibles.60="Noitamuodonmuutos" +collectibles.61="Luurankomuodonmuutos" +collectibles.62="Lumiukkomuodonmuutos" +collectibles.63="Grinch-muodonmuutos" +collectibles.64="Vartijamuodonmuutos" +collectibles.65="Et voi käyttää tätä muodonmuutosta vielä! Ole hyvä ja odota %%seconds%%" +collectibles.66="Aktivoi muodonmuutoskyky (Oikeaklikkaa)" +collectibles.67="Olet aktivoinut muodonmuutoksen %%name%% 5 minuutin ajaksi." +collectibles.68="Olet aktivoinut muodonmuutoksen %%name%% 5 minuutin ajaksi." +collectibles.69="Oikeaklikkaa Limapallolla aktivoidaksesi muodonmuutoskykysi!" +collectibles.70="Muodonmuutoksesi päättyi!" +collectibles.71="Odottamaton virhe tapahtui! Ilmoita tästä foorumeilla." +collectibles.72="Älä klikkaa liian nopeasti!" +collectibles.73="Nollaa muodonmuutos" +collectibles.74="Muodonmuutos nollattu." +collectibles.75="Sinulla ei ole muodonmuutosta käytössä juuri nyt!" +collectibles.76="Mahdollista määränpäätä ei löytynyt." +collectibles.77="Sinun tulee olla pelaajien lähettyvillä käyttääksesi tätä kykyä!" +collectibles.78="Sinun tulee katsoa palikkaa käyttääksesi tätä." +collectibles.79="Kunniaa!" +collectibles.80="Olen mahtavin!" +collectibles.81="Eeppinen voitto!" +collectibles.82="Voittoposeeraus" +collectibles.83="Näkemiin" +collectibles.84="Hei hei!" +collectibles.85="Hyvästi" +collectibles.86="Hypi ympäriinsä" +collectibles.87="Hype-tanssi" +collectibles.88="Aaltotanssi" +collectibles.89="Heitä vitonen!" +collectibles.90="Ylävitonen" +collectibles.91="Iloitsetko voittoasi? Ylävitonen-eleellä voit näyttää, kuinka paljon arvostat kilpakumppaneitasi!" +collectibles.92="Katso kun teen piruetin!" +collectibles.93="Balettitanssi" +collectibles.94="Haluatko tanssia tyylillä? Näytä parhaat liikkeesi Balettitanssieleellä!" +collectibles.95="Pää... RÄJÄHTÄÄ!" +collectibles.96="Et vain voi uskoa! Tämä ele saa pääsi räjähtämään... kirjaimellisesti!" +collectibles.97="Korkkarit kattoon!" +collectibles.98="Can-can-tanssi" +collectibles.99="Tanssi kuin ammattilainen tällä Can-can-tanssieleellä! Uskoisitko jaksavasi tanssia pidempään kuin 10 minuuttia?" +collectibles.100="Karaoke" +collectibles.101="Näytä kavereillesi mistä sinut on tehty laulamalla tämän Karaoke-eleen tahtiin!" +collectibles.102="Aloha!" +collectibles.103="Hulatanssi" +collectibles.104="Heiluta lantiotasi kuin Havaijilla tällä Hulatanssieleellä!" +collectibles.105="Nyt juhlitaan!" +collectibles.106="Valmistujaiset" +collectibles.107="Jeee!!! Koulu on ohi ja olet juuri valmistunut! Jaa onnesi ystäviesi kanssa tällä Valmistujaiseleellä!" +collectibles.108="Woop woop woop!" +collectibles.109="Raputanssi" +collectibles.110="Ylistäkää aurinkoa!" +collectibles.111="Aurinkotervehdys" +collectibles.112="Kaiva aarretta" +collectibles.113="Poistettiin eleesi." +collectibles.114="Sinun tulee olla maassa käyttääksesi tätä!" +collectibles.115="Tätä ei voi löytää tai työstää vielä!" +collectibles.116="%%color%%Klikkaa työstääksesi %%dust%% %%color%%mysteeripölyllä!" +collectibles.117="Tarvitset vielä %%dust%% pölyä lisää!" +collectibles.118="Tätä ei voi työstää pölyllä!" +collectibles.119="Hinta: %%credits%% Hypixel Creditiä" +collectibles.120="Oikeaklikkaa lisätäksesi suosikkeihisi!" +collectibles.121="Oikeaklikkaa poistaaksesi suosikeistasi!" +collectibles.122="Partikkelipaketti nollattu" +collectibles.123="Partikkelipaketit" +collectibles.124="Nollaa partikkelipakettisi" +collectibles.125="Et voi käyttää tätä naamioituneena." +collectibles.126="Riisuimme hattusi, sillä muutoin se menisi päällekkäin asusi hatun kanssa." +collectibles.127="%%name%% nollattu" +collectibles.128="Valitsit: %%name%%" +collectibles.129="Sinun tulee käyttää Minecraftin versiota 1.8 käyttääksesi tämän puvun kykyä." +collectibles.130="Täyden asun kyky:" +collectibles.131="Nollaa asu" +collectibles.132="Asut" +collectibles.133="Asuja ei voi käyttää tässä lobbyssa resurssipaketin vuoksi." +collectibles.134="Kerää ja käytä tietyn asun kaikkia osia lobbyssa saadaksesi erityisiä ominaisuuksia!" +collectibles.135="Ime lämpöä itseesi ja viilennä maailmaa kävelemällä ympäriinsä." +collectibles.136="Jääkävelijän puku" +collectibles.137="Mikä on parempaa kuin keksi? Mies, joka voi leipoa miljoona keksiä!" +collectibles.138="Klikkaa antaaksesi keksejä kaikille lobbyssa." +collectibles.139="Leipuripuku" +collectibles.140="Tiedätkö mikä on hauskempaa kuin rakentaminen? RAKENNUSTEN RÄJÄYTTELY!" +collectibles.141="Klikkaa heittääksesi pommin!" +collectibles.142="TNT-puku" +collectibles.143="%%color%%%%seconds%% sekuntia räjähdykseen!" +collectibles.144="Emme ole aivan varmoja, mikä tässä asussa surisee." +collectibles.145="Tämä asu soittaa klassista musiikkia lentäessäsi (vaatii VIP) tai vasenklikatessasi!" +collectibles.146="Kimalaispuku" +collectibles.147="Älä räpäytä silmiäsi - ei kertaakaan, ei sekunniksikaan... mitä tahansa teetkin - älä räpäytä silmiäsi!" +collectibles.148="Klikkaa pelaajaa jahdataksesi tätä ympäri lobbya." +collectibles.149="Kuoleman enkelin puku" +collectibles.150="Se oli isäsi suosikkitanssiliike - tuokaa takaisin vanha kunnon boogie tällä Diskopuvulla!" +collectibles.151="Vaihtaa väriä käyttäessäsi!" +collectibles.152="Diskopuku" +collectibles.153="Jo sukupolvien ajan Lohikäärmeen henkäys -puku on suojannut ihmisiä ikivanhoilla taioillaan." +collectibles.154="Klikkaa syöstäksesi tulta vihollisiasi päin!" +collectibles.155="Lohikäärmeen henkäys -puku" +collectibles.156="Vihdoinkin asu joka toimii kuin kello... koska se on kello!" +collectibles.157="Klikkaa soittaaksesi rumpuja!" +collectibles.158="Lelusotilaspuku" +collectibles.159="Tämä Palomiehen puku päällä sinusta tulee kaikkien tavallisten ihmisten sankari!" +collectibles.160="Klikkaa ruiskiaksesi vettä." +collectibles.161="Palomiehen puku" +collectibles.162="Mikään ei liiku nopeammin kuin valo... paitsi sinä käyttäessäsi Vauhtiveikon asua!" +collectibles.163="Sprinttaa juostaksesi älyttömän nopeasti." +collectibles.164="Vauhtiveikon asu" +collectibles.165="Yksi harvinaisimmista asuista. Selaa parhaimpia meemejä käyttäessäsi tätä Sammakkopukua." +collectibles.166="Superkorkea hyppy." +collectibles.167="Sammakkopuku" +collectibles.168="Tunnetko olevasi pelottava? Ota siis käyttöön tämä karmivan kauhea Aavemainen luurankopuku" +collectibles.169="Tekee käyttäjästään näkymättömän!" +collectibles.170="Aavemainen luurankopuku" +collectibles.171="Et voi käyttää tätä naamioituneena." +collectibles.172="YLLÄTYS! Palkintona anteliaisuudestasi voit nyt käyttää Yllätyslahjapukua!" +collectibles.173="Klikkaa naamioituaksesi lahjaksi, jonka muut pelaajat voivat avata." +collectibles.174="Yllätyslahjapuku" +collectibles.175="Antaa käyttäjänsä heitellä hiiliä varastaessaan joulua." +collectibles.176="Grinch-asu" +collectibles.177="Aalloissa siis, aalloissa siis! Suuntaa meren alle tällä Merenneitopuvulla." +collectibles.178="Muutu kauniiksi kalmariksi ollessasi veden alla." +collectibles.179="Merenneitopuku" +collectibles.180="Biletä hautausmaalla ja tuo kuolleet takaisin elävien kirjoihin tällä Nekromantikon puvulla!" +collectibles.181="Klikkaa nostaaksesi kuolleita henkiin." +collectibles.182="Nekromantikon puku" +collectibles.183="Kiertele suosikkilobbyssasi hiljaisesti tappaen tällä Ninjapuvulla." +collectibles.184="Klikkaa heittääksesi heittotähden!" +collectibles.185="Ninjapuku" +collectibles.186="ARRR! Purjehdi etsien aarretta, joka saa niin maakravut kuin kokeneimmat merikarhutkin kalpenemaan kateudesta, tällä Merirosvopuvulla!" +collectibles.187="Klikkaa purjehtiaksesi ympäriinsä veneellä." +collectibles.188="Merirosvopuku" +collectibles.189="Anteeksi, prinsessasi on toisessa lobbyssa!" +collectibles.190="Klikkaa heittääksesi tulipalloja." +collectibles.191="Putkimiehen puku" +collectibles.192="HOU HOU HOU! Kuka onkaan ollut kiltti, kuka tuhma? Sen saat selville tällä vanhalla ja iloisella Joulupukin puvulla." +collectibles.193="Klikkaa toimittaaksesi lahjoja!" +collectibles.194="Joulupukin puku" +collectibles.195="Vanha jalkapallosi korvattiin uudella!" +collectibles.196="Jalkapallo luotu! Jos kadotat sen, vasenklikkaa luodaksesi uuden." +collectibles.197="Unohda Ronaldo, unohda Messi, paras pelaaja maan päällä olet sinä käyttäessäsi tätä Jalkapallopelaajan asua!" +collectibles.198="Klikkaa luodaksesi jalkapallon, jota voit potkia ympäriinsä!" +collectibles.199="Jalkapallopelaajan asu" +collectibles.200="TÄYSIN LADATTU" +collectibles.201="O-ou! Aurinkovoimapuvustasi loppui akku. Vasenklikkaa ladataksesi sen." +collectibles.202="Kerää auringon luonnollista energiaa ladataksesi tämän Aurinkovoimapuvun!" +collectibles.203="Puvun akku kuluu liikkuessasi. Klikkaa ladataksesi!" +collectibles.204="Aurinkovoimapuku" +collectibles.205="Isol voimal on iso vastuu, tai jotain. Pelasta päivä tällä Spooderman-puvulla." +collectibles.206="Klikkaa keinuaksesi ympäri lobbyja!" +collectibles.207="Spooderman-puku" +collectibles.208="Tämä palikka on liian kaukana, tai ei kelpaa!" +collectibles.209="\"Pidän tästä puvusta. SEURAAVA!\" Ota haltuusi ukkosen jumalan voimat tällä Thor-puvulla." +collectibles.210="Klikkaa iskeäsi salamoita." +collectibles.211="Thor-puku" +collectibles.212="Kultamalmia löydetty. Oikeaklikkaa kerätäksesi!" +collectibles.213="Keräsit %%count%% kultakimpaletta" +collectibles.214="Arkeologia on faktojen ei totuuden etsimistä. Tutki hautoja, kryptoja ja raunioita tällä Aarteenmetsästäjän puvulla!" +collectibles.215="Tutki lobbyja kerätäksesi muinaisia kulta-aarteita." +collectibles.216="Aarteenmetsästäjän puku" +collectibles.217="Tällä Vampyyripuvulla voit vihdoin olla kuin itse verenhimoinen Tuonelan lepakko!" +collectibles.218="Muutu lepakoksi lentäessäsi." +collectibles.219="Sinun tulee olla maassa käyttääksesi Soturin puvun kykyjä." +collectibles.220="Soturin tie on kunniakas, raskas ja täynnä mahtavia erikoiskykyjä!" +collectibles.221="Vasenklikkaa ja katso alas tehdäksesi Tannertäräyksen tai katso eteenpäin tehdäksesi Seismisen aallon." +collectibles.222="Soturipuku" +collectibles.223="Käyttäessäsi tätä alueella, jolla on vähemmän pelaajia, saat enemmän susia!" +collectibles.224="Ei tarpeeksi tilaa ympärillä tämän käyttämiseksi!" +collectibles.225="Klikkaa kutsuaksesi susilaumasi!" +collectibles.226="Susiprinsessapuku" +collectibles.227="Osto peruttu!" +collectibles.228="Hakutulokset:" +collectibles.229="Viirit" +collectibles.230="Avaa kaikki viirit ja käytä niitä hattuina lobbyissa. Niitä voi käyttää myös housing-esineinä!" +collectibles.231="Nollaa hattu" +collectibles.232="Tapahtui virhe, pyydämme sinua ottamaan yhteyttä ylläpitoon (applyHat returned false)." +collectibles.233="Poistimme asusi kypärän, sillä se menisi päällekkäin hattusi kanssa." +collectibles.234="Poistimme emotesi, sillä se menisi päällekkäin hattusi kanssa." +collectibles.235="Klikkaat liian nopeasti." +collectibles.236="Tavalliset hatut" +collectibles.237="Aivan tavalliset hatut." +collectibles.238="Animoidut hatut" +collectibles.239="Kerää kaikki hatut ja käytä niitä lobbyssa. Jotkin hatut ovat poissa käytöstä tietyissä lobbyissa." +collectibles.240="Tämän vempaimen voi\nsaada ainoastaan\nkampanjatarjouksena\nMCProHostingilta! Kirjoita\n/mcph saadaksesi lisätietoa." +collectibles.241="%%name%% (Oikeaklikkaa)" +collectibles.242="Tämän vempaimen voi saada ainoastaan kampanjatarjouksena MCProHostingilta! Kirjoita% %yellow%%/mcph %%red%%saadaksesi lisätietoa." +collectibles.243="Sinulla on jo %%name%% valittuna!" +collectibles.244="Hauskat pelit" +collectibles.245="Pelaa pelejä tai ihan vain pelleile lobbyissa näillä hauskoilla vempaimilla!" +collectibles.246="Hirviöt ja otukset" +collectibles.247="Hirviöt ja otukset -vempaimilla voit luoda siistejä olentoja, joiden kanssa leikkiä!" +collectibles.248="Liikkuminen" +collectibles.249="Muuta sitä miten kävelet, juokset tai lennät ympäri lobbyja näillä liikkumista muokkaavilla vempaimilla!" +collectibles.250="Musiikki" +collectibles.251="Pidä ääntä näillä musikaalisilla vempaimilla!" +collectibles.252="Ammukset" +collectibles.253="Tulta! Ammuskele ympäri lobbya näillä hauskoilla asevempaimilla!" +collectibles.254="Ulkonäkö" +collectibles.255="Muuta itsesi tai lobbyn ulkonäköä näillä vempaimilla!" +collectibles.256="Ranked-palkinnot" +collectibles.257="Kosmeettisia palkintoja kaikkein kilpailunhaluisimmille pelaajillemme Ranked-peleissä." +collectibles.258="Hyviä uutisia! Tilastotarkkailijavempaimesi on nyt saatavilla kaikissa lobbyissa! Et enää tarvitse esinettä, voit vain käyttää komentoa /stats!" +collectibles.259="Kukkasi poistettiin." +collectibles.260="Vempaimet on tällä hetkellä poistettu käytöstä!" +collectibles.261="Vempaimet on tällä hetkellä poistettu käytöstä, pahoittelut!" +collectibles.262="Tämä vempain on väliaikaisesti poissa käytöstä!" +collectibles.263="Tämä vempain on tällä hetkellä poissa käytöstä!" +collectibles.264="Vempaimet on tällä hetkellä poistettu käytöstä tässä lobbyssa!" +collectibles.265="Et voi aktivoida vempaimia tällä alueella!" +collectibles.266="Sinun on odotettava vielä %%time%%s ennen kuin voit käyttää tätä!" +collectibles.267="Nollaa vempain" +collectibles.268="Oletko koskaan halunnut saada kaverisi kadehtimaan upeaa trampoliiniasi tai haluatko vain heitellä kakkapommeja kaikkia päin? Vempaimet ovat siis kuin juuri sinua varten! Näitä hauskoja pikku leluja voit käyttää lobbyissa." +collectibles.269="Odota käyttääksesi tätä uudelleen!" +collectibles.270="Tämä on kokeellinen toiminto, käytä omalla vastuullasi." +collectibles.271="Kun mennään niin ei meinata, eikä tarvita teitä... mutta tilaa tämän vempaimen aktivoiminen kyllä vaatii! Matkusta takaisin tulevaisuuteen tällä hullun siistillä Aikakoneautovempaimella." +collectibles.272="Hei, Doc, paras peruuttaa. Lobby ei riitä kiihdyttämiseen." +collectibles.273="Lobby? Siellä minne me menemme ei tarvita lobbyja." +collectibles.274="Vapauta lepakkoparvi käskystäsi!" +collectibles.275="Noniin, olet ansainnut sen! Järjestä kunnon grillijuhlat!" +collectibles.276="Luo sekalaisenvärisen pylvään." +collectibles.277="Asettaa maahan karkkitangon. Koska kukapa ei pitäisi karkista?!" +collectibles.278="Hyökkää vihollistesi kimppuun heidän pahimmalla pelollaan, kissoilla! Ampuu 4-6 räjähtävää kissaa tähtäyssuuntaasi." +collectibles.279="Testikanuuna, jossa ammuksina on kanoja. Mikä voisikaan mennä pieleen?" +collectibles.280="Tässä lobbyssa on jo joulukuoro. Yritä myöhemmin uudelleen." +collectibles.281="Kulkuset, kulkuset!" +collectibles.282="Tässä lobbyssa on jo enimmäismäärä joulukuusia. Odota hetki." +collectibles.283="Olet jo aktivoinut joulukuusen." +collectibles.284="Hei, mennään katsomaan millaisia lahjoja kuusen alta löytyy!" +collectibles.285="Lähistöllä ei ole ratsastettavia pelaajia!" +collectibles.286="Antaa sinun ratsastaa lähimmällä pelaajalla. Luo torneja ratsastamalla lemmikeillä ja muilla pelaajilla!" +collectibles.287="Luo kissakavereita, jotka seuraavat sinua kaikkialle!" +collectibles.288="Sinun tulee katsoa palikkaa käyttääksesi tätä!" +collectibles.289="Ammu ilmaan creeper, ja jos se pääsee ylös asti, nauti upeasta esityksestä!" +collectibles.290="Syväjäädyttää sinut. Oiva tapa selviytyä yllättävästä maailmanlopusta." +collectibles.291="Heitit numeron %%result%%!" +collectibles.292="Älä huoli, tämä noppa ei huku vaikka se putoaisi sohvan alle!" +collectibles.293="Noppasi putosi tyhjyyteen. Aika etsiä uusi!" +collectibles.294="Luo diskopallon, josta ei puutu siistejä efektejä ja hyvää musiikkia." +collectibles.295="Tykinkuula!" +collectibles.296="Mahaplätsi!" +collectibles.297="Pää edellä!" +collectibles.298="Takaperinvoltti!" +collectibles.299="Voltti!" +collectibles.300="Edellinen koppisi on edelleen täällä, et voi asettaa kahta samaan aikaan!" +collectibles.301="Tapahtui virhe, pyydämme sinua ottamaan yhteyttä ylläpitoon. (s%%number%% == null)" +collectibles.302="Jos ikinä tahdoitkaan olla DJ, nyt on se hetki! Lumoa ystäväsi tällä DJ-setillä ja tanssilattialla." +collectibles.303="Suoraan Farm Huntista, ainoa ja oikea Räjähtävä lammas on täällä taas räjähtävämpänä kuin koskaan." +collectibles.304="Teleporttitikut ovat luusereille. Kaikki kovat tyypit käyttävät Räjähdejousia." +collectibles.305="Aloittaa ilotulituksen, joka kirjoittaa taivaalle kirjaimet MCPH!" +collectibles.306="Oikeaklikkaa pelaajaa antaaksesi tälle kukan!" +collectibles.307="Olet saavuttanut kutsujen enimmäisrajoituksen, odota hetki ennen kuin lähetät seuraavan!" +collectibles.308="Et voi kutsua tätä pelaajaa." +collectibles.309="Yrität jo lähettää kukkaa pelaajalle %%player%%." +collectibles.310="Lähetit kukan pelaajalle %%player%%!" +collectibles.311="%%player%% antoi sinulle kukan!" +collectibles.312="[HYVÄKSY]" +collectibles.313="[HYLKÄÄ]" +collectibles.314="Klikkaa hyväksyäksesi kukan." +collectibles.315="Klikkaa hylätäksesi kukan." +collectibles.316="Kutsusi pelaajalle %%player%% vanhentui." +collectibles.317="Kutsu pelaajalta %%player%% vanhentui." +collectibles.318="Levitä iloa ja onnea antamalla kukkia kaikille ympärilläsi!" +collectibles.319="Sinulla ei ole odottavia kutsuja." +collectibles.320="Hylättiin pelaajan %%player%% kutsu." +collectibles.321="Sinulla ei ole odottavaa kutsua tältä pelaajalta." +collectibles.322="Tämä pelaaja poistui jo lobbysta." +collectibles.323="Oikeaklikkaa poistaaksesi kukkasi!" +collectibles.324="%%player%% hyväksyi kukkasi!" +collectibles.325="Väärä käyttötapa." +collectibles.326="Vahvat johtajat eivät polje heikompiaan. He nostavat nämä ilmaan ja iskevät maahan tehdäkseen mahdollisimman paljon vahinkoa." +collectibles.327="Pidä säännöllisesti taukoa pelaamisesta - se on hyväksi terveydellesi!" +collectibles.328="Siisti makuuhuone on merkki rikkinäisestä tietokoneesta." +collectibles.329="Mieli on kuin laskuvarjo - se ei toimi, jos se ei ole avoin." +collectibles.330="34% internetistä löytyvistä tilastoista on täysin tekaistuja!" +collectibles.331="Jos et onnistu ensimmäisellä yrityksellä, ei laskuvarjohyppy ehkä ole sinun lajisi!" +collectibles.332="Tekoälystä ei ole vastusta luonnolliselle tyhmyydelle." +collectibles.333="Kun elämä antaa sitruunoita, tee niistä mehua. Kun elämä antaa limejä, heitä ne ikkunasta ja osta itsellesi sitruunamehua!" +collectibles.334="Saatat olla päättämätön, tai sitten et, päätä itse." +collectibles.335="Huomenna käänny vasempaan. Sitten oikeaan. Sitten taas vasempaan. Olet saapunut määränpäähäsi." +collectibles.336="Jos luulet, ettei kukaan huomioi sinua, yritäpä olla maksamatta laskujasi!" +collectibles.337="Rakkaus on sitä, kun käsket toista suksimaan kuuseen ja murehdit sitten pääsikö tämä perille turvallisesti." +collectibles.338="Jos et halua, että sinua pyydetään tekemään jotain uudestaan, epäonnistu ensimmäisellä kerralla tarkoituksella!" +collectibles.339="Tulipalon sattuessa, poistu rakennuksesta ENNEN kuin kerrot siitä netissä!" +collectibles.340="Tasapainoinen ruokavalio ei tarkoita sitä, että pidät kakkua molemmissa käsissäsi!" +collectibles.341="Raha puhuu; yleensä se sanoo näkemiin." +collectibles.342="Olet hyvä pitämään salaisuuksia - vain ihmiset joille niitä kerrot eivät ole!" +collectibles.343="Voitat sen SkyWars-pelin. Yritä vain kunnes onnistut!" +collectibles.344="Silloin tällöin on vain parasta olla sanomatta mitään." +collectibles.345="Jos sinun ei kuuluisi syödä yöllä, miksi jääkaapissa sitten on valot?" +collectibles.346="Apua! Minua pidetään vankina Hypixelin onnenkeksitehtaalla! Lähettäkää apua!" +collectibles.347="Mikään ei pilaa hyvää perjantaita niin kuin se, kun tajuat että on oikeasti tiistai." +collectibles.348="Paranna muistiasi tekemällä unohtumattomia asioita." +collectibles.349="Myy miehelle kala, hän syö yhden päivän. Opeta mies kalastamaan, menetät asiakkaan!" +collectibles.350="Kuuntele vain keksien neuvoja - älä usko muihin ennustaviin elintarvikkeisiin!" +collectibles.351="Yritit parhaasi ja epäonnistuit surkeasti. Mitä tästä opimme: älä yritä." +collectibles.352="Tee se! Tee se nyt! Älä anna unelmiesi jäädä vain unelmiksi, ja tee se!" +collectibles.353="Älä koskaan luovuta, paitsi jos olet osallistunut kansainvälisiin luovuttamisen maailmanmestaruuskisoihin." +collectibles.354="Keksit tuovat onnea. Nea tuo keksejä." +collectibles.355="Ihmiset ovat kuin suklaakonvehteja. Jotkut ovat sisältä pehmeitä, jotkut kovia, jotkut sitkeitä ja jotkut taas läpeensä pahoja!" +collectibles.356="Jos unohdat miltä näytät, katso peiliin. Jos peili ei katso takaisin, se on ikkuna!" +collectibles.357="Älä huolehdi tilastoista - vain hauskuudella on merkitystä!" +collectibles.358="Tiimityö on tärkeää - voit aina syyttää jotakuta muuta kuin itseäsi." +collectibles.359="Syö tacosi aina tortillan päällä. Niin, jos täytteet putoavat sisältä, saat heti toisen tacon!" +collectibles.360="Tee jonkun päivästä hyvä olemalla mukava, ja joku saattaa tehdä samoin sinulle!" +collectibles.361="Aikainen lintu madon nappaa, mutta yök kuka haluaisi syödä matoja???" +collectibles.362="Mikset hankkisi kavereita tänään? Lisää heitä komennolla /friend!" +collectibles.363="Jos et ole iloinen juuri siinä ja nyt, ota pari askelta vasemmalle. Jos et vieläkään ole iloinen, emme valitettavasti voi auttaa." +collectibles.364="Jos työnnät tarpeeksi lujaa, pääset minkä tahansa esteen ohi - paitsi ehkä vedettävän oven!" +collectibles.365="Hyvät tavat korvaavat vain nopeat refleksit." +collectibles.366="Älä huolestu, jos suunnitelma A epäonnistuu - aakkosissa on vielä 28 kirjainta jäljellä!" +collectibles.367="Jos haluat saada perheesi huomion, laita vain WiFi pois päältä hetkeksi!" +collectibles.368="Kun ihmiset sanovat käyneensä maailman joka nurkassa, mitä he oikeastaan tarkoittavat? Eihän maapallolla ole nurkkia!" +collectibles.369="Jos äiti sanoo ei, kysy iskältä!" +collectibles.370="Unohda kaikki mitä olen joskus sanonut." +collectibles.371="Onnittelut, olet voittanut tyhjänpäiväisen elämänviisauden! Twiittaa kuvankaappaus @HypixelNetwork saadaksesi palkinnoksi ei-mitään!" +collectibles.372="Jotkut oppivat toisten tekemistä virheistä; jotkut taas ovat niitä toisia." +collectibles.373="Ihmissuhteet ovat kuin matematiikkaa. Aivan liikaa muuttujia eikä ratkaisuja löydy millään." +collectibles.374="Olet ainutlaatuinen, kuten kaikki muutkin." +collectibles.375="Aloitit tyhjästä ja tyhjällä jatketaan, ainakin suurimmaksi osaksi." +collectibles.376="Vaihda salasanaksesi \"väärin\". Sillä tavoin, jos satut unohtamaan sen, tietokoneesi kyllä muistuttaa!" +collectibles.377="Kuinkahan syviä valtameret olisivat ilman pesusieniä?" +collectibles.378="Maailmassa on kolmenlaisia ihmisiä: niitä jotka saavat laskea ja niitä jotka eivät osaa." +collectibles.379="Jos et löydä avointa ovea, kokeile ikkunaa. Jos et löydä avointa ikkunaa, älä yritä murtautua talooni!" +collectibles.380="Maailmankaikkeus koostuu protoneista, neutroneista, elektroneista ja tomppeleista" +collectibles.381="Seuraava virke on valetta. Edellinen virke on totta." +collectibles.382="Etsimäsi onni löytyy toisesta keksistä." +collectibles.383="Jos kampaamossa on kaksi kampaajaa, valitse se, jolla on huonompi kampaus." +collectibles.384="Tänään voisit pelata jotain mitä et ole koskaan ennen kokeillut - käytä kompassia!" +collectibles.385="Oho, katso, keksi!" +collectibles.386="Se keksi oli todella maukas!" +collectibles.387="Katsohan, siellä oli pieni paperinpala sisällä! Mitä siinä lukee?" +collectibles.388="Onnenkeksi: %%message%%" +collectibles.389="Mikä on parempaa kuin keksi? Keksi joka antaa myös päteviä elämänohjeita! Nauti tästä makeasta herkusta ja sen jakamista viisaista sanoista tällä Onnenkeksivempaimella." +collectibles.390="Joku edelleen leikkii edellisellä Frisbeelläsi! Et voi tuoda kahta frisbeetä juhliin, eihän se olisi reilua!" +collectibles.391="Heitit frisbeen! Ystäväsi voivat oikeaklikata sitä ottaakseen sen kiinni ja vasenklikata heittääkseen sen!" +collectibles.392="Frisbeetäsi on heitetty %%passes%% kerran." +collectibles.393="Frisbeetäsi on heitetty %%passes%% kertaa." +collectibles.394="Heitä tämä matto... siis frisbee ystävillesi pitääksenne hauskaa!" +collectibles.395="Ensimmäinen" +collectibles.396="Toinen" +collectibles.397="Kolmas" +collectibles.398="Neljäs" +collectibles.399="Viides" +collectibles.400="Luo leijuvia kummituspäitä, jotka lentelevät ympäriinsä ennen nopeaa katoamistaan." +collectibles.401="Joskus on heitettävä turhat huolet pois... ja joskus taas on vain heitettävä! Keinu ympäri suosikkilobbyasi tällä Heittokoukkuvempaimella." +collectibles.402="Näet salaman välähdyksiä, kuulet verenhimoisia huutoja ja tunnet kauan sitten kuolleen kuninkaan kutsun... Minulla on ikävä tunne tästä Kauhuelokuvavempaimesta!" +collectibles.403="Tässä lobbyssa on jo kuumailmapallo. Yritä myöhemmin uudelleen." +collectibles.404="Pyysimme ihan tavallista ilmapalloa, mutta sillä kaverilla oli vain XXL-kokoa jäljellä. Lennä taivaisiin tällä Kuumailmapallovempaimella!" +collectibles.405="Ooh, kauhallinen minttusuklaata? Onnistuu!" +collectibles.406="Mansikkajäätelöä, minun suosikkiani!" +collectibles.407="Hasselpähkinäkuorrute... Tuplasuklaa... Ja vaniljaa... Unohtuikohan jotain?" +collectibles.408="Pahoittelut, meillä käy vain käteinen!" +collectibles.409="Valitettavasti minulla ei ole vaihtorahaa juuri nyt :(" +collectibles.410="Jäätelönmyyjä: %%message%%" +collectibles.411="\"Ottaisin vaniljatoffeejäätelön, kiitos!\"" +collectibles.412="Avaa musiikkisoittimen, josta voit valita soittettavan minkä tahansa C418:n hittikappaleista." +collectibles.413="13" +collectibles.414="Palikat" +collectibles.415="Chirp" +collectibles.416="Far" +collectibles.417="Mall" +collectibles.418="Mellohi" +collectibles.419="Stal" +collectibles.420="Strad" +collectibles.421="Ward" +collectibles.422="11" +collectibles.423="Wait" +collectibles.424="Pysäytä kappale" +collectibles.425="Pysäytä nykyinen kappale." +collectibles.426="\"3... 2... 1... olemme nousseet ilmaan! Odotas hetki... jep... hän osui puuhun!\" Täräytä itsesi äärettömyyteen ja sen yli tällä räjähtävän tehokkaalla Rakettireppuvempaimella." +collectibles.427="Anna keksien sataa ympärillesi!" +collectibles.428="Vapauta pieni lumimyrsky, joka peittää alueen ympärilläsi lumeen joksikin aikaa!" +collectibles.429="Saa vastauksia mieltä painaviin kysymyksiin maailman suurimmilta johtajilta." +collectibles.430="Se kaveri, joka just tapettiin," +collectibles.431="Ammmmuuuuuuu." +collectibles.432="Kello on 12, herätys." +collectibles.433="Piippolan vaari" +collectibles.434="GLaDOS" +collectibles.435="Taas yksi tiimaaja" +collectibles.436="VRRUUUUMMMMM" +collectibles.437="TUHOTAAN!" +collectibles.438="Autoclicker" +collectibles.439="Nicholas Cage" +collectibles.440="Rakastan sinua." +collectibles.441="*psst* liity palvelimelle mc.hypixel.net" +collectibles.442="Puu, joka on oikeasti koira" +collectibles.443="YOLOOOOOOOO" +collectibles.444="SlothPixel" +collectibles.445="Korjattu." +collectibles.446="Limbossa taitaa olla jotain..." +collectibles.447="Nerffatkaa toi luokka!" +collectibles.448="Korjaus: Itkevät enkelit eivät itse asiassa puhu." +collectibles.449="Kukko" +collectibles.450="Keksimonsteri" +collectibles.451="Tohtori" +collectibles.452="RUOKI MINUT." +collectibles.453="Matkija." +collectibles.454="notch" +collectibles.455="Kybermies" +collectibles.456="Lehmä" +collectibles.457="Dalek" +collectibles.458="Olen Batman." +collectibles.459="Rooarrrrrrr" +collectibles.460="Rick Grimes" +collectibles.461="Teini Starbucksin autokaistalla" +collectibles.462="Joku" +collectibles.463="Kissa" +collectibles.464="Varastan itsenäisyysjulistuksen." +collectibles.465="AgentKid" +collectibles.466="Vuh. Hehe." +collectibles.467="Eikö tämä muka ole voita?" +collectibles.468="Haistan sinut." +collectibles.469="Sinun tappaminen ja neuvominen eivät ole toisensa poissulkevia." +collectibles.470="Olisin kateellinen sinulle, jos en olisi minä." +collectibles.471="Sinut päivitetään." +collectibles.472="Cryptkeeper" +collectibles.473="Morgan Freeman" +collectibles.474="MUTTTA CARRRLLLLL!" +collectibles.475="Olen vain tosi, tosi, tosi, tosi hyvä jitterclickaamaan" +collectibles.476="Keksejä." +collectibles.477="I'm so GLaD to see you" +collectibles.478="Älä räpäytä silmiäsi." +collectibles.479="Barney" +collectibles.480="#EiFiltteriä" +collectibles.481="Karhu" +collectibles.482="Se imuri Teletapeista" +collectibles.483="Jotkut tiimaajat just tappo mut!" +collectibles.484="Batman" +collectibles.485="häh" +collectibles.486="Rikki." +collectibles.487="Minulla on talo." +collectibles.488="hcherndon" +collectibles.489="Taikapallo" +collectibles.490="Itkevä enkeli" +collectibles.491="%%author%% sanoo: %%message%%" +collectibles.492="Jokseenkin tavallinen matto. Paitsi että sillä voi lentää, tietenkin. Arabian yöt odottavat sinua ja tätä Taikamattovempainta." +collectibles.493="OtusPyssy: %%mob%% (Klikkaa käyttääksesi)" +collectibles.494="Oikeaklikkaa ampuaksesi valitun otuksen." +collectibles.495="Vasenklikkaa valitaksesi otuksen." +collectibles.496="Ammu räjähtäviä ammuksia, jotka voivat olla %%amount%% erilaista otusta." +collectibles.497="Ei hätää, tämän vempaimen aktivoiminen ei aiheuta sukupuuttoaaltoa... se vain säikäyttää ystäväsi! Syöksy maahan tulisena räjähdyksenä tällä galaktisella Meteoriittivempaimella." +collectibles.498="Peittää sinut timanteilla näyttäen suuret rikkautesi." +collectibles.499="Yksittäinen" +collectibles.500="Kolminkertainen" +collectibles.501="Viisinkertainen" +collectibles.502="Värikuula-ase: %%type%% laukaus (Klikkaa käyttääksesi)" +collectibles.503="Oikeaklikkaa ampuaksesi." +collectibles.504="Vasenklikkaa vaihtaaksesi ammuksia." +collectibles.505="Mikä olisikaan parempi tapa koristella lobbya kuin maalata sitä vähän uudestaan? Tai paljon...kuka laskee?" +collectibles.506="Jättää satunnaisesti värjätyn, nopeasti katoavan savivanan jälkeesi." +collectibles.507="Laukaisee sinut taivaisiin ja aktivoi sitten laskuvarjon, jotta voit laskeutua pehmeästi takaisin maahan." +collectibles.508="Räjähdä poksuvaksi konfettisateeksi, joka varmasti saa koko lobbyn juhlatunnelmaan." +collectibles.509="Ratsasta Ender-helmellä!" +collectibles.510="SANO CHEESE!" +collectibles.511="HYMYÄ!" +collectibles.512="HYPIXEL!" +collectibles.513="Valmistaudu kuvaan!" +collectibles.514="Ota näyttökuva parhaiden ystäviesi kanssa!" +collectibles.515="Etkö voi mennä rannalle? Ei se mitään! Kanna omaa paikkaasi takataskussasi!" +collectibles.516="Ota ystäväsi mukaan lätkimään Pinataa. Voitte pitää karkit." +collectibles.517="Sytyttää sinut tulipalloksi 10 sekunnin ajaksi, kunnes jäähdyt taas." +collectibles.518="Lobbyt heräävät eloon musiikin tahdissa! Kuuntele parhaimpia levysoitinhittejä tällä patentoidulla Radiovempaimella!" +collectibles.519="Tapahtui virhe yrittäessä soittaa tuota kappaletta!" +collectibles.520="Nyt soi %%name%%." +collectibles.521="Suoraan Quakecraftista, tavallinen sädease valmiina tulittamaan käskystä!" +collectibles.522="Tämä lobby on liian kiireinen, jotta voisit käyttää tuota Vempainta!" +collectibles.523="Tässä lobbyssa on jo Sateenkaari, yritä uudelleen hetken kuluttua!" +collectibles.524="Luo kokonaisen sateenkaaren, josta löytyvät kaikki rakastamasi värit, jotka vain voit nähdä." +collectibles.525="RAKETIN LAUKAISU %%time%% SEKUNNIN KULUTTUA!" +collectibles.526="RAKETIN LAUKAISU %%time%% SEKUNNIN KULUTTUA!" +collectibles.527="HOUSTON, OLEMME ILMASSA!" +collectibles.528="Räjähdä suoraan kuuhun tällä suurella raketilla, josta löytyvät niin lähtölaskenta kuin äänetkin unohtamatta räjähtäviä efektejä." +collectibles.529="Sinun tulee kutsua lemmikkisi käyttääksesi tätä vempainta!" +collectibles.530="Käske lemmikkiäsi kierähtämään selälleen, jotta voit rapsuttaa sen mahaa." +collectibles.531="Rakenna oma linnasi oikealla hiekalla!" +collectibles.532="Luo variksenpelättimen, joka muuttaa lähellä olevien pelaajien päät kurpitsoiksi." +collectibles.533="Tee itsestäsi todellinen VIP näillä Salaisen palvelun agenteilla." +collectibles.534="Olet jo asettanut viirin." +collectibles.535="Aseta viiri esitelläksesi mahtavaa pistemäärääsi SkyWars Rankedissa." +collectibles.536="Huhtikuu 2016" +collectibles.537="Toukokuu 2016" +collectibles.538="Kesäkuu 2016" +collectibles.539="Heinäkuu 2016" +collectibles.540="Elokuu 2016" +collectibles.541="Kauden 1 viiri" +collectibles.542="Kauden 2 viiri" +collectibles.543="Kauden 2 viiri" +collectibles.544="Kauden 3 viiri" +collectibles.545="Kauden 3 viiri" +collectibles.546="Kauden 4 viiri" +collectibles.547="Kauden 4 viiri" +collectibles.548="Kauden 5 viiri" +collectibles.549="Kauden 5 viiri" +collectibles.550="Rautadivisioona" +collectibles.551="Rautadivisioona #%%position%%" +collectibles.552="Kultadivisioona" +collectibles.553="Kultadivisioona #%%position%%" +collectibles.554="Timanttidivisioona" +collectibles.555="Timanttidivisioona #%%position%%" +collectibles.556="Mestaridivisioona" +collectibles.557="Mestaridivisioona #%%position%%" +collectibles.558="SkyWars -palkintoviiri" +collectibles.559="Tämä viiri on palkinto SkyWars Rankedin kaudesta %%season%%" +collectibles.560="Klikkaa tästä aktivoidaksesi!" +collectibles.561="Voi ei, se on rikki!" +collectibles.562="Et ole avannut tätä viiriä." +collectibles.563="Kiemurtele kuin käärme!" +collectibles.564="Tällä tekniikalla käyttäjät vaihtavat oman ruumiinsa puupalikkaan." +collectibles.565="Käynnistetään teleporttausta. Odota paikoillasi!" +collectibles.566="Skannataan pelaajia ja etsitään teleporttikohdetta..." +collectibles.567="Tehtävä \"etsiKohde\" epäonnistui! Ei sopivia kohteita!" +collectibles.568="Kohde havaittu: %%target%%!" +collectibles.569="Pysäytetään teleporttausta..." +collectibles.570="Pidä kiinni! Teleportataan..." +collectibles.571="Oho! Kohde on poistunut tutkasta! Pysäytetään..." +collectibles.572="Teleporttaus suoritettu! Kiitos, että käytit Hypixelin Pikakuljetusta!" +collectibles.573="Liian kaukana!" +collectibles.574="Et voi teleportata sinne!" +collectibles.575="Voit teleportata minne tahansa lobbyssa oikeaklikkamalla tällä taikakepillä." +collectibles.576="Tennispallovempain. Se on pallo ja yleensä sitä käytetään tenniksen pelaamiseen. Ai etkö pelaa tennistä? Voit toki aina heitellä sitä lemmikillesi, jos sinulla siis on sellainen!" +collectibles.577="Luo salon ja pallon - nyt voit pelata nopean pelin salkopalloa!" +collectibles.578="Klikkaa tästä!" +collectibles.579="Klikkaa tästä asettaaksesi merkkisi." +collectibles.580="Ei ole sinun vuorosi!" +collectibles.581="Nyt ei ole sinun vuorosi - et voi tehdä mitään." +collectibles.582="Tämä paikka kuuluu oranssille." +collectibles.583="Tämä paikka kuuluu siniselle." +collectibles.584="Oikeaklikkaa pelaajaa aloittaaksesi Ristinollapelin hänen kanssaan!" +collectibles.585="Olet jo kutsunut pelaajan %%player%% Ristinollapeliin." +collectibles.586="Haastoit pelaajan %%player%% Ristinollapeliin." +collectibles.587="%%player%% haastoi sinut Ristinollapeliin." +collectibles.588="Klikkaa tästä hyväksyäksesi haasteen." +collectibles.589="Klikkaa tästä hylätäksesi haasteen." +collectibles.590="Oranssi:" +collectibles.591="Sininen:" +collectibles.592="Oranssi pelaaja on %%player%%" +collectibles.593="Sininen pelaaja on %%player%%" +collectibles.594="Ristinollapeli pelaajan %%player%% kanssa päättyi tasapeliin." +collectibles.595="Voitit pelaajan %%player%% Ristinollassa!" +collectibles.596="%%player%% voitti sinut Ristinollassa!" +collectibles.597="Haasta ystäväsi ristinollapeliin. Kuka onkaan voittaja?" +collectibles.598="%%player%% poistui Ristinollapelistä." +collectibles.599="Luo animoidun suihkulähteen, josta sataa sytytettyä TNT:tä." +collectibles.600="Kutsu Tornado, aivan kuin pelaisit Mega Wallsia Shamaanina." +collectibles.601="Luo trampoliinin, jolla voit pomppia korkealle ilmaan. Kutsu kaikki kaveritkin mukaan!" +collectibles.602="Mikä on parasta, mitä kullalla voi tehdä? Tietenkin heitellä sitä ympäriinsä." +collectibles.603="Uusi Rantapallosi korvasi vanhan." +collectibles.604="Mikään ei ole hauskempaa kuin pelata rantapalloa, kutsu kaikki kaverisikin mukaan!" +collectibles.605="Vesi-ilmapallosi on edelleen jossain!" +collectibles.606="Luo lentävän sian, jolla voit ratsastaa taisteluun!" +collectibles.607="Suoraan TNT Wizardsista. Voit vaihtaa Kineettisten, Jäisten ja Veristen voimien välillä! Ota käyttöösi taian mahti tällä taikasauvavempaimella." +collectibles.608="Taikasauva: %%name%% (Vasenklikkaa vaihtaaksesi tyyppiä)" +collectibles.609="Oikeaklikkaa käyttääksesi." +collectibles.610="Vasenklikkaa vaihtaaksesi." +collectibles.611="Unohditko aurinkovoiteen mennessäsi rannalle? Anna kaikkien tietää kuinka pahasti olet palanut tällä Rusketusemotella!" +collectibles.612="Ihana tunne? Levitä hyvää oloa tällä Sydänsilmät-emotella!" +collectibles.613="Eikö päälobbyn vuoristorata ole tehty sinua varten? Näytä kaikille millainen olo sinulla on tällä Pahoinvoiva-emotella!" +collectibles.614="Onko kaikki sinun käsissäsi? Näytä armoa vastustajillesi tällä Rest in Pepperoni -emotella!" +collectibles.615="Mukava olo? Varmasti on tällä Rentoutunut-emotella!" +collectibles.616="Oliko se habanero tulista? Näytä tuskasi muillekin tällä Tulinen-emotella!" +collectibles.617="Pidätkö leveilystä? Näytä kaikille kuinka siisti tyyppi olet tällä oikealla Deal with it -emotella!" +collectibles.618="Voi viikset millaiset viikset! Esittele vetovoimaasi tällä herrasmiesmäisellä Viikset-emotella." +collectibles.619="Emotet on tällä hetkellä poistettu käytöstä!" +collectibles.620="Tämä emote on väliaikaisesti poissa käytöstä!" +collectibles.621="Tämä emote on tällä hetkellä poissa käytöstä!" +collectibles.622="Emotet on tällä hetkellä poistettu käytöstä tässä lobbyssa!" +collectibles.623="Emotet & eleet" +collectibles.624="Toteuta itseäsi! Näytä koko tunteidesi kirjo näillä ainutlaatuisilla animoiduille Emoteilla & Eleillä" +collectibles.625="Nollaa emote" +collectibles.626="%%name%%emote" +collectibles.627="Muodonmuutokset on väliaikaisesti poistettu käytöstä" +collectibles.628="Valitaksesi hatun, avaa Vanity Shop tavaraluettelostasi!" +collectibles.629="Et ole kutsunut lemmikkiä!" +collectibles.630="Lemmikin nimi nollattu." +collectibles.631="Lemmikin nimi voi olla enintään 16 merkkiä pitkä!" +collectibles.632="Asetettiin lemmikin nimeksi %%name%%" +collectibles.633="Lemmikin nimen tulee olla aakkosnumeerinen!" +collectibles.634="Aseta lemmikin nimi." +collectibles.635="Teleporttaa lemmikki luoksesi." +collectibles.636="Teleporttaa lemmikin luo." +collectibles.637="Omistajat ja heidän lemmikkinsä: %%result%%" +collectibles.638="Ei löydetty pelaajaa tuolla nimellä!" +collectibles.639="Tyyppiä %%type%% ei ole olemassa!" +collectibles.640="Pelaajalla %%target%% ei ole lemmikkiä: %%type%%" +collectibles.641="Etsi omistaja -> lemmikki nykyisestä istunnosta." +collectibles.642="Etsi kaikki tietyn pelaajan lemmikit." +collectibles.643="Nollaa pelaajan lemmikin nimi." +collectibles.644="Emotet on väliaikaisesti poistettu käytöstä" +collectibles.645="Eleet on väliaikaisesti poistettu käytöstä" +collectibles.646="Limapartikkelipaketti" +collectibles.647="Laavapisarat-partikkelipaketti" +collectibles.648="Vesipisarat-partikkelipaketti" +collectibles.649="Nuottipartikkelipaketti" +collectibles.650="Sydänpartikkelipaketti" +collectibles.651="Iloinen kyläläinen -partikkelipaketti" +collectibles.652="Vihainen kyläläinen -partikkelipaketti" +collectibles.653="Lumouspöytä-partikkelipaketti" +collectibles.654="Taputusele" +collectibles.655="Siisti tanssi -ele" +collectibles.656="Voitonele" +collectibles.657="Näkemiin-ele" +collectibles.658="Hyppyele" +collectibles.659="Hype-tanssiele" +collectibles.660="Aaltotanssiele" +collectibles.661="Ylävitonen-ele" +collectibles.662="Balettiele" +collectibles.663="Mieli-ele" +collectibles.664="Can-ele" +collectibles.665="Karaoke-ele" +collectibles.666="Hulatanssiele" +collectibles.667="Valmistujaiset-ele" +collectibles.668="Raputanssiele" +collectibles.669="Aurinkoele" +collectibles.670="Aarre-ele" +collectibles.671="Juuri nyt poissa käytöstä!" +collectibles.672="Nämä partikkeleista tehdyt kaavut ovat äärimmäisen tyylikkäitä. Kaapu aktivoituu jos seisot paikallasi sekunnin ajan lobbyssa." +collectibles.673="Nollaa kaapu" +collectibles.674="Supersankarin kaapu" +collectibles.675="Mystinen kaapu" +collectibles.676="Tulisiivet-kaapu" +collectibles.677="Vampyyrinsiivet-kaapu" +collectibles.678="Huurteinen kaapu" +collectibles.679="Jääsiivet-kaapu" +collectibles.680="Shamaanin kaapu" +collectibles.681="Nouse tuhkasta kuin feeniks näiden liekkien keskeltä!" +collectibles.682="Saa nyt kylmä viima tää puhaltaa!" +collectibles.683="Olenko se vain minä vai onko täällä kylmä?" +collectibles.684="Salaisuuksiin kätketty ja uskomattoman voimakas, tämä kaapu on monen legendan keskipiste." +collectibles.685="Joudu tornadon saartamaksi, samanlaisen kuin Shamaanilla Mega Wallsissa." +collectibles.686="Suoraan sarjakuvista tuleva kuuluisa punainen kaapu!" +collectibles.687="Suuret mustanpunaiset vampyyrinsiivet levittäytyvät selästäsi luomaan kauhua!" +collectibles.688="Tyyppi: %%type%%" +collectibles.689="Janoisuus" +collectibles.690="Kunto" +collectibles.691="Tila: %%happiness%%" +collectibles.692="Luominen tai nimeäminen vaatii VIP-rankin." +collectibles.693="Luominen tai nimeäminen vaatii VIP-rankin." +collectibles.694="Osta osoitteessa http://store.hypixel.net" +collectibles.695="Vasenklikkaa poistaaksesi tämän companionin." +collectibles.696="Vasenklikkaa poistaaksesi tämän lemmikin." +collectibles.697="Vasenklikkaa kutsuaksesi tämän companionin." +collectibles.698="Vasenklikkaa kutsuaksesi tämän lemmikin." +collectibles.699="(Käytä komentoa /pet asettaaksesi nimen)" +collectibles.700="Klikkaa nähdäksesi kaikki lemmikit kategoriasta %%category%%!" +collectibles.701="Et voi ratsastaa muiden pelaajien companioneilla!" +collectibles.702="Et voi ratsastaa tällä lemmikillä." +collectibles.703="Et voi ratsastaa muiden pelaajien lemmikeillä!" +collectibles.704="Sinulla tulee olla %%rank%% voidaksesi ratsastaa lemmikilläsi!\nOsta se osoitteessa http://store.hypixel.net" +collectibles.705="Lemmikit on tällä hetkellä poistettu käytöstä tässä lobbyssa!" +collectibles.706="Sinun tulee olla vähintään VIP voidaksesi kutsua lemmikkejä!\nOsta se osoitteessa http://store.hypixel.net" +collectibles.707="Käsitellään viimeisintä tehtäväpyyntöäsi!" +collectibles.708="Et voi käyttää tätä vielä! Ole hyvä ja odota vielä %%minutes%% minuuttia." +collectibles.709="Oikeaklikkaa lemmikkiäsi Lemmikkivalikossa syöttääksesi niitä ja kasvattaaksesi niiden onnellisuutta." +collectibles.710="Kerää niitä, syötä niitä ja leiki niiden kanssa! Nosta lemmikkiesi tasoa pitämällä niistä huolta!" +collectibles.711="Tarvitsetko jonkun auttamaan sinut ulos kuorestasi? Kaikki onnistuu kyllä, hitaasti mutta varmasti. Sen tietää myös tämä Turtle companion!" +collectibles.712="Nämä pikku kaverit seuraavat maailman anteliainta ihmistä, ja sehän oletkin " +collectibles.713="Ulvoo, uikuttaa ja ulisee keskellä yötä... kaikki ystäväsi siis nähdessään siistin karvaisen kaverisi! Vie tämä Black Pug companion kävelylle tänään." +collectibles.714="Etsitkö mahtavaa kumppania? Tämä kaakattava pikkukaveri ja sen pikkuinen nokka ovat voittamattomat! Laita höyhenet pöllyämään tällä Duck companionilla!" +collectibles.715="Hän oli kerran kaunis ihmisprinssi, jonka vanhan noidan kirous muutti... tai ainakin niin hän kaikille kertoo. Tämä ystävällinen Frog companion on vain hypyn, loikan ja ponkauksena päässä!" +collectibles.716="BLIIP-BLOOP. BLIIP-BLOOP. Bwwwoooooooo! Se on robottikieltä ja tarkoitaa \"rakastan sinua\". Aavikkoplaneetalta Hypixelin lobbyyn, valmistaudu pyörimään tämän rakastettavan HP8 companionin kanssa!" +collectibles.717="Jos koira on ihmisen paras ystävä, tämä pikkukaveri on parhaistakin ystävistä parhain! Vietä koiranpäiviä tämän White Pug companionin kanssa." +collectibles.718="Such pet. Many fluffy. Much doge. Wow. Ystävysty kaikkien aikojen suloisimman ja pörröisimmän meemin, Shibe companionin, kanssa!" +collectibles.719="Apina näkee, apina tekee, apina perässäsi kuljeskelee. Syö paljon banaania yhdessä tämän puun oksissa keinuvan Chimp companionin kanssa!" +collectibles.720="Voit kysyä häneltä miksi hän lyö rintaansa, voit kysyä häneltä miksi hän rakastaa banaaneja, mutta mitä tahansa teetkin... ÄLÄ kysy mistä hän hankki nuo lasit! Tapaa viidakon todellinen kunigas tällä rajulla Gorilla companionilla." +collectibles.721="Hän ei ehkä taida pelättyä Kung Fua, mutta anna tälle pikkukaverille vähän bambua, niin saat elinikäisen ystävä. Naura ja leiki tämän laiskanpulskean Panda companionin kanssa!" +collectibles.722="Sanotaan, ettei norsu koskaan unohda... seurata sinua ympäri Hypixelin lobbyja! Ota kiinni kärsästäsi ja liity laumaan tällä pienellä Elephant companionilla." +collectibles.723="Tauon paikka! Aika venytellä jalkoja ja lähteä kävelyllä tämän seikkailunhaluisen Magic Dog companionin kanssa!" +collectibles.724="Voit tukea palvelinta avaamalla tämän Companionin Hypixel Storessa: store.hypixel.net!" +collectibles.725="Tämän lemmikin voi saada ainoastaan kampanjatarjouksena MCProHostingilta! Kirjoita /mcph saadaksesi lisätietoa." +collectibles.726="Poistettiin companion: %%type%%!" +collectibles.727="Kutsuttiin companion: %%name%%!" +collectibles.728="Kutsuttiin lemmikki: %%name%%!" +collectibles.729="Sinulla ei ole lemmikkiesineitä! Löydä niitä avaamalla Mystery Boxes ensin!" +collectibles.730="Hanki tämä mahtava ja halittava %%pet%% itsellesi heti!" +collectibles.731="Tämän lemmikin voi\nsaada ainoastaan\nkampanjatarjouksena\nMCProHostingilta! Kirjoita\n/mcph saadaksesi lisätietoa." +collectibles.732="Oikeaklikkaa huolehtiaksesi tai poistaaksesi suosikeista." +collectibles.733="Oikeaklikkaa huolehtiaksesi tai lisätäksesi suosikkeihin." +collectibles.734="Oikeaklikkaa huolehtiaksesi." +collectibles.735="Kissa: Musta" +collectibles.736="Kissa: Punainen" +collectibles.737="Kissa: Siamilainen" +collectibles.738="Hevonen: Ruskea" +collectibles.739="Lammas: Valkoinen" +collectibles.740="Lammas: Harmaa" +collectibles.741="Lammas: Ruskea" +collectibles.742="Lammas: Hopea" +collectibles.743="Hevonen: Kermanvalkoinen" +collectibles.744="Hevonen: Kastanjanruskea" +collectibles.745="Hevonen: Tummanruskea" +collectibles.746="Hevonen: Harmaa" +collectibles.747="Muuli" +collectibles.748="Kyläläinen: Maanviljelijä" +collectibles.749="Kyläläinen: Kirjastonhoitaja" +collectibles.750="Kyläläinen: Pappi" +collectibles.751="Kyläläinen: Seppä" +collectibles.752="Kyläläinen: Teurastaja" +collectibles.753="Lammas: Oranssi" +collectibles.754="Lammas: Purppura" +collectibles.755="Lammas: Vaaleansininen" +collectibles.756="Lammas: Keltainen" +collectibles.757="Lammas: Limetinvihreä" +collectibles.758="Lammas: Syaani" +collectibles.759="Lammas: Violetti" +collectibles.760="Lammas: Sininen" +collectibles.761="Lammas: Vihreä" +collectibles.762="Lammas: Punainen" +collectibles.763="Luolahämähäkki" +collectibles.764="Lima (Pieni)" +collectibles.765="Magmakuutio (Pieni)" +collectibles.766="Zombi (Pieni)" +collectibles.767="Possu" +collectibles.768="Vasikka" +collectibles.769="Sudenpentu" +collectibles.770="Kananpoika" +collectibles.771="Kissanpentu: Musta" +collectibles.772="Kissanpentu: Punainen" +collectibles.773="Kissanpentu: Siamilainen" +collectibles.774="Varsa: Ruskea" +collectibles.775="Karitsa: Valkoinen" +collectibles.776="Karitsa: Harmaa" +collectibles.777="Karitsa: Ruskea" +collectibles.778="Karitsa: Hopea" +collectibles.779="Hevonen: Valkoinen" +collectibles.780="Hevonen: Musta" +collectibles.781="Epäkoullut hevonen" +collectibles.782="Kyläläinen: Zombi" +collectibles.783="Sikamieszombi" +collectibles.784="Lammas: Musta" +collectibles.785="Lammas: Vaaleanpunainen" +collectibles.786="Lepakko" +collectibles.787="Lima (Keskikokoinen)" +collectibles.788="Magamkuutio (Keskikokoinen)" +collectibles.789="Mooshroom" +collectibles.790="Varsa: Kermanvalkoinen" +collectibles.791="Varsa: Kastanjanruskea" +collectibles.792="Varsa: Tummanruskea" +collectibles.793="Varsa: Harmaa" +collectibles.794="Kyläläinen: Maanviljelijä (Pieni)" +collectibles.795="Kyläläinen: Kirjastonhoitaja (Pieni)" +collectibles.796="Kyläläinen: Pappi (Pieni)" +collectibles.797="Kyläläinen: Seppä (Pieni)" +collectibles.798="Kyläläinen: Teurastaja (Pieni)" +collectibles.799="Karitsa: Oranssi" +collectibles.800="Karitsa: Purppura" +collectibles.801="Karitsa: Vaaleansininen" +collectibles.802="Karitsa: Keltainen" +collectibles.803="Karitsa: Limetinvihreä" +collectibles.804="Karitsa: Syaani" +collectibles.805="Karitsa: Violetti" +collectibles.806="Karitsa: Sininen" +collectibles.807="Karitsa: Vihreä" +collectibles.808="Karitsa: Punainen" +collectibles.809="Lammas: Sateenkaari" +collectibles.810="Mooshroom-vasikka" +collectibles.811="Sikamieszombi (Pieni)" +collectibles.812="Karitsa: Vaaleanpunainen" +collectibles.813="Karitsa: Musta" +collectibles.814="Noita" +collectibles.815="Luurankohevonen" +collectibles.816="Lumiukko" +collectibles.817="Lima (Iso)" +collectibles.818="Magmakuutio (Iso)" +collectibles.819="Wither-luuranko" +collectibles.820="Vihreä tonttu" +collectibles.821="Punainen tonttu" +collectibles.822="Villi oselotti" +collectibles.823="Villi oselotinpentu" +collectibles.824="Jänis: Ruskea" +collectibles.825="Jänis: Valkoinen" +collectibles.826="Jänis: Musta" +collectibles.827="Jänis: Mustavalkoinen" +collectibles.828="Jänis: Kultainen" +collectibles.829="Jänis: Harmaanruskea" +collectibles.830="Varautunut creeper" +collectibles.831="Kilpikonna" +collectibles.832="Gifterino" +collectibles.833="Black Pug" +collectibles.834="Ankka" +collectibles.835="Sammakko" +collectibles.836="White Pug" +collectibles.837="Shibe" +collectibles.838="Chimp" +collectibles.839="Gorilla" +collectibles.840="Panda" +collectibles.841="Elephant" +collectibles.842="Magic Dog" +collectibles.843="Nykyinen companion" +collectibles.844="Nykyinen lemmikki" +collectibles.845="Et voi käyttää tätä vielä! Ole hyvä ja odota vielä %%minutes%% minuuttia." +collectibles.846="Odotusaika: VALMIS" +collectibles.847="Klikkaa ansaitaksesi Lemmikkipisteitä!" +collectibles.848="Odotusaika: %%minutes%% minuuttia" +collectibles.849="Et voi käyttää tätä vielä." +collectibles.850="Kerättyjen Lemmikkipisteiden\nmäärä kasvaa mitä onnellisempi\nlemmikkisi on." +collectibles.851="Lähettää kaikki Onnelliset , Erittäin\nonnelliset ja Superonnelliset lemmikkisi\nhuippusalaiselle lemmikkitehtävälle, jotta\nne ansaitsisivat lemmikkipisteitä!" +collectibles.852="Lähettää lemmikit tehtävälle" +collectibles.853="Lemmikkisi" +collectibles.854="Herkullinen hedelmä!" +collectibles.855="Lemmikkisi %%name%% %%attribute%% on jo täynnä!" +collectibles.856="Tämän esineen voi löytää vain Mysteeriholvista! Pelaa pelejä ansaitaksesi Mystery Boxes." +collectibles.857="Kasvattaa lemmikin kylläisyyttä." +collectibles.858="Kasvattaa lemmikin kuntoa." +collectibles.859="Laskee lemmikin janoisuutta." +collectibles.860="Jäljellä: %%consumables%%" +collectibles.861="Klikkaa antaaksesi lemmikille!" +collectibles.862="Sisältää siemeniä." +collectibles.863="Annoskoko: kaikki." +collectibles.864="Tekee hyvää näölle!" +collectibles.865="Pe-ru-na Po-taat-ti" +collectibles.866="Sienikeitto" +collectibles.867="Tämä EI ole sienimuhennosta!" +collectibles.868="Maistuu yhtä hyvältä kuin tuoksuukin!" +collectibles.869="Heinä" +collectibles.870="Hei nääs..." +collectibles.871="Ei vielä käsitelty" +collectibles.872="Vasta leivottu." +collectibles.873="Suklaahipuilla!" +collectibles.874="Tämä ei ole valetta." +collectibles.875="Paikallisen kalastajan nappaama." +collectibles.876="Niille, jotka pitävät raasta lihasta!" +collectibles.877="Kokolihapihvi" +collectibles.878="Hyvin valmistettu ja maustettu." +collectibles.879="Kaivettu maasta." +collectibles.880="Hhyyiiii!" +collectibles.881="VAROITUS: Äärimmäisen kuumaa!" +collectibles.882="Puhdistettua." +collectibles.883="Maito" +collectibles.884="Täysmaitoa." +collectibles.885="Erittäin kuumaa!" +collectibles.886="Puinen tikku" +collectibles.887="Pallo" +collectibles.888="Pomppii ja pyörii!" +collectibles.889="Talutushihna" +collectibles.890="Lähdetäänpä kävelylle!" +collectibles.891="Kuti, kuti!" +collectibles.892="NOUDA!" +collectibles.893="Harjoittelumiekka" +collectibles.894="En garde!" +collectibles.895="Hän pitää siitä!" +collectibles.896="Hän todella pitää siitä!" +collectibles.897="Kypärä" +collectibles.898="Perimmäinen muodonmuutos! Käyttämällä näitä lobbyissa voit muuntautua erilaisiksi olennoiksi ja avata ainutlaatuisia voimia muiden ihailtaviksi!" +collectibles.899="Tue Hypixeliä näillä erityisillä Companioneilla - useimmat niistä on avattavissa Hypixel Storesta! Kuinka monta saat kerättyä itsellesi?" +collectibles.900="Vähintään yhden lemmikeistäsi on oltava Onnellinen tehdäksesi tuon." +collectibles.901="Poistettiin lemmikki: %%type%%!" +collectibles.902="Jo valittu!" +collectibles.903="%%name%% (Sivu %%page%%/%%size%%)" +collectibles.904="Lumiukko tehtäisiinkös? Oikeaklikkaa aloittaaksesi lumiukon rakentaminen, jatka klikkailua rakentaaksesi aaaaaivan ylös asti." +collectibles.905="Kaikkialta Euroopasta löytyvä perinteinen paukkukaramelli! Oikeaklikkaa toista pelaajaa avataksesi karamellin tämän kanssa; toinen tai molemmat teistä saavat jouluisen vitsin!" +collectibles.906="Menneet ovat menneitä, ja nyt puhaltavat uudet tuulet! Juhli vuoden vaihtumista tällä Uudenvuoden lähtölaskenta -vempaimella." +collectibles.907="Kurpitsapiirasta. Kurpitsakeittoa. Kurpitsamaustetta. Ja nyt, Kurpitsakanuuna! Valaise jonkun elämää tällä monipuolisella vihanneksella." +collectibles.908="Karkki vai kepponen?! Käytä tätä vempainta toiseen pelaajaan antaaksesi hänen valita kiva karkki... tai kauhea kepponen!" +collectibles.909="Aurinkovoimapuku Akun tila: %%charge%%" +collectibles.910="Animoidut hatut" +collectibles.911="Nämä edistyksellisemmät hatut liikkuvat, kun ne ovat päässäsi." +collectibles.912="Oikeaklikkaa lumiukkoa uudelleen jatkaaksesi rakentamista!" +collectibles.913="Ender Steve -hattu" +collectibles.914="Timanttinen Steve -hattu" +collectibles.915="Kultainen Steve -hattu" +collectibles.916="Rautainen Steve -hattu" +collectibles.917="Kivinen Steve -hattu" +collectibles.918="Puinen Steve -hattu" +collectibles.919="Ender Dragonling -hattu" +collectibles.920="Jääkarhuhattu" +collectibles.921="Koalahattu" +collectibles.922="Lintuhattu" +collectibles.923="Mehiläishattu" +collectibles.924="Vuokkokalahattu" +collectibles.925="Frettihattu" +collectibles.926="Mursuhattu" +collectibles.927="Apinahattu" +collectibles.928="Kaktushattu" +collectibles.929="Hampurilaishattu" +collectibles.930="Monitorihattu" +collectibles.931="Rantapallohattu" +collectibles.932="Ankkahattu" +collectibles.933="Maapallohattu" +collectibles.934="\"A\"-hattu" +collectibles.935="\"B\"-hattu" +collectibles.936="\"C\"-hattu" +collectibles.937="\"D\"-hattu" +collectibles.938="\"E\"-hattu" +collectibles.939="\"F\"-hattu" +collectibles.940="\"G\"-hattu" +collectibles.941="\"H\"-hattu" +collectibles.942="\"I\"-hattu" +collectibles.943="\"J\"-hattu" +collectibles.944="\"K\"-hattu" +collectibles.945="\"L\"-hattu" +collectibles.946="\"M\"-hattu" +collectibles.947="\"N\"-hattu" +collectibles.948="\"O\"-hattu" +collectibles.949="\"P\"-hattu" +collectibles.950="\"Q\"-hattu" +collectibles.951="\"R\"-hattu" +collectibles.952="\"S\"-hattu" +collectibles.953="\"T\"-hattu" +collectibles.954="\"U\"-hattu" +collectibles.955="\"V\"-hattu" +collectibles.956="\"W\"-hattu" +collectibles.957="\"X\"-hattu" +collectibles.958="\"Y\"-hattu" +collectibles.959="\"Z\"-hattu" +collectibles.960="\"0\"-hattu" +collectibles.961="\"1\"-hattu" +collectibles.962="\"2\"-hattu" +collectibles.963="\"3\"-hattu" +collectibles.964="\"4\"-hattu" +collectibles.965="\"5\"-hattu" +collectibles.966="\"6\"-hattu" +collectibles.967="\"7\"-hattu" +collectibles.968="\"8\"-hattu" +collectibles.969="\"9\"-hattu" +collectibles.970="\"+\"-hattu" +collectibles.971="\"#\"-hattu" +collectibles.972="\"?\"-hattu" +collectibles.973="\"!\"-hattu" +collectibles.974="Pyrypallohattu" +collectibles.975="Leivänpaahdinhattu" +collectibles.976="Munapäähattu" +collectibles.977="Voileipähattu" +collectibles.978="Juustohattu" +collectibles.979="Marshattu" +collectibles.980="Pingviinihattu" +collectibles.981="Norsuhattu" +collectibles.982="Kalmarihattu" +collectibles.983="Hevoshattu" +collectibles.984="Astronauttihattu" +collectibles.985="Klovnihattu" +collectibles.986="Groopo-hattu" +collectibles.987="Shibahattu" +collectibles.988="Haltiaprinsessahattu" +collectibles.989="Saukkohattu" +collectibles.990="Dinosaurushattu" +collectibles.991="Muumiohattu" +collectibles.992="Örkkihattu" +collectibles.993="Minotauros-hattu" +collectibles.994="Demoniritarihattu" +collectibles.995="Keräilijähattu" +collectibles.996="Kultainen ritari -hattu" +collectibles.997="Valkoinen velho -hattu" +collectibles.998="Kaivoshattu" +collectibles.999="Jalkapallotähden hattu" +collectibles.1000="Munkkihattu" +collectibles.1001="Metsähaltiahattu" +collectibles.1002="Kuolleen merirosvon hattu" +collectibles.1003="Odin-hattu" +collectibles.1004="Salamurhaajakyläläishattu" +collectibles.1005="Alien-etanahattu" +collectibles.1006="Kummitushattu" +collectibles.1007="Variksenpelättihattu" +collectibles.1008="Egyptiläinen kuningatar -hattu" +collectibles.1009="Maagihattu" +collectibles.1010="Kettuhattu" +collectibles.1011="Sateenkaarihäiriöhattu" +collectibles.1012="Kallohattu" +collectibles.1013="Possuzombin hattu" +collectibles.1014="Ghast-hattu" +collectibles.1015="Karkkitankohattu" +collectibles.1016="Pipariukkohattu" +collectibles.1017="Punainen joulupallohattu" +collectibles.1018="Joululahjahattu" +collectibles.1019="Kilpikonnahattu" +collectibles.1020="Hp8-hattu" +collectibles.1021="Sammakkohattu" +collectibles.1022="Papukaijahattu" +collectibles.1023="Valkoinen mopsihattu" +collectibles.1024="Musta mopsihattu" +collectibles.1025="Pöllöhattu" +collectibles.1026="Pandahattu" +collectibles.1027="Ankanpoikahattu" +collectibles.1028="Laiskiaishattu" +collectibles.1029="Gorillahattu" +collectibles.1030="Taikakoirahattu" +collectibles.1031="Onnenlohikäärmehattu" +collectibles.1032="Hypixelin H -hattu" +collectibles.1033="Ilkeä kurpitsahattu" +collectibles.1034="Marionettihattu" +collectibles.1035="Lumiukkohattu" +collectibles.1036="Porohattu" +collectibles.1037="Lahjanantajan hattu" +collectibles.1038="Ylävitonen-ele" +collectibles.1039="Balettitanssiele" +collectibles.1040="Riivattu-ele" +collectibles.1041="Lumipallonheittoele" +collectibles.1042="Voittoposeerausele" +collectibles.1043="Pää räjähtää -ele" +collectibles.1044="Can-can-tanssiele" +collectibles.1045="Hulatanssiele" +collectibles.1046="Hypi ympäriinsä -ele" +collectibles.1047="Aurinkotervehdysele" +collectibles.1048="Kaiva aarretta -ele" +collectibles.1049="Zombitanssiele" +collectibles.1050="Onko sinusta koskaan tuntunut siltä kuin et olisi aivan oma itsesi? Luovuta itsesi aaveille tällä Riivattu-eleellä!" +collectibles.1051="Pimeyden laskeutuessa maan ylle ja keskiyön tuntien lähestyessä zombit tanssivat etsien verta, terrorisoidakseen naapurustoasi!" +collectibles.1052="Jos tuijotat liian pitkään pimeyteen, pimeys saattaa tuijottaa takaisin!" +collectibles.1053="Anna kavereillesi paras lahja, jonka he voisivat saada: SINUT! Aktivoi tämä Lahjan avaus -emote." +collectibles.1054="Sloth" +collectibles.1055="HP8" +collectibles.1056="Nämä pikku kaverit seuraavat maailman anteliainta ihmistä, ja sehän oletkin sinä!" +collectibles.1057="Animoitu Vesipallohattu" +collectibles.1058="Animoitu Koripallohattu" +collectibles.1059="Animoitu Tulidemonihattu" +collectibles.1060="Animoitu Metsänhoitajahattu" +collectibles.1061="Animoitu Jäävelhohattu" +collectibles.1062="Animoitu Robolintuhattu" +collectibles.1063="Animoitu Seireenihattu" +collectibles.1064="Animoitu Liikennevalohattu" +collectibles.1065="Animoitu Avaruushattu" +collectibles.1066="Animoitu Ihmissusihattu" +collectibles.1067="Animoitu Variksenpelätinhattu" +collectibles.1068="Animoitu Haltiapoikahattu" +collectibles.1069="Animoitu Haltiatyttöhattu" +collectibles.1070="Animoitu Golem-hattu" +collectibles.1071="Animoitu Rikkinäinen TV -hattu" +collectibles.1072="Animoitu Joulupallohattu" +collectibles.1073="Animoitu Pipariukkohattu" +collectibles.1074="Animoitu Paha silmä -hattu" +collectibles.1075="Animoitu Pellehattu" +collectibles.1076="Animoitu Joulupukin hattu" +collectibles.1077="Animoitu Ketunhenkihattu" +collectibles.1078="Animoitu Mustavalkoinen tyttö -hattu" +collectibles.1079="Animoitu Huiviheppuhattu" +collectibles.1080="Animoitu Kyborgityttöhattu" +collectibles.1081="Animoitu Herobrine-hattu" +collectibles.1082="Animoitu Kromalimahattu" +collectibles.1083="Animoitu Iloinen kaveri -hattu" +collectibles.1084="Animoitu Punastushattu" +collectibles.1085="Animoitu Partiolaistyttöhattu" +collectibles.1086="Animoitu Kukkaiskruunuhattu" +collectibles.1087="Animoitu Punahaalarihattu" +collectibles.1088="Animoitu Sininen huppari -hattu" +collectibles.1089="Animoitu Ender-pulssi -hattu" +collectibles.1090="Animoitu Sateenkaarityttöhattu" +collectibles.1091="Animoitu Demonisilmät-hattu" +collectibles.1092="Animoitu Hassut silmät -hattu" +collectibles.1093="Hypixel-viiri" +collectibles.1094="Lumikaniviiri" +collectibles.1095="Poroviiri" +collectibles.1096="Joulukuusiviiri" +collectibles.1097="Joulupukkiviiri" +collectibles.1098="Joulukranssiviiri" +collectibles.1099="Sydänviiri" +collectibles.1100="Kitaraviiri" +collectibles.1101="Dinoviiri" +collectibles.1102="Redpool-viiri" +collectibles.1103="Pinguviiri" +collectibles.1104="Kallokuningasviiri" +collectibles.1105="Uudenvuodenjuhlapuku" +collectibles.1106="Companionit" +collectibles.1107="On Halloween, hienojen pukujen aika - miksi valita yksi karmiva kostyymi kun voit ottaa ne kaikki?" +collectibles.1108="Tämä asu vaihtaa nopeasti erilaisten karmivien pukujen välillä." +collectibles.1109="Juhlista taas yhden hullun vuoden päätöstä tällä Uudenvuodenjuhlapuvulla!" +collectibles.1110="Lyö ampuaksesi ilotulitteen." +collectibles.1111="Eiväthän kaikki voi rakastaa joulua! Kerää tämä koko asu ja muutu ilkeäksi Grinchiksi." +collectibles.1112="Lyö luodaksesi lahjoja, jotka muuttuvat hiiliksi." +collectibles.1113="Muodonmuutoksesi päättyy %%seconds%% kuluttua" +collectibles.1114="%%name%% kypärä" +collectibles.1115="%%name%% rintapanssari" +collectibles.1116="%%name%% housut" +collectibles.1117="%%name%% kengät" +collectibles.1118="Hoppin Blocks" +collectibles.1119="Happy" +collectibles.1120="Corpse Party" +collectibles.1121="Kirby's Gourmet Race" +collectibles.1122="Gamemode 8" +collectibles.1123="Bad Apple" +collectibles.1124="Similar" +collectibles.1125="Aztec Dash" +collectibles.1126="Chased By Creeper" +collectibles.1127="Victory" +collectibles.1128="Voting" +collectibles.1129="Pump It Up" +collectibles.1130="Suspenseful" +collectibles.1131="Interdimensional" +collectibles.1132="Feels" +collectibles.1133="Olympus" +collectibles.1134="Lobby Song" +collectibles.1135="Minecraft Is My Life" +collectibles.1136="Entertainer" +collectibles.1137="Taso " +collectibles.1138="RIKKI" +collectibles.1139="OtusPyssy-vempain" +collectibles.1140="Kieri-vempain" +collectibles.1141="iPixel-vempain" +collectibles.1142="Cowboyvempain" +collectibles.1143="Pyromaanivempain" +collectibles.1144="Kun possut lentävät -vempain" +collectibles.1145="Teleporttitikkuvempain" +collectibles.1146="Maaginen 9-pallovempain" +collectibles.1147="Kissakatapulttivempain" +collectibles.1148="Timanttisuihkuvempain" +collectibles.1149="Kultasuihkulähdevempain" +collectibles.1150="Kawarimi no Jutsu -vempain" +collectibles.1151="Sädeasevempain" +collectibles.1152="Jääputkivempain" +collectibles.1153="Trampoliinivempain" +collectibles.1154="Ponnahduslautavempain" +collectibles.1155="Hypixel Radio -vempain" +collectibles.1156="Värikuula-asevempain" +collectibles.1157="Räjähdejousivempain" +collectibles.1158="Onnenkeksivempain" +collectibles.1159="Maalivanavempain" +collectibles.1160="Räjähtävä lammas -vempain" +collectibles.1161="Tulivanavempain" +collectibles.1162="Creeper-astronauttivempain" +collectibles.1163="Kummitusvempain" +collectibles.1164="Heittokoukkuvempain" +collectibles.1165="Rakettireppuvempain" +collectibles.1166="Salainen palvelu -vempain" +collectibles.1167="Laskuvarjovempain" +collectibles.1168="Konfettitykkivempain" +collectibles.1169="Kakkapommivempain" +collectibles.1170="Salkopallovempain" +collectibles.1171="Diskopallovempain" +collectibles.1172="Kauhuelokuvavempain" +collectibles.1173="Tennispallovempain" +collectibles.1174="Teleportterivempain" +collectibles.1175="Taikamattovempain" +collectibles.1176="TNT Wizards -taikasauvavempain" +collectibles.1177="Meteoriittivempain" +collectibles.1178="Rakettivempain" +collectibles.1179="TNT-suihkulähdevempain" +collectibles.1180="Sateenkaarivempain" +collectibles.1181="DJ-koppivempain" +collectibles.1182="Vesi-ilmapallovempain" +collectibles.1183="Noppavempain" +collectibles.1184="Kannettava hiekkaranta -vempain" +collectibles.1185="Frisbeevempain" +collectibles.1186="Rantapallovempain" +collectibles.1187="Ristinollavempain" +collectibles.1188="Hiekkalinnavempain" +collectibles.1189="Grillivempain" +collectibles.1190="Kanatykkivempain" +collectibles.1191="Jäätelökojuvempain" +collectibles.1192="Kukanlahjoittajavempain" +collectibles.1193="MCProHosting-ilotulitevempain" +collectibles.1194="Keksisuihkulähdevempain" +collectibles.1195="Lepakkolaukaisin-vempain" +collectibles.1196="Variksenpelätinvempain" +collectibles.1197="Lunta saa tuiskuttaa -vempain" +collectibles.1198="Joulukuorovempain" +collectibles.1199="Joulukuusivempain" +collectibles.1200="SkyWars Ranked -viirivempain" +collectibles.1201="Karkki vai kepponen -vempain" +collectibles.1202="Kurpitsakanuunavempain" +collectibles.1203="Uusi vuosi -vempain" +collectibles.1204="Paukkukaramellivempain" +collectibles.1205="Lumiukkovempain" +collectibles.1206="Itkuemote" +collectibles.1207="Uninen-emote" +collectibles.1208="Raivoemote" +collectibles.1209="Suruemote" +collectibles.1210="Hymyemote" +collectibles.1211="Nenäkäs-emote" +collectibles.1212="Cool-emote" +collectibles.1213="Silmäniskuemote" +collectibles.1214="Virnistysemote" +collectibles.1215="Yllättynyt-emote" +collectibles.1216="Rusketusemote" +collectibles.1217="Sydänsilmät-emote" +collectibles.1218="Pahoinvoiva-emote" +collectibles.1219="RIP-emote" +collectibles.1220="Rentoutunut-emote" +collectibles.1221="Tulinen-emote" +collectibles.1222="Deal with it -emote" +collectibles.1223="Viikset-emote" +collectibles.1224="Pisteet:" +collectibles.1225="Sammakkopuvun pääkappale" +collectibles.1226="Sammakkopuvun rintakappale" +collectibles.1227="Sammakkopuvun housut" +collectibles.1228="Sammakkopuvun kengät" +collectibles.1229="Ninjapuvun pääkappale" +collectibles.1230="Ninjapuvun rintakappale" +collectibles.1231="Ninjapuvun housut" +collectibles.1232="Ninjapuvun kengät" +collectibles.1233="Vauhtiveikon asun pääkappale" +collectibles.1234="Vauhtiveikon asun rintakappale" +collectibles.1235="Vauhtiveikon asun housut" +collectibles.1236="Vauhtiveikon asun kengät" +collectibles.1237="Aavemaisen luurankopuvun pääkappale" +collectibles.1238="Aavemaisen luurankopuvun rintakappale" +collectibles.1239="Aavemaisen luurankopuvun housut" +collectibles.1240="Aavemaisen luurankopuvun kengät" +collectibles.1241="Diskopuvun kypärä" +collectibles.1242="Diskopuvun rintakappale" +collectibles.1243="Diskopuvun housut" +collectibles.1244="Diskopuvun kengät" +collectibles.1245="Merenneitopuvun pääkappale" +collectibles.1246="Merenneitopuvun rintakappale" +collectibles.1247="Merenneitopuvun housut" +collectibles.1248="Merenneitopuvun kengät" +collectibles.1249="Spooderman-puvun pääkappale" +collectibles.1250="Spooderman-puvun rintakappale" +collectibles.1251="Spooderman-puvun housut" +collectibles.1252="Spooderman-puvun kengät" +collectibles.1253="Soturipuvun pääkappale" +collectibles.1254="Soturipuvun rintakappale" +collectibles.1255="Soturipuvun housut" +collectibles.1256="Soturipuvun kengät" +collectibles.1257="Nekromantikon puvun pääkappale" +collectibles.1258="Nekromantikon puvun rintakappale" +collectibles.1259="Nekromantikon puvun housut" +collectibles.1260="Nekromantikon puvun kengät" +collectibles.1261="Thor-puvun pääkappale" +collectibles.1262="Thor-puvun rintakappale" +collectibles.1263="Thor-puvun housut" +collectibles.1264="Thor-puvun kengät" +collectibles.1265="Kuoleman enkelin puvun pääkappale" +collectibles.1266="Kuoleman enkelin puvun rintakappale" +collectibles.1267="Kuoleman enkelin puvun housut" +collectibles.1268="Kuoleman enkelin puvun kengät" +collectibles.1269="Leipuripuvun pääkappale" +collectibles.1270="Leipuripuvun rintakappale" +collectibles.1271="Leipuripuvun housut" +collectibles.1272="Leipuripuvun kengät" +collectibles.1273="Kimalaispuvun pääkappale" +collectibles.1274="Kimalaispuvun rintakappale" +collectibles.1275="Kimalaispuvun housut" +collectibles.1276="Kimalaispuvun kengät" +collectibles.1277="Palomiehen puvun pääkappale" +collectibles.1278="Palomiehen puvun rintakappale" +collectibles.1279="Palomiehen puvun housut" +collectibles.1280="Palomiehen puvun kengät" +collectibles.1281="Jääkävelijän puvun pääkappale" +collectibles.1282="Jääkävelijän puvun rintakappale" +collectibles.1283="Jääkävelijän puvun housut" +collectibles.1284="Jääkävelijän puvun kengät" +collectibles.1285="Vampyyripuvun pääkappale" +collectibles.1286="Vampyyripuvun rintakappale" +collectibles.1287="Vampyyripuvun housut" +collectibles.1288="Vampyyripuvun kengät" +collectibles.1289="Lohikäärmeen henkäys -puvun pääkappale" +collectibles.1290="Lohikäärmeen henkäys -puvun rintakappale" +collectibles.1291="Lohikäärmeen henkäys -puvun housut" +collectibles.1292="Lohikäärmeen henkäys -puvun kengät" +collectibles.1293="Merirosvopuvun pääkappale" +collectibles.1294="Merirosvopuvun rintakappale" +collectibles.1295="Merirosvopuvun housut" +collectibles.1296="Merirosvopuvun kengät" +collectibles.1297="TNT-puvun pääkappale" +collectibles.1298="TNT-puvun rintakappale" +collectibles.1299="TNT-puvun housut" +collectibles.1300="TNT-puvun kengät" +collectibles.1301="Susiprinsessapuvun pääkappale" +collectibles.1302="Susiprinsessapuvun rintakappale" +collectibles.1303="Susiprinsessapuvun housut" +collectibles.1304="Susiprinsessapuvun kengät" +collectibles.1305="Aurinkovoimapuvun kypärä" +collectibles.1306="Aurinkovoimapuvun rintakappale" +collectibles.1307="Aurinkovoimapuvun housut" +collectibles.1308="Aurinkovoimapuvun kengät" +collectibles.1309="Jalkapallopelaajan asun pääkappale" +collectibles.1310="Jalkapallopelaajan asun paita" +collectibles.1311="Jalkapallopelaajan asun housut" +collectibles.1312="Jalkapallopelaajan asun kengät" +collectibles.1313="Joulupukin puvun pääkappale" +collectibles.1314="Joulupukin puvun rintakappale" +collectibles.1315="Joulupukin puvun housut" +collectibles.1316="Joulupukin puvun kengät" +collectibles.1317="Lelusotilaspuvun pääkappale" +collectibles.1318="Lelusotilaspuvun rintakappale" +collectibles.1319="Lelusotilaspuvun housut" +collectibles.1320="Lelusotilaspuvun kengät" +collectibles.1321="Yllätyslahjapuvun kypärä" +collectibles.1322="Yllätyslahjapuvun rintakappale" +collectibles.1323="Yllätyslahjapuvun housut" +collectibles.1324="Yllätyslahjapuvun kengät" +collectibles.1325="Aarteenmetsästäjän puvun pääkappale" +collectibles.1326="Aarteenmetsästäjän puvun rintakappale" +collectibles.1327="Aarteenmetsästäjän puvun housut" +collectibles.1328="Aarteenmetsästäjän puvun kengät" +collectibles.1329="Naamiaisasun pääkappale" +collectibles.1330="Naamiaisasun rintakappale" +collectibles.1331="Naamiaisasun housut" +collectibles.1332="Naamiaisasun kengät" +collectibles.1333="Uudenvuodenjuhlapuvun pääkappale" +collectibles.1334="Uudenvuodenjuhlapuvun rintakappale" +collectibles.1335="Uudenvuodenjuhlapuvun housut" +collectibles.1336="Uudenvuodenjuhlapuvun kengät" +collectibles.1337="Grinch-asun pääkappale" +collectibles.1338="Grinch-asun rintakappale" +collectibles.1339="Grinch-asun housut" +collectibles.1340="Grinch-asun kengät" +collectibles.1341="Lahjan avaus -emote" +collectibles.1342="Sulava naama -emote" +collectibles.1343="Ei saatavilla" +collectibles.1344="Tämä esine ei ole saatavilla." +collectibles.1345="Syötä" +collectibles.1346="hakusanasi!" +collectibles.1347="%%name%% heitti numeron %%result%%!" +collectibles.1348="Klikkaa hyväksyäksesi paukkukaramellin." +collectibles.1349="Klikkaa hylätäksesi paukkukaramellin." +collectibles.1350="**KRÄKS** Paukkukaramelli repesi kahtia!" +collectibles.1351="Kauden 6 viiri" +collectibles.1352="Kauden 6 viiri" +collectibles.1353="Kauden 7 viiri" +collectibles.1354="Kauden 7 viiri" +collectibles.1355="Kauden 8 viiri" +collectibles.1356="Kauden 8 viiri" +collectibles.1357="Kauden 9 viiri" +collectibles.1358="Kauden 9 viiri" +collectibles.1359="Kauden 10 viiri" +collectibles.1360="Kauden 10 viiri" +collectibles.1361="Kauden 11 viiri" +collectibles.1362="Kauden 11 viiri" +collectibles.1363="Kauden 12 viiri" +collectibles.1364="Kauden 12 viiri" +collectibles.1365="Kauden 13 viiri" +collectibles.1366="Kauden 13 viiri" +collectibles.1367="Kauden 14 viiri" +collectibles.1368="Kauden 14 viiri" +collectibles.1369="Kauden 15 viiri" +collectibles.1370="Kauden 15 viiri" +collectibles.1371="Kauden 16 viiri" +collectibles.1372="Kauden 16 viiri" +collectibles.1373="Kauden 17 viiri" +collectibles.1374="Kauden 17 viiri" +collectibles.1375="Kauden 18 viiri" +collectibles.1376="Kauden 18 viiri" +collectibles.1377="Kauden 19 viiri" +collectibles.1378="Kauden 19 viiri" +collectibles.1379="Kauden 20 viiri" +collectibles.1380="Kauden 20 viiri" +collectibles.1381="Kauden 21 viiri" +collectibles.1382="Kauden 21 viiri" +collectibles.1383="Lisää suosikkeihin" +collectibles.1384="Poista suosikeista" +collectibles.1385="Klikkaa poistaaksesi tämän lemmikin suosikeistasi." +collectibles.1386="Lemmikinhoitotarvikkeet" +collectibles.1387="Sait pussillisen karkkeja, jotka kuitenkin olivat vanhentuneet!" +collectibles.1388="Sait paloauton, mutta se paloi poroksi!" +collectibles.1389="Sait radio-ohjattavan auton, mutta siitä loppuivat paristot!" +collectibles.1390="Sait keijukaisnuken, mutta se lensi pois!" +collectibles.1391="Sait pyörän, mutta sen kumit ovat puhjenneet!" +collectibles.1392="Sait pehmokoiran, mutta sitä ei ole kesytetty!" +collectibles.1393="Sait sähikäisiä, mutta ne kaikki räjähtivät!" +collectibles.1394="Sait sukkaparin, siis juuri sen mitä halusitkin!" +collectibles.1395="Tekijä: %%author%%" +collectibles.1396="Oikeaklikkaa pelaajaa antaaksesi tälle paukkukaramellin!" +collectibles.1397="Yrität jo lähettää paukkukaramellia pelaajalle %%name%%." +collectibles.1398="Lähetit paukkukaramellin pelaajalle %%name%%!" +collectibles.1399="%%name%% antoi sinulle paukkukaramellin!" +collectibles.1400="Wäääää!" +collectibles.1401="zzzZZZZZZ" +collectibles.1402="GRRRRR!!!" +collectibles.1403="niisk" +collectibles.1404="hymyä" +collectibles.1405=":P" +collectibles.1406="B)" +collectibles.1407="vink vink" +collectibles.1408="Jee!" +collectibles.1409="OMG" +collectibles.1410="Aurinkoista" +collectibles.1411="❤_❤" +collectibles.1412="x_x" +collectibles.1413="Rest In Pepperoni" +collectibles.1414="Huh" +collectibles.1415="Polttaa!" +collectibles.1416="Deal with it ;)" +collectibles.1417="Miten komeat!" +collectibles.1418="MINÄ SULANNNNN!" +collectibles.1419="❄" +collectibles.1420="Kuin olisit Times Squarella..." +collectibles.1421="Se tapahtuu vain kerran vuodessa..." +collectibles.1422="Nopeasti, tee uudenvuodenlupauksia" +collectibles.1423="Oikeaklikkaa pelaajaa kysyäksesi tältä \"Karkkia vai kepponen?\"!" +collectibles.1424="Olet koputtanut liian monelle ovelle, odota hetki ennen kuin teet niin uudelleen!" +collectibles.1425="Et voi koputtaa tämän pelaajan ovelle." +collectibles.1426="Olet jo koputtanut pelaajan %%name%% ovelle." +collectibles.1427="Koputit pelaajan %%name%% ovelle ja kysyit: \"Karkki vai kepponen?\"" +collectibles.1428="%%name%% kysyy \"Karkki vai kepponen?\"" +collectibles.1429="[KEPPONEN] " +collectibles.1430="[KARKKI] " +collectibles.1431="[HYLKÄÄ] " +collectibles.1432=" Valitsit vaihtoehdon %%subType%%!" +collectibles.1433="Tämä pelaaja ei ole enää ovellasi." +collectibles.1434="Suljit oven kun %%name%% oli sen takana." +collectibles.1435="Kukaan ei ole ollut ovesi takana, tai hän lähti jo." +collectibles.1436="%%name%% ei vastannut koputukseesi." +collectibles.1437="Et vastannut pelaajan %%name%% koputukseen." +collectibles.1438="%%name%% valitsi vaihtoehdon %%subType%%!" +collectibles.1439="Väärä käyttötapa." +collectibles.1440="OIKEAKLIKKAA" +collectibles.1441="Kauden 1 viiri" +collectibles.1442="Lemmikkisi %%color%%%%pet%% söi ruoan %%name%%." +collectibles.1443="Lemmikkisi %%color%%%%pet%% söi ruoan %%name%%." +collectibles.1444="Lemmikkisi %%color%%%%pet%% joi juoman %%name%%." +collectibles.1445="Lemmikkisi %%color%%%%pet%% joi juoman %%name%%." +collectibles.1446="Lemmikkisi %%color%%%%pet%% leikki esineellä %%name%%." +collectibles.1447="Lemmikkisi %%color%%%%pet%% leikki esineellä %%name%%." +collectibles.1448="Nollaa viiri" +collectibles.1449="ampua nuolia" +collectibles.1450="Vartija" +collectibles.1451="Superonnellinen" +collectibles.1452="Superonnellinen" +collectibles.1453="Onnellinen" +collectibles.1454="Okei" +collectibles.1455="Nollaa %%name%%" +collectibles.1456="Luo keinuvin kaikista keinuista." +collectibles.1457="Aloita hype-juna! Lennä ilmassa ja odota että muut pelaajat liittyvät mukaasi klikkaamalla junaa." +collectibles.1458="Pelaajia Hype-junassasi: %%count%%" +collectibles.1459="Sinulla on jo Pong-pallo käytössä!" +collectibles.1460="Pelaajia pelaajan %%name%% Hype-junassa: %%count%%" +collectibles.1461="Ammu pong-pallo eteesi. Kuka tahansa voi lyödä palloa pitääkseen sen ilmassa!" +collectibles.1462="pelaajan %%player%% Pong: %%count%% osuma" +collectibles.1463="pelaajan %%player%% Pong: %%count%% osumaa" +collectibles.1464="Lopulliset pisteet:" +collectibles.1465="Et voi käyttää vempaimia juuri nyt!" +collectibles.1466="Oikeaklikkaa pelaajaa aloittaaksesi Kivi, paperi, keritsimet -pelin hänen kanssaan!" +collectibles.1467="Haasta ystäväsi kivi, paperi, keritsimet -peliin. Kuka onkaan (onnekas) voittaja?" +collectibles.1468="Tätä kutsua ei ole olemassa tai se on vanhentunut!" +collectibles.1469="Olet jo pelissä!" +collectibles.1470="Kivi, paperi, keritsimet - %%target%%" +collectibles.1471="Vasen: %%name%%" +collectibles.1472="Oikea: %%name%%" +collectibles.1473="Vasemmanpuoleinen pelaaja on %%name%%" +collectibles.1474="Oikeanpuoleinen pelaaja on %%name%%" +collectibles.1475="Valitsit: %%choice%%" +collectibles.1476="Paljastetaan..." +collectibles.1477="Vastustajasi valitsi: %%choice%%" +collectibles.1478="Matkaa ympäri lobbya tällä erityisellä ender-helmellä!" +collectibles.1479="Valitsit %%name%%!" +collectibles.1480="%%who%% valitsi %%name%%!" +collectibles.1481="Voitit Kivi, paperi, keritsimet -pelin pelaajaa %%opponent%% vastaan!" +collectibles.1482="Hävisit Kivi, paperi, keritsimet -pelin." +collectibles.1483="Tasapeli!" +collectibles.1484="Olet jo kutsunut pelaajan %%player%% Kivi, paperi, keritsimet -peliin." +collectibles.1485="Sinun täytyy odottaa %%time%% ennen kuin voit käyttää tätä kykyä." +collectibles.1486="Haluatko onnitella jotakuta hyvästä pelistä? Aktivoi vain Taputusele!" +collectibles.1487="Näytä jäätävän siistejä liikkeitäsi - valtaa tanssilattia aktivoimalla Siisti tanssi -ele!" +collectibles.1488="Tunnetko ylpeyttä? Juhli tyylillä ja aktivoi tämä Voittoposeerausele!" +collectibles.1489="Lähdit sitten kokonaan pois tai vaihdoit vain lobbya, jätä hyvästit tällä Näkemiin-eleellä!" +collectibles.1490="Oletko vähän liiankin innoissasi? Hankkiudu eroon ylimääräisestä energiasta aktivoimalla tämä Hypi ympäriinsä -ele!" +collectibles.1491="Nostakaa kaikki kädet korkealle ilmaan! Innosta itseäsi ja muita aktivoimalla tämä Hype Dance -ele!" +collectibles.1492="Sulje silmäsi, nyökytä päätäsi ja liiku musiikin tahtiin aktivoimalla tämä Aaltotanssiele!" +collectibles.1493="Jos haluat tanssia... miksi et kokeilisi Raputanssia? Woop woop woop vain ympäri lobbya tällä Raputanssieleellä!" +collectibles.1494="Tunnetko iloa ja lämpöä? Juhli kesää tällä Aurinkotervehdyseleellä! Kunpa vain voisimme ollakin niin törkeän loistavia..." +collectibles.1495="Olet ryöstänyt hautoja, tutkinut kartoittamattomia alueita, ja nyt olet valmis keräämään rikkautesi tällä Kaiva aarretta -eleellä!" +collectibles.1496="Ei häntä ei huvita tehdä lumiukkoja ... äläkä sano hänelle \"Taakse jää!\"." +collectibles.1497="Metsän suojelijana se, joka käyttää Susiprinsessapukua, voi kutsua eläinliittolaisensa koolle." +collectibles.1498="Uiminen on mukavaa... kunhan kukaan ei roiskuta vettä päällesi. Esittele sisäistä vesipetoasi tällä Ponnahduslautavempaimella." +collectibles.1499="Antaa sinulle Nopeus II -vaikutuksen ja jättää tulisen vanan taaksesi." +collectibles.1500="Poistuit Kivi, paperi, keritsimet -pelistä!" +collectibles.1501="Vastustajasi poistui Kivi, paperi, keritsimet -pelistä!" +collectibles.1502="Jos nimi ei kerro tarpeeksi, tämä on pommi, joka räjähtäessään levittää kakkaa joka paikkaan. Jep." +collectibles.1503="Tämä kesä tosiaan on lämmin! Vilvoitellaan yhdessä heittelemällä toisiamme vesi-ilmapalloilla!" +collectibles.1504="Oletko surullinen kun et voi pelata Hypixelissä koko ajan? Vuodata kyyneliä tällä animoidulla Itkuemotella!" +collectibles.1505="Olitko koko yön hereillä pelaamassa suosikkiminipeliäsi? Nukahda tällä animoidulla Uninen-emotella!" +collectibles.1506="Kiehuttaako jokin vertasi? Päästä höyryt ulos tällä animoidulla Raivoemotella!" +collectibles.1507="Onko mieli maassa? Anna koko maailman tietää se tällä Suruemotella!" +collectibles.1508="Kaikki on mahtavaa? Näytä maailmalle koko onnesi tällä animoidulla Hymyemotella!" +collectibles.1509="Kujeita luvassa? Varoita kaikkia ajatuksistasi tällä animoidulla Nenäkäs-emotella!" +collectibles.1510="Oletko mielestäsi koko palvelimen siistein kaveri? Astele ylväästi tällä animoidulla Cool-emotella!" +collectibles.1511="Onko hauskaa? Kerro kaikille parhaat vitsisi tällä animoidulla Silmäniskuemotella!" +collectibles.1512="Onko kaikki mahtavaa? Eipä olisi parempaa tapaa näyttää sitä kuin tämä animoitu Virnistys-emote!" +collectibles.1513="Oletko järkyttynyt? Näytä se kaikille tässä lobbyssa tällä animoidulla Yllättynyt-emotella!" +collectibles.1514="Tason %%level%% lemmikkisi %%name%% ansaitsi %%exp%% pistettä lemmikkitehtävästä! Se nousi seuraavalle tasolle!" +collectibles.1515="Tason %%level%% lemmikkisi %%name%% ansaitsi %%exp%%pistettä lemmikkitehtävästä!" +collectibles.1516="Hän on muuttanut tänne etelänavalta saakka! Ystävysty tämän söpön Penguin companionin kanssa jo tänään." +collectibles.1517="Lumipallojen viskominen on talvipäivien ilo! Anna jollekulle kunnon lumipesu tällä Talvieleellä." +collectibles.1518="Voi viikset millaiset viikset! Esittele vetovoimaasi tällä herrasmiesmäisellä Viikset-emotella!" +collectibles.1519="Anna kavereillesi paras lahja, jonka he voisivat saada: SINUT! Aktivoi vain tämä Lahjan avaus -emote!" +collectibles.1520="Katoat ja ilmestyt toisaalle aivan silmän räpäyksessä. Matkusta aika-avaruudessa tällä Teleportterivempaimella." +collectibles.1521="Olen lähettänyt %%gifts%% lahjaa!" +collectibles.1522="Et voi käyttää tätä näin lähellä spawnia!" +collectibles.1523="Animoitu Avaruuden valloittaja -hattu" +collectibles.1524="Animoitu Pisterohmuhattu" +collectibles.1525="Animoitu Avaajakonehattu" +collectibles.1526="Klikkaa muokataksesi asua!" +collectibles.1527="Sadepäivä" +collectibles.1528="Se on kuin kannettava suihku." +collectibles.1529="Skanneri" +collectibles.1530="Bliip Bloop!" +collectibles.1531="Kivi, paperi, keritsimet" +collectibles.1532="Hype-juna" +collectibles.1533="Tätä ei voi pysäyttää!" +collectibles.1534="Pong" +collectibles.1535="Ender-helmi" +collectibles.1536="Sadepäivä-kaapu" +collectibles.1537="Skannerikaapu" +collectibles.1538="Kivi, paperi, keritsimet -vempain" +collectibles.1539="Hype-junavempain" +collectibles.1540="Pong-vempain" +collectibles.1541="Ender-helmivempain" +collectibles.1542="Avaruuden valloittaja" +collectibles.1543="Pisterohmu" +collectibles.1544="Avaajakone" +collectibles.1545="%%points%%K" +collectibles.1546="Näyttää keräämiesi Saavutuspisteiden määrän (1K = 1000)." +collectibles.1547="Haastetaan pelaajaa %%target%%" +collectibles.1548="Joulutodiste" +collectibles.1549="%%count%% Adventtipalkinto lunastettu" +collectibles.1550="%%count%% Adventtipalkintoa lunastettu" +collectibles.1551="Valitse pimeä puoli ja valvo koko Hypixelin Imperiumia tällä iloisella, lumella täytetyllä HP9-B6-robotilla." +collectibles.1552="HP9-B6" +collectibles.1553="Infrapunasilmä ja kiiltävä maalipinta; laajenna Hypixelin valtakuntaa kaikkiin lobbyihin tällä päivitetyllä HP9-B companionilla." +collectibles.1554="HP9-B" +collectibles.1555="Keinuvempain" +collectibles.1556="Keinu" +collectibles.1557="Pelaajia Hype-junassasi: %%count%%" +collectibles.1558="Kruunu" +collectibles.1559="Ahmatti" +collectibles.1560="Muurinpirstoja" +collectibles.1561="Deal with it -pupu" +collectibles.1562="Saavutuspisteet" +collectibles.1563="Et voi käyttää Rakettireppuvempainta!" +collectibles.1564="Et voi käyttää heittokoukkua!" +collectibles.1565="Kuollut merirosvo" +collectibles.1566="Kuolleen merirosvon hattu" +collectibles.1567="Piparkakku-ukko" +collectibles.1568="Pipariukkohattu" +collectibles.1569="Et voi teleportata lemmikkiäsi luoksesi, se jäisi palikan sisään jumiin!" +collectibles.1570="Et voi teleportata lemmikkisi luokse, jäisit palikan sisään jumiin!" +collectibles.1571="Et voi tehdä tätä näin lähellä spawnia." +collectibles.1572="Oikeaklikkaa huolehtiaksesi\ntai poistaaksesi suosikeista." +collectibles.1573="Oikeaklikkaa huolehtiaksesi\ntai lisätäksesi suosikkeihin." +collectibles.1574="Lähettää kaikki Onnelliset, Erittäin\nonnelliset ja Superonnelliset lemmikkisi\nhuippusalaiselle lemmikkitehtävälle, jotta\nne ansaitsisivat lemmikkipisteitä!" +collectibles.1575="Hypixelin miekka" +collectibles.1576="Salanimesi on edelleen ei-MVP+ joten et voi ratsastaa lemmikeillä! Käytä /unnick poistaaksesi salanimesi." +collectibles.1577="Kuuma peruna" +collectibles.1578="Neljän suora" +collectibles.1579="Säästöpossu" +collectibles.1580="Tämän vempaimen voi saada vain kampanjatarjouksena." +collectibles.1581="Emote" +collectibles.1582="Little You" +collectibles.1583="Meidän jokaisen sisällä on se pieni ääni, joka kertoo miten ajattelemme ja tunnemme. Tämä companion on se pieni ääni, ja se näyttää aivan sinulta!" +collectibles.1584="Kaapu" +collectibles.1585="Lumipallo suoraan kasvoihin on merkki pitkän ystävyyden alusta." +collectibles.1586="Guildisi tulisi olla 100 parhaan joukossa legacy guild -järjestelmässä!" +collectibles.1587="Avataan pelaamalla The Pitiä!" +collectibles.1588="Tämä esine avataan osallistumalla turnauksiin!" +collectibles.1589="Vempain" +collectibles.1590="Muodonmuutos" +collectibles.1591="Mini Wither" +collectibles.1592="jouluna!" +collectibles.1593="Sinun on oltava Guildissa, jonka taso on vähintään %%level%% käyttääksesi tätä esinettä." +collectibles.1594="Tyylikäs tapa erottautua joukosta. Itse asiassa, erottaudut joukosta niin paljon, että kaikki ympärilläsi alkavat lyödä sinua." +collectibles.1595="Arkkienkelikaapu" +collectibles.1596="Lumivyörykaapu" +collectibles.1597="Viiri" +collectibles.1598="Bliip Bloop! " +collectibles.1599="Ympäröi sinut yhdellä värillä kerrallaan." +collectibles.1600="Luo jalkoihisi Hypixel rankkisi plus-merkin värisiä partikkeleita. (oletuksena punainen)" +collectibles.1601="Pilvipartikkelipaketti" +collectibles.1602="Värilaatikkokaapu" +collectibles.1603="Kosmeettisia palkintoja kaikkein kilpailunhaluisimmille pelaajillemme." +collectibles.1604="Krittipartikkelipaketti" +collectibles.1605="Liekkipartikkelipaketti" +collectibles.1606="Guild-kaapu" +collectibles.1607="Iloitsetko voittoasi? Ylävitonen-eleellä voit näyttää, kuinka paljon arvostat kilpakumppaneitasi!" +collectibles.1608="Hattu" +collectibles.1609="Tee vaikutus muihin pelaajiin esittelemällä Guild-kaapuasi." +collectibles.1610="Rajoitetun ajan lemmikki (ei enää ostettavissa): Infrapunasilmä ja kiiltävä maalipinta; laajenna Hypixelin valtakuntaa kaikkiin lobbyihin tällä päivitetyllä HP9-B companionilla." +collectibles.1611="Taikapartikkelipaketti" +collectibles.1612="Salaperäinen kissaviiri" +collectibles.1613="Pit Bounty -kaapu" +collectibles.1614="Putkimiehen puvun pääkappale" +collectibles.1615="Kurpitsaviiri" +collectibles.1616="Rank-partikkelipaketti" +collectibles.1617="Renkaat-partikkelipaketti" +collectibles.1618="Esittele guildisi sijoitusta ennen vuoden 2018 guild-päivitystä." +collectibles.1619="Lumipartikkelipaketti" +collectibles.1620="Pallopartikkelipaketti" +collectibles.1621="Asu" +collectibles.1622="Top 100 Guild -kaapu" +collectibles.1623="Tornadopartikkelipaketti" +collectibles.1624="Tryhard-viiri" +collectibles.1625="???" +collectibles.1626="Haasta ystäväsi neljän suora -peliin. Kuka onkaan voittaja?" +collectibles.1627="Animoitu Comet-poro -hattu" +collectibles.1628="Räjäytä possu ja kerää kaikki kulta." +collectibles.1629="Kuumaa, kuumaa, kuumaa!" +collectibles.1630="Hypixelin turnauspalkinto" +collectibles.1631="Animoitu Joe-pingviini -hattu" +collectibles.1632="Sienihattu" +collectibles.1633="Aseta viiri esitelläksesi mahtavaa pistemäärääsi Turbo Kart Race Grand Prixissä." +collectibles.1634="Aseta viiri esitelläksesi sijoitustasi Tournament Hallin tapahtumassa." +collectibles.1635="Soita musiikkia käyttäen näppäimistöäsi pianona!" +collectibles.1636="Animoitu Sammy-keksi -hattu" +collectibles.1637="TKR Grand Prix -palkinto" +collectibles.1638="Hypixelin miekka" +collectibles.1639="Feenikspuku" +collectibles.1640="Feenikspuvun kypärä" +collectibles.1641="Feenikspuvun rintakappale" +collectibles.1642="Feenikspuvun housut" +collectibles.1643="Feenikspuvun kengät" +collectibles.1644="Tämä majesteettinen lintu nousee edeltäjänsä tuhkista!" +collectibles.1645="Klikkaa toistaaksesi uudelleensyntymisanimaation Mega Walssista!" +collectibles.1646="Avataan kauden %%season%% Battle Passissa." +collectibles.1647="Viehättävä kaapu" +collectibles.1648="Sydänsiivet peittävät selkäsi!" +collectibles.1649="Paha kaapu" +collectibles.1650="Minua pelottaa!" +collectibles.1651="Pyhä kaapu" +collectibles.1652="Kaunis kukkanen kasvaa selästäsi!" +collectibles.1653="Ping-kaapu" +collectibles.1654="Näyttää tämänhetkisen viiveesi." +collectibles.1655="Värikynäkaapu" +collectibles.1656="Siipesi hohtavat useissa väreissä!" +collectibles.1657="Vartijavanhin" +collectibles.1658="Hikipartikkelipaketti" +collectibles.1659="Laavapartikkelipaketti" +collectibles.1660="Neljän suora -vempain" +collectibles.1661="Ankanpoikavempain" +collectibles.1662="Luo kolme ankanpoikaa, jotka seuraavat sinua ympäri lobbya." +collectibles.1663="Säästöpossuvempain" +collectibles.1664="Syntetisaattorivempain" +collectibles.1665="Joulutodistevempain" +collectibles.1666="Duels-kauden viirivempain" +collectibles.1667="TKR Grand Prix -viirivempain" +collectibles.1668="Tournament Hall -viirivempain" +collectibles.1669="Klikkausefektit" +collectibles.1670="Hankkiudu huomion keskipisteeksi käyttämällä klikkausefektiä! Nämä kosmeettiset esineet aktivoituvat aina pelaajan klikatessa sinua." +collectibles.1671="Kritit-klikkausefekti" +collectibles.1672="Aivan kuin hyppäisit ja löisit pelaajaa, mutta tyylikkäämpi." +collectibles.1673="Kierre-klikkausefekti" +collectibles.1674="Sydänklikkausefekti" +collectibles.1675="Joku tykkää sinusta! Pienet sydämet jahtaavat lyöjääsi." +collectibles.1676="Zeus-klikkausefekti" +collectibles.1677="Mahtailu-klikkausefekti" +collectibles.1678="Esittele lempiväriäsi! (rankkisi %%color%%+-merkin väri!)" +collectibles.1679="Pää pois -klikkausefekti" +collectibles.1680="Lähetä pääsi avaruuteen! Ehkä joku tarvitsee sitä siellä..." +collectibles.1681="Munaisa klikkausefekti" +collectibles.1682="Kumpi tuli ensin: muna vai kana? KLIK." +collectibles.1683="Duels-kauden palkinto" +collectibles.1684="Joskus enkelit ovat vain tavallisia ihmisiä jotka auttavat meitä uskomaan ihmeisiin taas.\n\nTämän kaavun reunan väri riippu + väristäsi (oletuksena punainen)." +collectibles.1685="Aseta viiri esitelläksesi mahtavaa pistemäärääsi Duels-kaudella." +collectibles.1686="Siisti spiraali kiertää sinun ympäri päästä varpaisiin." +collectibles.1687="Klikkausefekti" +collectibles.1688="Tämä esine on saatavilla vain osoitteesta https://store.hypixel.net/ joulun aikaan!" +collectibles.1689="Ostettu Halloween Bundlesta!" +collectibles.1690="Ostettu Easter Bundlesta!" +collectibles.1691="Sinulla ei ole yhtään tämän asun osia käytettävissä!" +collectibles.1692="Puit yllesi yhden osan asusta %%suit%%" +collectibles.1693="Puit yllesi %%amount%% osaa asusta %%suit%%" +collectibles.1694="Pue yllesi koko asu" +collectibles.1695="Pue yllesi kaikki avaamasi asun %%name%% osat." +collectibles.1696="Pomppuhämähäkki" +collectibles.1697="Tappajakani" +collectibles.1698="Spooky Ghost" +collectibles.1699="Oletko koskaan halunnut karmivan kumppanin, jolla pelotella muita? Nyt sinulla on kummitus!" +collectibles.1700="Muutu karmivaksi kummitukseksi!" +collectibles.1701="Aavemainen klikkausefekti" +collectibles.1702="Näytä kallopyörre!" +collectibles.1703="Kalloklikkausefekti" +collectibles.1704="Näytä tukesi suurelle Magma Bossille tällä puvulla." +collectibles.1705="Valele magmavoidetta jalkojesi juureen luodaksesi maahan rituaalikuvion." +collectibles.1706="Magma Boss -puvun pääkappale" +collectibles.1707="Magma Boss -puvun rintakappale" +collectibles.1708="Magma Boss -puvun housut" +collectibles.1709="Magma Boss -puvun kengät" +collectibles.1710="Päättömän hevosmiehen puvun pääkappale" +collectibles.1711="Päättömän hevosmiehen puvun rintakappale" +collectibles.1712="Päättömän hevosmiehen puvun housut" +collectibles.1713="Päättömän hevosmiehen puvun kengät" +collectibles.1714="Karmivan kauhean luurankopuvun pääkappale" +collectibles.1715="Karmivan kauhean luurankopuvun rintakappale" +collectibles.1716="Karmivan kauhean luurankopuvun housut" +collectibles.1717="Karmivan kauhean luurankopuvun kengät" +collectibles.1718="Karkkisuihkulähde" +collectibles.1719="Hemmottele itseäsi kurpitsapiirakalla, kakulla, kultaomenoilla ja kekseillä tällä sokerisella suihkulähteellä!" +collectibles.1720="Muuta alue hautausmaaksi, joka tulvii kummituksia!" +collectibles.1721="Hautausmaavempain" +collectibles.1722="heittää witherin pääkalloja" +collectibles.1723="hypätä korkealle ilmaan" +collectibles.1724="Wither-luurankomuodonmuutos" +collectibles.1725="Luolahämähäkkimuodonmuutos" +collectibles.1726="Pimeän enkelin kaapu" +collectibles.1727="Pimeä energia -kaapu" +collectibles.1728="Vapauta pimeä energiasi mustan magian loitsuina kuolevaisesta ruumiistasi!" +collectibles.1729="Kierre-kaapu" +collectibles.1730="Pimeän energian spiraali kiertää ympärilläsi!" +collectibles.1731="%%player%% oli sijalla #%%rank%% %%points%% pisteellä" +collectibles.1732="Tournament Hall -viirit" +collectibles.1733="Sinun tulee ostaa tämä viiri esitelläksesi sitä!" +collectibles.1734="Käytä tribuutteja avataksesi sen Tournament Hallissa sen ollessa avoinna!" +collectibles.1735="Et ole osallistunut tähän turnaukseen!" +collectibles.1736="Et osallistunut!" +collectibles.1737="Pisteet: %%points%%" +collectibles.1738="Sijoitus: #%%pos%%" +collectibles.1739="Klikkaa luodaksesi!" +collectibles.1740="Viiriä ei ostettu!" +collectibles.1741="Turnausviiri" +collectibles.1742="Esittele sijoitustasi pelin %%gametype%% turnauksessa, joka järjestettiin %%month%%ssa %%year%%." +collectibles.1743="Tämä pelaaja ei voi vastaanottaa kukkaa juuri nyt." +collectibles.1744="Nämä pölyiset siivet auttavat pimeän enkeleitä nousemaan taivaalle taisteluun!" +collectibles.1745="Voit avata tämän companionin lähettämällä Giftejä muille pelaajille. Giftejä voi ostaa Hypixelin kaupasta:\nstore.hypixel.net!" +collectibles.1746="Luo klooneja ja lähetä ne kauas pois korkeuksiin." +collectibles.1747="Tämä esine on saatavilla vain osoitteesta https://store.hypixel.net/ pääsiäisen aikaan!" +collectibles.1748="Tämä esine avataan palkintona pistetaulukkosijasta turnauksissa!" +collectibles.1749="oli täällä joulukuussa %%year%%" +collectibles.1750="Joulutodisteen vuodet" +collectibles.1751="Näytä kuinka monta Adventtikalenteripalkintoa lunastit vuonna %%year%%!" +collectibles.1752="Vuoden %%year%% joulutodiste" +collectibles.1753="Karkkisuihkulähdevempain" +collectibles.1754="Todiste siitä, että olit täällä jouluna." +collectibles.1755="Tämä esine on saatavilla vain osoitteesta https://store.hypixel.net/ Black Fridayn aikaan!" +collectibles.1756="Jäätynyt luuranko" +collectibles.1757="Yritit lyödä luurankoa, mutta se jäädyitkin itse paikallesi!" +collectibles.1758="Jäätynyt zombi" +collectibles.1759="Alennusmyyntikaapu" +collectibles.1760="Black Friday, alennusmyyntien luvattu päivä (vai viikko?)." +collectibles.1761="Karkkispiraalikaapu" +collectibles.1762="Mikä onkaan parempaa kuin makeat karkit?" +collectibles.1763="Karkkitankokaapu" +collectibles.1764="Karkin mahtavat värit." +collectibles.1765="Makeasiivet-kaapu" +collectibles.1766="Melkein syömäkelpoinen." +collectibles.1767="Karmivan kauhea luurankopuku" +collectibles.1768="Tanssi ympäriinsä karmivan kauheana luurankona!" +collectibles.1769="Tämä asu soittaa myös karmivan kappaleen." +collectibles.1770="Säikäytä muut pelaajat muuttumalla Päättömäksi hevosmieheksi!" +collectibles.1771="Hyppää epäkuolleen ratsusi selkään." +collectibles.1772="Lumimiehen puku" +collectibles.1773="Lumimiehen puvun pääkappale" +collectibles.1774="Lumimiehen puvun rintakappale" +collectibles.1775="Lumimiehen puvun housut" +collectibles.1776="Lumimiehen puvun kengät" +collectibles.1777="Rawrrrrrrr" +collectibles.1778="Klikkaa heittääksesi lumipalloja noita ärsyttäviä ihmisiä päin." +collectibles.1779="Tonttupuku" +collectibles.1780="Tonttupuvun pääkappale" +collectibles.1781="Tonttupuvun rintakappale" +collectibles.1782="Tonttupuvun housut" +collectibles.1783="Tonttupuvun kengät" +collectibles.1784="Oletko koskaan halunnut olla yksi Joulupukin uskollisista apureista? Nyt voit olla!" +collectibles.1785="Klikkaa lähettääksesi lahjan!" +collectibles.1786="Jääpartikkelipaketti" +collectibles.1787="Koristenauhapartikkelipaketti" +collectibles.1788="Lumivanapartikkelipaketti" +collectibles.1789="Ilotulitusvempain" +collectibles.1790="On juhlan aika!" +collectibles.1791="Uudenvuoden lähtölaskenta -vempain" +collectibles.1792="Runsaudensarvivempain" +collectibles.1793="Olkoon tämä sarvi kuolemattomalta vuohelta tai joen jumalalta, on se kykenevä sylkemään sisuksistaan loputtomasti ravintoa." +collectibles.1794="Lahjaklikkausefekti" +collectibles.1795="Kuka sanoi ettei lahja voisi olla ihminen?" +collectibles.1796="Jouluilotulitus-klikkausefekti" +collectibles.1797="Ilotulitteet sopivat jokaiseen vuodenaikaan!" +collectibles.1798="Näytä partikkeleita ympärilläsi lobbyissa näillä siisteillä partikkeliefekteillä!" +collectibles.1799="Kilpailupelimuotojen esineet" +collectibles.1800="Lahjakaapu" +collectibles.1801="Paras asia joulussa" +collectibles.1802="Saatavilla rajoitetun ajan %%event%% Bundlesta osoitteesta https://store.hypixel.net/" +collectibles.1803="Tämä esine on saatavilla %%event%% Bundlesta rajoitetun ajan ja saattaa palata tulevaisuudessa!" +collectibles.1804="Saatavilla %%event%% Bundlesta osoitteesta http://store.hypixel.net/" +collectibles.1805="Tämä esine ei ole juuri nyt saatavilla!" +collectibles.1806="Artemis-kaapu" +collectibles.1807="Hiirivempain" +collectibles.1808="Kiinalainen uusivuosi -partikkelipaketti" +collectibles.1809="Tämä esine on saatavilla Ingame Storesta rajoitetun ajan %%event%%tapahtumamme aikana!" +collectibles.1810="Tämä esine on saatavilla Ingame Storesta rajoitetun ajan %%event%%tapahtumamme aikana ja saattaa palata tulevaisuudessa!" +collectibles.1811="Saatavilla Ingame Storesta, Harvinaisuudet-valikon alta" +collectibles.1812="Karmivat vempaimet, jotka ovat saatavilla Halloween-tapahtuman ajan!" +collectibles.1813="Kun ilmassa on joulun taikaa, ovat nämäkin vempaimet saatavilla vain Joulutapahtuman ajan!" +collectibles.1814="Kun lämpötilat ovat korkealla, viilennä itseäsi näillä hauskoilla vempaimilla, jotka ovat saatavilla vain Kesätapahtuman ajan!" +collectibles.1815="Kiinalaisen uudenvuoden mukana tulevat nämä vempaimet, jotka ovat saatavilla vain tapahtuman ajan!" +collectibles.1816="Kevät on tullut, kuten myös kaikki allergiatkin. Pakene niitä näillä vempaimilla Pääsiäistapahtumastamme!" +collectibles.1817="Et voi käyttää vempaimia tähän pelaajaan!" +collectibles.1818="Kasvava zombi" +collectibles.1819="Buggy Companion" +collectibles.1820="Kevätpartikkelipaketti" +collectibles.1821="Jänishattu" +collectibles.1822="Pääsiäismunahattu" +collectibles.1823="Leppäkerttuhattu" +collectibles.1824="Suklaamunahattu" +collectibles.1825="Vahinkoilmaisin-klikkausefekti" +collectibles.1826="Kanapuku" +collectibles.1827="Kanapuvun pääkappale" +collectibles.1828="Kanapuvun rintakappale" +collectibles.1829="Kanapuvun housut" +collectibles.1830="Kanapuvun kengät" +collectibles.1831="Pääsiäismuna-asun pääkappale" +collectibles.1832="Pääsiäismuna-asun rintakappale" +collectibles.1833="Pääsiäismuna-asun housut" +collectibles.1834="Pääsiäismuna-asun kengät" +collectibles.1835="Puunistutusvempain" +collectibles.1836="Istuttanut" +collectibles.1837="Jänismuodonmuutos" +collectibles.1838="hypätä tosi korkealle" +collectibles.1839="Pääsiäismunakaapu" +collectibles.1840="Monarkinsiivet-kaapu" +collectibles.1841="Parvikaapu" +collectibles.1842="Halloween" +collectibles.1843="Joulu" +collectibles.1844="Kesä" +collectibles.1845="Kiinalainen uusivuosi" +collectibles.1846="Pääsiäinen" +collectibles.1847="Pääsiäismunaklikkausefekti" +collectibles.1848="Tämä avataan erikoistehtävästä!" +collectibles.1849="Klikkaa tästä lisätäksesi tämän lemmikin suosikkeihisi. Voit kutsua ja poistaa suosikkilemmikkisi suoraan tavaraluettelostasi." +collectibles.1850="Myrskykaapu" +collectibles.1851="Kalakaapu" +collectibles.1852="Keisarin siivet-kaapu" +collectibles.1853="Rantapartikkelipaketti" +collectibles.1854="Lentävä kalmari" +collectibles.1855="Pomppulammas" +collectibles.1856="%%name%% paloi poroksi käsiteltyään kuumaa perunaa!" +collectibles.1857="Karmivat siivet -kaapu" +collectibles.1858="Kurpitsalyhtykaapu" +collectibles.1859="Palava zombi" +collectibles.1860="Hiiltynyt luuranko" +collectibles.1861="Parvivempain" +collectibles.1862="Kurpitsahattu" +collectibles.1863="Patahattu" +collectibles.1864="Jason-hattu" +collectibles.1865="Kurpitsa-asun pääkappale" +collectibles.1866="Kurpitsa-asun rintakappale" +collectibles.1867="Kurpitsa-asun housut" +collectibles.1868="Kurpitsa-asun saappaat" +collectibles.1869="Luurankosamurain kypärä" +collectibles.1870="Luurankosamurain rintakappale" +collectibles.1871="Luurankosamurain housut" +collectibles.1872="Luurankosamurain kengät" +collectibles.1873="Jack o' Lantern Companion" +collectibles.1874="Saatavilla juuri nyt!" +collectibles.1875="Ei saatavilla juuri nyt!" +collectibles.1876="Mikä olisikaan parempi aika heitellä kurpitsoja? Enpä kyllä keksi." +collectibles.1877="Klikkaa ampuaksesi pyöriviä kurpitsoja ympärilläsi!" +collectibles.1878="Hiljaa kuin varjo, luurankosamurai kulkee halki lobbyjen luiset miekat tanassa." +collectibles.1879="Klikkaa heittääksesi kuolettavan tarkka luupuukko." +collectibles.1880="Kalat seuraavat kävellessäsi." +collectibles.1881="Luo kaloja taaksesi kävellessäsi lobbyssa!" +collectibles.1882="Luo hämähäkkilauma pelottelemaan muita ympärilläsi!" +collectibles.1883="Esittele halloweenhenkeä tällä välkkyvällä kurpitsalyhdyllä, joka sopii hyvin selkääsi!" +collectibles.1884="Nämä siivet vaihtavat väriä oranssin ja violetin, kahden kauhistuttavimman värin, välillä!" +collectibles.1885="Tuo valoshow mukanasi minne vain. Tämä karmiva kurpitsalyhty syttyy seuraten sinua." +collectibles.1886="Juhlista Hypixel Networkia tällä siistillä efektillä, joka näyttää Hypixelin logon pääsi päällä ilotuliteräjähdyksenä!" +collectibles.1887="Loistaa kirkkaasti yöllä. Tämä kaapu seuraa oikeita kuun vaiheita!" +collectibles.1888="Paljon pääsiäismunia lentelee kehostasi." +collectibles.1889="Tämä pikkuinen ötökkäystävä surraa ympärilläsi lobbyissa!" +collectibles.1890="Karmiva partikkelipaketti" +collectibles.1891="Kruunuviiri" +collectibles.1892="Ahmattiviiri" +collectibles.1893="Muurinpirstojaviiri" +collectibles.1894="Deal with it -pupuviiri" +collectibles.1895="Portaaliviiri" +collectibles.1896="Hypixel-miekkaviiri" +collectibles.1897="Iloinen lammas" +collectibles.1898="Grinch-hattu" +collectibles.1899="Kellohattu" +collectibles.1900="Pyrypallohattu" +collectibles.1901="Jouluinen pallokalahattu" +collectibles.1902="Jouluinen zombihattu" +collectibles.1903="Jouluinen luurankohattu" +collectibles.1904="Jouluinen kyläläishattu" +collectibles.1905="Jouluinen kalmarihattu" +collectibles.1906="Jouluinen Herobrine-hattu" +collectibles.1907="Animoitu Sateenkaarilahjahattu" +collectibles.1908="Lumimyrsky-klikkausefekti" +collectibles.1909="Dreidel-vempain" +collectibles.1910="Lumimyrskykaapu" +collectibles.1911="Kimaltelevat siivet -kaapu" +collectibles.1912="Vesipatsas-klikkausefekti" +collectibles.1913="Vettä suihkuaa päästäsi!" +collectibles.1914="Kasvoviitta" +collectibles.1915="Näyttää kasvosi!" +collectibles.1916="Ranks Gifted -kaapu" +collectibles.1917="Näyttää kuinka monta rankkia olet antanut muille pelaajille." +collectibles.1918="Piñata-vempain" +collectibles.1919="Lohikäärmeratsastajavempain" +collectibles.1920="Ratsasta ympäriinsä mahtavalla Ender-lohikäärmeellä!" +collectibles.1921="Tässä lobbyssa on jo joku, joka käyttää tätä vempainta." +collectibles.1922="Lohikäärmeesi täytyy levätä!" +collectibles.1923="Hän ei pidä siitä kovinkaan paljon." +collectibles.1924="Se on hänen lempiruokaansa!" +collectibles.1925="Se on hänen lempijuomaansa!" +collectibles.1926="Se on hänen lempilelunsa!" +collectibles.1927="Sinulla on jo Kuuma peruna, älä ole ahne! :)" +collectibles.1928="Sinulle annettiin lumottu kuuma peruna!" +collectibles.1929="Buggy" +collectibles.1930="Pikku apulainen" +collectibles.1931="Kot kot ko-kot" +collectibles.1932="Klikkaa muniaksesi" +collectibles.1933="Niin paljon värejä, liian paljon, jotta voisin valita! Miksi ei siis kaikkia?" +collectibles.1934="Asu vaihtaa nopeasti erilaisten pääsiäismunatyylien välillä" +collectibles.1935="Luo nälkäisiä hiiriä! Anna niille vähän juustoa tehdäksesi ne onnellisiksi!" +collectibles.1936="Piglin-asu" +collectibles.1937="Tässä asussa ovat kaikki maailman rikkaudet... jopa piglinit ovat sen perässä!" +collectibles.1938="Kiiltäviä esineitä putoilee kävellessäsi" +collectibles.1939="Ruusukaapu" +collectibles.1940="Kaunis ruusu, jonka Hypixel Team antoi sinulle!" +collectibles.1941="Laiskiaisnaamakaapu" +collectibles.1942="Näyttää laiskiaisen kasvot" +collectibles.1943="Menorakaapu" +collectibles.1944="Lampunjalka puhtaasta kullasta" +collectibles.1945="Apilakaapu" +collectibles.1946="Vehreä apila auringonvalossa kimmeltävä apila! On erittäin harvinaista, että sillä on neljä lehteä..." +collectibles.1947="Kauniisti koristeltu pääsiäismuna!" +collectibles.1948="Kevät edustaa uusia alkuja, mukaan lukien perhosia nousemassa koteloistaan. Näytä kirjavat siipesi ylpeästi!" +collectibles.1949="Blub" +collectibles.1950="Luo hyinen luistelurata tänne lobbyyn!" +collectibles.1951="Luisteluvempain" +collectibles.1952="Lumipallohattu" +collectibles.1953="Sukkahattu" +collectibles.1954="Hassu lumiukkohattu" +collectibles.1955="Kanaviiri" +collectibles.1956="Munakokkeliviiri" +collectibles.1957="Luo myrsky aina jonkun klikatessa sinua" +collectibles.1958="Näytä yksityiskohtaisia ilmeitä kaikille, jotka sinua katsovat!" +collectibles.1959="Esittele liikkeitäsi, heiluttele ystävillesi ja paljon muuta näillä siisteillä eleillä!" +collectibles.1960="Tee vaikutus muihin pelaajiin esittelemällä Guildisi tasoa." +collectibles.1961="Sortunut enkeli -kaapu" +collectibles.1962="Esittele SkyWars-etenemistäsi tällä kaavulla!" +collectibles.1963="Häiveperhonen sen kauniine sinisine siipineen" +collectibles.1964="Kesän mukana tulevat myös myrskyt." +collectibles.1965="Bzzzz" +collectibles.1966="Myrskyt voivat olla julmia, mutta saisimme ehkä lumisen päivän!?" +collectibles.1967="Tämä kauniit siivet kimaltelevat auringonvalossa heijastaen kuten lumi ja jää." +collectibles.1968="Pyöritä ja katso, mitä saat!" +collectibles.1969="Onko tämä SkyBlock?" +collectibles.1970="Et voi käyttää tätä nuottia nyt. Näin tapahtuu soittaessasi liian nopeasti!" +collectibles.1971="Haastoit pelaajan %%player%% Neljän suora -peliin." +collectibles.1972="Et voi aktivoida vempaimia parkourlaattojen lähellä!" +collectibles.1973="Saatavilla Kausittaisesta kalastuksesta" +collectibles.1974="Paina numeroita 1-8 näppäimistölläsi!" +collectibles.1975="Jokin meni vikaan! Ilmoitathan tästä." +collectibles.1976="Keräilyesineet eivät ole käytössä alpha-palvelimella!" +collectibles.1977="Vain VIP:t ja sitä korkeammat voivat saada tämän esineen liittyessään palvelimelle ystävänpäivänä!" +collectibles.1978="Vastastajasi valitsi: ???" +collectibles.1979="Kukaan ei osunut kehenkään! Surullista!" +collectibles.1980="Olet liian korkealla voidaksesi käyttää tätä juuri nyt!" +collectibles.1981="Kuuma peruna" +collectibles.1982="Vaihda!" +collectibles.1983="Hyvää ystävänpäivää %%year%%!" +collectibles.1984="Näppäimistötila" +collectibles.1985="Klikkaa käyttääksesi!" +collectibles.1986="Tämä on saatavilla kalastuksesta Päälobbyssa kausitapahtumien aikaan!" +collectibles.1987=" • Paina numeroita 1-8 näppäimistölläsi" +collectibles.1988="Salarankillasi ei ole oikeutta käyttää tätä lemmikkiä! Käytä komentoa /unnick poistaaksesi salanimesi." +collectibles.1989="%%month%% %%year%%" +collectibles.1990="Tämän esineen voi saada vain Duels-kauden palkintona." +collectibles.1991="%%player%% poistui Neljän suora -pelistä." +collectibles.1992="Ladataan..." +collectibles.1993="Oikeaklikkaa esikatsellaksesi" +collectibles.1994="Osu niin moneen pelaajaan kuin mahdollista ennen ajan loppumista!" +collectibles.1995="%%player%% haastoi sinut Neljän suora -peliin." +collectibles.1996="Blitz-tähtiefekti suoraan Blitzistä. Loppumme on lähellä!" +collectibles.1997="Sinun tulee olla vähintään VIP voidaksesi kutsua lemmikkejä! Osta se osoitteessa https://store.hypixel.net" +collectibles.1998="Ohjeet:" +collectibles.1999="Sinulle annettiin lumottu kuuma peruna!" +collectibles.2000="Kuka tietää minkä vastustajasi valitsee?" +collectibles.2001="Hyvää Pyhän Patrickin päivää %%year%%!" +collectibles.2002="TKR Grand Prix -viiri" +collectibles.2003="%%prefix%%Divisioona %%division%% x%%stars%%" +collectibles.2004="Klikkausefekti nollattu" +collectibles.2005="Ei saatavilla juuri nyt" +collectibles.2006="Voittaa: %%what%%" +collectibles.2007="Lumisota on päättynyt!" +collectibles.2008="Liityit lumisotaan! Osu niin moneen pelaajaan kuin mahdollista ennen ajan loppumista!" +collectibles.2009="Tämä avataan erikoissaavutuksesta!" +collectibles.2010="Klikkaa tästä nähdäksesi saatavilla olevat Kaapusi!" +collectibles.2011="Sininen" +collectibles.2012="Vastustajasi on tehnyt valintansa ja odottaa nyt sinua." +collectibles.2013="Tämän esineen voi saada vain TKR Grand Prix -palkintona." +collectibles.2014="Alempi oktaavi" +collectibles.2015="Tarvitset enemmän dustia!" +collectibles.2016=" • Käytä näppäimiä Q tai 9 vaihtaaksesi oktaavia" +collectibles.2017="Klikkaa tästä nähdäksesi saatavilla olevat Kaapusi!" +collectibles.2018="iPixel" +collectibles.2019="Nykyinen lemmikkisi ei tue tätä vempainta!" +collectibles.2020="Et voi käyttää kykyjä tällä alueella!" +collectibles.2021="Alun perin Warlordsista, kirjaimellisesti työntää maan pois luotasi." +collectibles.2022="Kultainen" +collectibles.2023="%%points%%ms" +collectibles.2024="MAX EXP" +collectibles.2025="ANNA KUUMA PERUNA ETEENPÄIN!" +collectibles.2026="Ei kausiviirejä saatavilla" +collectibles.2027="Luo mukavan penkin sinulle ja ystävillesi!" +collectibles.2028="Odotusaika!" +collectibles.2029=" • Pidä hiiresi minkä tahansa työkalupalkin kvartsin päällä" +collectibles.2030="Haastoit pelaajan %%player%% Kivi, paperi, keritsimet -peliin." +collectibles.2031="Lähistöltä kuulunut ääni ei soi näin lähellä spawnia!" +collectibles.2032="Lumipallo (Oikeaklikkaa)" +collectibles.2033="Duels-kauden %%season%% viiri" +collectibles.2034="Klikkaa tästä asettaaksesi merkkisi tälle pystyriville." +collectibles.2035="Klikkaa tästä hylätäksesi." +collectibles.2036="TURNAUSVIIRI" +collectibles.2037="Et voi käyttää tätä ratsastaessasi toisilla pelaajilla!" +collectibles.2038="Appelsiini" +collectibles.2039="Duels-kausi %%season%%" +collectibles.2040="Sait Apilakaavun liityttyäsi palvelimelle Pyhän Patrickin päivänä!" +collectibles.2041="Voit ruiskuttaa tulta ja saada 100% varmasti Smokey-karhun itkemään. Vain sinä voit pysäyttää metsäpalot." +collectibles.2042="Sinun tulee käyttää Minecraftin versiota 1.8 käyttääksesi tätä vempainta." +collectibles.2043="Ei avattavissa!" +collectibles.2044="Valitse toinen!" +collectibles.2045="Soitin" +collectibles.2046="Et lunastanut yhtään palkintoa tuona vuonna!" +collectibles.2047="%%player%% voitti sinut Neljän suora -pelissä!" +collectibles.2048="ERRPR" +collectibles.2049="Tämä esine avataan The Pitissä!" +collectibles.2050="Näytä mihin divisioonaan ylsit Duels-kaudella %%season%%!" +collectibles.2051="Et omista yhtään Turnausviiriä! Osta yksi Tournament Hallista." +collectibles.2052="Klikkaa!" +collectibles.2053="Näppäimistön näppäin" +collectibles.2054="RIKKI" +collectibles.2055="Soita näppäimistölläsi!" +collectibles.2056="Ei saatavilla!" +collectibles.2057="Hypixel Radio" +collectibles.2058="#%%num%%" +collectibles.2059="Tässä lobbyssa on jo lumisota käynnissä!" +collectibles.2060="Voittava siirto!" +collectibles.2061="Vain VIP:t ja sitä korkeammat voivat saada tämän esineen liittyessään palvelimelle Pyhän Patrickin päivänä!" +collectibles.2062="Ylempi!" +collectibles.2063="Olet jo kutsunut pelaajan %%player%% Neljän suora -peliin." +collectibles.2064="Voitit pelaajan %%player%% Neljän suorassa!" +collectibles.2065="Tässä lobbyssa on jo kuuma peruna -vempain käytössä!" +collectibles.2066="Et voi käyttää tätä muodonmuutoksen ollessa aktiivisena!" +collectibles.2067="Pidä hiiri tämän kohdalla!" +collectibles.2068="Oikeaklikkaa pelaajaa aloittaaksesi Neljän suora -pelin hänen kanssaan!" +collectibles.2069="Ei Duels-kauden viirejä saatavilla, sillä Duels-kausi ei ole päättynyt." +collectibles.2070="Mestaridivisioona" +collectibles.2071="Et saavuttanut tarpeeksi korkeaa divisioonaa Duels-kaudella %%season%% asettaaksesi tätä viiriä!" +collectibles.2072="Yritit lyödä luurankoa, mutta se sokaisi sinut savulla!" +collectibles.2073="Neljän suora -peli pelaajan %%player%% kanssa päättyi tasapeliin." +collectibles.2074="%%player%% haastoi sinut Kivi, paperi, keritsimet -peliin." +collectibles.2075="Klikkaa tästä antaaksesi karkin." +collectibles.2076="Se on hänen lempi%%type%%nsa!" +collectibles.2077="Ylempi oktaavi" +collectibles.2078="Et voi käyttää tätä täällä!" +collectibles.2079="Tämä näkyy vain Admineille!" +collectibles.2080="Sait Ruusukaavun liityttyäsi palvelimelle ystävänpäivänä!" +collectibles.2081="Et saavuttanut tarpeeksi korkeaa divisioonaa!" +collectibles.2082="Soittimen valinta" +collectibles.2083="Salarankillasi ei ole oikeutta käyttää tätä vempainta! Käytä komentoa /unnick poistaaksesi salanimesi." +collectibles.2084="Klikkaa tästä tehdäksesi kepposen." +collectibles.2085="Kauas pois korkeuksiin -vempain" +collectibles.2086="Tämä löytyy kiertävien esineiden valikoimasta Hypixelin kaupasta!" +collectibles.2087="Hypixel Store -eksklusiivinen" +collectibles.2088="Kivi" +collectibles.2089="%%winner%% voitti Neljän suora -pelin pelaajaa %%loser%% vastaan!" +collectibles.2090="%%loser%% hävisi Neljän suora -pelin pelaajaa %%winner%% vastaan!" +collectibles.2091="Munaskannerikaapu" +collectibles.2092="Tulimunatykkivempain" +collectibles.2093="Pupujuhlavempain" +collectibles.2094="Pääsiäiskorihattu" +collectibles.2095="Kananpoikahattu" +collectibles.2096="Mehiläislemmikki" +collectibles.2097="Maapallokaapu" +collectibles.2098="Katso äiti, täältä näkee koko maailman!" +collectibles.2099="Ostettavissa In-Game Hypixel Storesta Maan päivänä!" +collectibles.2100="Hypixel Storen Maan päivän erityistuote" +collectibles.2101="Vaatii rankin MVP++" +collectibles.2102="Lobbyn vempaimet eivät enää vaikuta sinuun." +collectibles.2103="Lobbyn vempaimet vaikuttavat nyt sinuun." +collectibles.2104="Estät Cowboy-vempaimen toiminnan kohdallasi." +collectibles.2105="Sallit Cowboy-vempaimen toiminnan kohdallasi." +collectibles.2106="Huomio: /stopabusingme saattaa edelleen estää vempaimen." +collectibles.2107="Sinun on oltava MVP++ voidaksesi käyttää tuota! Osta rankkeja osoitteesta https://store.hypixel.net" +collectibles.2108="Kaapu nollattu" +collectibles.2109="Kannettava lampi -vempain" +collectibles.2110="Vie kalat mukanasi minne vain!" +collectibles.2111="Kultainen pallokalahattu" +collectibles.2112="Kokenut kalastaja -viiri" +collectibles.2113="Hämähäkkiratsastaja" +collectibles.2114="Kanaratsastaja" +collectibles.2115="Kyklooppi" +collectibles.2116="Henki-klikkausefekti" +collectibles.2117="Lumipallokaapu" +collectibles.2118="Sulkee sinut lumipallon sisään!" +collectibles.2119="Lumiukkoratsulemmikki" +collectibles.2120="Pyrypallovempain" +collectibles.2121="Juhli lobbyssa jouluisen musiikin säestyksellä!" +collectibles.2122="Present Companion" +collectibles.2123="Muokkaa tätä leijuvaa lahjaa haluamaksesi ja anna sen seurata sinua ympäri lobbya!" +collectibles.2124="Present Companion Skin" +collectibles.2125="Muokkaa Present Companionisi ulkonäköä!" +collectibles.2126="Muutettiin Present Companionin ulkonäköä!" +collectibles.2127="Punakeltainen" +collectibles.2128="Vihreä turkoosilla nauhalla" +collectibles.2129="Sininen purppuranauhalla" +collectibles.2130="Oranssi sinisellä nauhalla" +collectibles.2131="Vaaleanpunainen keltaisella nauhalla" +collectibles.2132="Turkoosi vihreällä nauhalla" +collectibles.2133="Violetti turkoosilla nauhalla" +collectibles.2134="Violetti vaaleanpunaisella nauhalla" +collectibles.2135="Harmaa violetilla nauhalla" +collectibles.2136="Sininen vihreällä nauhalla" +collectibles.2137="Kultainen violetilla nauhalla" +collectibles.2138="Sininen hopeanauhalla" +collectibles.2139="Vaaleanpunainen turkoosilla nauhalla" +collectibles.2140="Musta vihreällä nauhalla" +collectibles.2141="Violetti vihreällä nauhalla" +collectibles.2142="Violetti punaisella nauhalla" +collectibles.2143="Oranssi vihreällä nauhalla" +collectibles.2144="Keltainen violetilla nauhalla" +collectibles.2145="Hopeinen kultanauhalla" +collectibles.2146="Vaaleansininen kultanauhalla" +collectibles.2147="Sininen beigellä nauhalla" +collectibles.2148="Punainen vihreällä nauhalla" +collectibles.2149="Ruskea sinisellä nauhalla" +collectibles.2150="Vihreä vaaleanpunaisella nauhalla" +collectibles.2151="Turkoosi purppuranauhalla" +collectibles.2152="Putkimiehen puvun rintakappale" +collectibles.2153="Putkimiehen puvun housut" +collectibles.2154="Putkimiehen puvun kengät" +collectibles.2155="Ostettavissa store bundleista\njouluisin!" +collectibles.2156="Ostettavissa store bundleista\nBlack Fridayna!" +collectibles.2157="Auta maapalloa istuttamalla puu lobbyyn!" +collectibles.2158="Nollaa suosikit?" +collectibles.2159="Blub" +collectibles.2160="Legendaarinen kalastajaviiri" +collectibles.2161="Karmiva kalastajaviiri" +collectibles.2162="Jouluinen kalastajaviiri" +collectibles.2163="Pelästynyt pallokala -hattu" +collectibles.2164="Partikkelipaketit" +collectibles.2165="Valjasta jumalten voimat ja iske salamalla häntä, joka uskaltaa sinua lyödä." +collectibles.2166="Iske niiltä sielut pihalle!" +collectibles.2167="Tulikärpänen" +collectibles.2168="Luo trampoliini, joka näyttää, kuinka pitkään olet pelannut Hypixelissä!" +collectibles.2169="Räjäytä possu ja kerää kaikki kulta." +collectibles.2170="Noidan pata -vempain" +collectibles.2171="Vie alkemia mukanasi minnevain!" +collectibles.2172="Pelottavat kalat -vempain" +collectibles.2173="Kalat lentävät!" +collectibles.2174="Kaikki räjäytetään!!!" +collectibles.2175="Niin paljon pupuja!" +collectibles.2176="Kurpitsalyhtykaapu" +collectibles.2177="Langennut enkeli -kaapu" +collectibles.2178="Älä riko sitä!" +collectibles.2179="Mitä saat, kun yhdistät tontun ja vuohen?" +collectibles.2180="Joulupukin" +collectibles.2181="Kuka antaa joululahjat pikkukaloille?" +collectibles.2182="Kalapukki!" +collectibles.2183="Mitä tapahtui miehelle, joka varasti joulukalenterin?" +collectibles.2184="Hän sai 24 päivää!" +collectibles.2185="Mikä on maailman paras joululahja?" +collectibles.2186="Rikkinäinen rumpu, aivan lyömätön!" +collectibles.2187="Kuka on joulupukin suosikkilaulaja?" +collectibles.2188="Tonttu Wiskari!" +collectibles.2189="Miksi joulukuuset ovat niin huonoja ompelijoita?" +collectibles.2190="Ne pudottavat aina neulasensa!" +collectibles.2191="Kävikö Petteri Punakuono koulua?" +collectibles.2192="Ei. Hän on aivan tonttu!" +collectibles.2193="Mitä saat, kun yhdistät lumiukon ja vampyyrin?" +collectibles.2194="Pakkasenpureman!" +collectibles.2195="Missä Kuuraparta pitää rahojaan?" +collectibles.2196="Lumipenkassa." +collectibles.2197="Miksi taiteilija ei halunnut esiintyä jouluna?" +collectibles.2198="Hänellä ei ollut lahjoja." +collectibles.2199="Mitä lumiukko syö aamiaiseksi?" +collectibles.2200="Lumihiutaleita." +collectibles.2201="Minä vuonna uudenvuodenpäivä tulee ennen joulua?" +collectibles.2202="Joka vuosi." +collectibles.2203="Mitä joulupukki kysyi Skotlannissa?" +collectibles.2204="Onko täällä kilttejä?!" +collectibles.2205="Miksi talonmies irtisanoutui epäonnistuttuaan lumenluonnissa?" +collectibles.2206="Se oli kova kolaus hänelle." +collectibles.2207="Miksi kutsutaan lumiukkoa kesälomalla?" +collectibles.2208="Lätäköksi." +collectibles.2209="Mitä Jeesus sanoi avatessaan joululahjoja?" +collectibles.2210="Jee, sukset!" +collectibles.2211="Hiivi muniaksesi" +collectibles.2212="Valjasta jumalten voimat ja iske salamalla häntä, joka uskaltaa sinua lyödä." +collectibles.2213="Rankkasadekaapu" +collectibles.2214="Ethän unohda sateenvarjoa!" +collectibles.2215="Lattevempain" +collectibles.2216="Et voi aktivoida tätä ollessasi parkourissa!" +collectibles.2217="Kaikki tarvitsemasi energia." +collectibles.2218="Lämpöaalto-partikkelipaketti" +collectibles.2219="Kalakauppiaan asun hattu" +collectibles.2220="Kalakauppiaan asun rintapanssari" +collectibles.2221="Kalakauppiaan asun housut" +collectibles.2222="Kalakauppiaan asun kengät" +collectibles.2223="Tämä esine avataan SkyWarsin Enkelin laskeutumisessa!" +collectibles.2224="Avataan ostamalla se SkyWarsin Enkelin laskeutumisesta!" +collectibles.2225="Akvaariokaapu" +collectibles.2226="Sateenvarjosta ei ole apua täällä." +collectibles.2227="Lohi" +collectibles.2228="Jopa luilla on tarinoita kerrottavanaan." +collectibles.2229="Lohikäärmesiivet-kaapu" +collectibles.2230="Levitä siipesi ja lennä." +collectibles.2231="Avataan eventin %%festival%% kaupasta!" +collectibles.2232="Lumiukkoratsu" +collectibles.2233="Jänisratsu" +collectibles.2234="Avataan Päälobbyn Kalastuspalkintona!" +collectibles.2235="Saatavilla kalastamalla Päälobbyssa" +collectibles.2236="Veri" +collectibles.2237="Kineesi" +collectibles.2238="Kanapuvun housut" +collectibles.2239="Kanapuvun kengät" +collectibles.2240="Pääsiäismuna-asu" +collectibles.2241="Kurpitsa-asu" +collectibles.2242="Kurpitsa-asun rintakappale" +collectibles.2243="Kalakauppiaan asu" +collectibles.2244="Piglin-asun pääkappale" +collectibles.2245="Piglin-asun rintakappale" +collectibles.2246="Piglin-asun housut" +collectibles.2247="Piglin-asun saappaat" +collectibles.2248="Et voi käyttää muodonmuutosta aloittaessasi parkouria!" +collectibles.2249="Luo upea ritari vartioimaan lobbya!" +collectibles.2250="pelaajan %%player%% ritari" +collectibles.2251="Rakenteet" +collectibles.2252="Vempaimet, jotka muuttavat ympäristöäsi, trampoliineista raketteihin!" +collectibles.2253="Vapauta meri ja lähetä eteesi hyökyaalto!" +collectibles.2254="%%event%% -kosmeettiset esineet" +collectibles.2255="Katso kosmeettisia esineitä, jotka on saatavilla %%event%%tapahtuman aikana." +collectibles.2256="Tietyt kosmetiikkatuotteet ovat saatavilla vain tiettyjen tapahtumien aikana. Katso kunkin tapahtuman sisältö ja saatavuus." +collectibles.2257="Roihukaapu" +collectibles.2258="Avataan eventin %%festival%% bingokortista!" +collectibles.2259="Korruptoitunut vempain" +collectibles.2260="Korruptoi maailma ympärilläsi." +collectibles.2261="Kurpitsasadevempain" +collectibles.2262="Kolme- ja puolimetrinen jättiluuranko -vempain" +collectibles.2263="Et voi käyttää tämän tyyppistä vempainta spawnin lähellä!" +collectibles.2264="Vain %%amount%% tällaista vempainta voi olla käytössä samaan aikaan!" +collectibles.2265="Pelaajan %%player%% jättiluuranko" +collectibles.2266="Tekee selkärankaa kihellyttävän keskipisteen Halloweeniin." +collectibles.2267="Anna kurpitsojen sataa!" +collectibles.2268="Lumi-klikkausefekti" +collectibles.2269="Jänis: Valkoinen (pieni)" +collectibles.2270="Höyhenpeitekaapu" +collectibles.2271="Pastellilammas" +collectibles.2272="Heinäpaali" +collectibles.2273="Tarviiiiitko kaveeeerin? Hypixelin suosikki-eläin tulee luoksii tällä söpöllä laiskiaisseuralla!" +#collectibles.2274="" # No translation available +#collectibles.2275="" # No translation available +#collectibles.2276="" # No translation available +collectibles.2277="Nouki lohkot taianomaisesti ja lennätä ne kavereidesi päälle!" +#collectibles.2278="" # No translation available +collectibles.2279="Sikatykin lisälaite" +collectibles.2280="Laukaise sika korkealle taivaalle samalla kun ratsastat sillä!" +collectibles.2281="Meloni" +#collectibles.2282="" # No translation available +#collectibles.2283="" # No translation available +collectibles.2284="Aivan kuin satukirjasta! Vai oliko se ankka?" +#collectibles.2285="" # No translation available \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/daily_rewards.properties b/configuration/i18n/fi_FI/official/daily_rewards.properties new file mode 100644 index 000000000..1a8439ba5 --- /dev/null +++ b/configuration/i18n/fi_FI/official/daily_rewards.properties @@ -0,0 +1,76 @@ +daily_rewards.claim_reward="Lunasta palkintosi" +daily_rewards.1="Pelaa palkintoja voittaneita Minecraft-minipelejä kavereidesi kanssa ilmaiseksi. Vain Hypixelin Minecraft-palvelimella!" +daily_rewards.2="Hypixel-palkintokortti" +daily_rewards.3="Joko tätä linkkiä ei ole olemassa tai se on vanhentunut." +daily_rewards.4="Tämä palvelu ei ole juuri nyt saatavilla, ilmoitathan asiasta henkilökunnalle." +daily_rewards.5="Vieraile Hypixelin nettisivuilla" +daily_rewards.6="Tabletteja ja mobiililaitteita ei tueta tällä hetkellä. Ole hyvä ja käytä tietokoneen selainta." +daily_rewards.7="Selaimesi on joko vanhentunut tai ei tue modernia web-teknologiaa ja ei pysty näyttämään tätä nettisivua. Ole hyvä ja päivitä tai vaihda selaintasi. Suosittelemme Chromea parhaan kokemuksen saavuttamiseksi." +daily_rewards.8="Hanki Chrome" +daily_rewards.9="§a-----------------------------------------------------\n§fOlet lunastanut {$color}§l[{$rarity} {$item}] §f-palkintokortin!\nTule takaisin huomenna tai käytä\n§ePalkintomerkkejä §fLähettimiehen luona yrittääksesi uudelleen!\n§a-----------------------------------------------------" +daily_rewards.10="Yleinen" +daily_rewards.11="Eeppinen" +daily_rewards.12="Harvinainen" +daily_rewards.13="Legendaarinen" +daily_rewards.14="Harvinaisuus: " +daily_rewards.15="Päivittäinen putki" +daily_rewards.16="Kun lunastat joka päivä 9 kertaa putkeen, saat yhden ylimääräisen Palkintomerkin, jolla voit lunastaa yhden palkinnon" +daily_rewards.17="Päivittäinen palkinto" +daily_rewards.18="Pistemäärä nyt: " +daily_rewards.19="Ennätys: " +daily_rewards.20="Ohita" +daily_rewards.21="Voit ohittaa tämän videon rankkisi ansiosta." +daily_rewards.22="Ohita nämä videot, ostamalla rank kaupastamme." +daily_rewards.23="Katso tätä videota {$seconds} sekunnin ajan lunastaaksesi palkintosi!" +daily_rewards.24="Katso tämä video ja lunasta palkintosi!" +daily_rewards.25="{$game} -kolikkoa" +daily_rewards.26="Pelin {$game} kolikot" +daily_rewards.27="Mysteeripöly" +daily_rewards.28="Käytetään kosmeettisien esineiden työstämiseen" +daily_rewards.29="Hypixel EXP" +daily_rewards.30="Käytetään nostamaan Hypixel-leveliäsi" +daily_rewards.31="Mysteerilaatikko" +daily_rewards.32="Avaa saadaksesi kosmeettisia esineitä!" +daily_rewards.33="SkyWars -sielua" +daily_rewards.34="Käytetään SkyWarsin Sielukaivossa" +daily_rewards.35="Gift Box" +daily_rewards.36="Lähetä Mystery Box kaverillesi!" +daily_rewards.37="Housing-esine" +daily_rewards.38="Yksi kuudesta ainutlaatuisesta Housing-palikasta tässä setissä" +daily_rewards.39="Palkintomerkki" +daily_rewards.40="Jokainen merkki antaa sinulle yhden mahdollisuuden lisää avata Palkintokortteja" +daily_rewards.41="Yksi neljästä ainutlaatuisesta kosmeettisesta asun osasta" +daily_rewards.42="Ainutlaatuinen animoitu Emote-esine" +daily_rewards.43="Ainutlaatuinen animoitu Ele-esine" +daily_rewards.44="Aarteenmetsästäjän puku" +daily_rewards.45="Kypärä" +daily_rewards.46="Housut" +daily_rewards.47="Saappaat" +daily_rewards.48="Rintapanssari" +daily_rewards.49="Viikset-emote" +daily_rewards.50="Kaiva aarretta -ele" +daily_rewards.51="Housing-kuutio" +daily_rewards.52="Housing-kuutio" +daily_rewards.53="Housing-kuutio" +daily_rewards.54="Punainen aarrearkku" +daily_rewards.55="Sininen aarrearkku" +daily_rewards.56="Vihreä aarrearkku" +daily_rewards.57="Kultahippu" +daily_rewards.58="Ruukullinen kultaa" +daily_rewards.59="Rubikin kuutio" +daily_rewards.60="Säästöpossu" +daily_rewards.61="Parannusjuoma" +daily_rewards.62="Rahasäkki" +daily_rewards.63="Koristekypärä" +daily_rewards.64="Taskugalaksi" +daily_rewards.65="Mystinen helmi" +daily_rewards.66="Ketteryyshelmi" +daily_rewards.67="Kultainen pikari" +daily_rewards.68="Korulaatikko" +daily_rewards.69="Kruunu" +daily_rewards.70="Sulanut ydin" +daily_rewards.71="Manajuoma" +daily_rewards.72="Apua" +daily_rewards.73="Sulje" +daily_rewards.74="Huomasimme sinun käyttävän mainostenesto-ohjelmaa. Lunastaaksesi palkinnon sinun tulee asettaa mainostenesto-ohjelma pois päältä tällä sivulla." +daily_rewards.75="

KUINKA SE TOIMII

\n\nJoka kerta lunastaessasi palkintoa, pakasta vedetään 3 satunnaista korttia. Näissä korteissa olevat palkinnot sisältävät minipelien kolikoita, Hypixel-experienceä, Mystery Box -esineitä ja paljon muuta. Voit klikata yhtä näistä korteista lunastaaksesi siinä olevan palkinnon pelissä. Kun viet hiiren kortin päälle, saat lisätietoa palkinnosta.\n\nPalkintokortit voivat olla harvinaisuustasoltaan Yleisiä, Harvinaisia, Eeppisiä tai Legendaarisia. Yleinen esine on kaikkein arvottomin, ja Legendaarinen taas arvokkain ja vaikein löytää.\n\nTavallisesti voit lunastaa vain yhden palkinnon päivässä - ajastin nollautuu joka päivä keskiyöllä EST (04:00 UTC).\n\n

PALKINTOMERKIT

\n\nVoit käyttää Palkintomerkkejä lunastaaksesi enemmän palkintoja - yksi käytetty merkki Lähettimiehen luona sallii sinun lunastaa yhden palkinnon. Palkintomerkkejä taas voi löytää palkintokorteista, ja uusia tapoja löytää niitä saatetaan lisätä myöhemmin.\n\n

PÄIVITTÄINEN PUTKI

\n\nPalkintojärjestelmään kuuluu myös laskuri, joka laskee kuinka monena päivänä peräkkäin olet lunastanut palkintoja. Joka päivä kun lunastat palkinnon, kasvatat lukua, joka näkyy palkintosivulla netissä. Joka yhdeksäs päivä, kerättyäsi palkintoja päivittäin, saat yhden ilmaisen Palkintomerkin, jolla voit lunastaa yhden ylimääräisen palkinnon!\n\n

JAA SOSIAALISESSA MEDIASSA

\n\nKun olet lunastanut palkinnon, voit jakaa sen Twitterissä tai Facebookissa klikkaamalla kuvakkeita. Voit myös ladata kortin kuvan itsellesi voidaksesi siirtää sen muille nettisivuille tai vaikkapa tänne foorumeille!" \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/game_menu.properties b/configuration/i18n/fi_FI/official/game_menu.properties new file mode 100644 index 000000000..be6921bc1 --- /dev/null +++ b/configuration/i18n/fi_FI/official/game_menu.properties @@ -0,0 +1,298 @@ +game_menu.0="Pelivalikko (Oikeaklikkaa)" +game_menu.1="Oikeaklikkaa avataksesi Pelivalikon!" +game_menu.2="Peli käynnissä!" +game_menu.3="➠ Pelaajan %%player%% Network Booster" +game_menu.4="➠ %%multiplier%%" +game_menu.5="➠ Ei aktiivista boosteria :(" +game_menu.6="Kolikkokerroin: %%multiplier%%x" +game_menu.7="%%amount%% pelaamassa juuri nyt!" +game_menu.8="Palaa takaisin pelivalikkoon." +game_menu.9="Paintball" +game_menu.10="Nopeatempoinen ammuntapeli lumipalloilla." +game_menu.11="Yhden osuman tapot ja tappoputket\npitävät sinut taatusti hereillä!" +game_menu.12="The Walls" +game_menu.13="Neljä tiimiä taistelee voitosta\n15 minuutin valmistelujen\njälkeen. Erinomainen peli\npelaajille, jotka nauttivat\nnormaalista Minecraftin PvP:stä." +game_menu.14="Blitz Survival Games" +game_menu.15="Kaikille avoin selviytymispeli\nkiteillä. Ole ensimmäinen,\njoka löytää Blitz-tähden ja\ntaistele tiesi voittoon!" +game_menu.16="VampireZ" +game_menu.17="Ihmiset vastaan vampyyrit -peli.\nJos kuolet ihmisenä, synnyt\nuudestaan vampyyrina." +game_menu.18="Arcade" +game_menu.19="∙ Galaxy Wars" +game_menu.20="∙ Hole in the Wall" +game_menu.21="∙ The Blocking Dead" +game_menu.22="∙ Farm Hunt" +game_menu.23="∙ Creeper Attack" +game_menu.24="∙ Ender Spleef" +game_menu.25="∙ Bounty Hunters" +game_menu.26="∙ Dragon Wars" +game_menu.27="Quakecraft" +game_menu.28="Nopeatempoinen ammuntapeli sädeaseilla." +game_menu.29="Suositun Quake-pelin innoittama\nQuakecraft testaa nopeita\nampumistaitojasi ja refleksejäsi!" +game_menu.30="Mega Walls" +game_menu.31="Eeppinen 100 pelaajan peli\nhauskoilla ja uniikeilla luokilla.\nTuhoa vihollisten Wither estääksesi\nheitä syntymästä uudelleen." +game_menu.32="Cops n' Crims" +game_menu.33="Suositun FPS-pelisarja\nCounter-Striken innoittama\nasepeli." +game_menu.34="TNT Games" +game_menu.35="Hauskoja minipelejä, joissa mukana TNT:tä!" +game_menu.36="∙ TNT Run" +game_menu.37="∙ PVP Run" +game_menu.38="∙ Bow Spleef" +game_menu.39="∙ TNT Tag" +game_menu.40="∙ TNT Wizards" +game_menu.41="Arena Brawl" +game_menu.42="UHC" +game_menu.43="Tiimipohjainen selviytymispeli, jossa on\n111 pelaajaa. Satunnaisesti luodut\nmaailmat, vanilla PvP, kustomoitu\ntyöstäminen sekä uniikit kitit ja\nammatit odottavat sinua." +game_menu.44="Warlords" +game_menu.45="SkyWars" +game_menu.46="Hypixelin versio tunnetusta SkyWars-pelistä." +game_menu.47="Sisältää Kuoleman enkelin, Sielukaivon ja INSANE-pelimuodon!" +game_menu.48="Pelaa yksin tai tiimeissä." +game_menu.49="Pixel Painters" +game_menu.50="Piirrä annettuun aiheeseen liittyvä mestariteos!" +game_menu.51="Käytä laajaa työkalujen valikoimaa\nsaadaksesi aikaan luovan taideteoksen!\nAnsaitse muiden pelaajien äänet voittaaksesi!" +game_menu.52="Build Battle" +game_menu.53="Turbo Kart Racers" +game_menu.54="Kilpaile 11 muuta kilpa-ajajaa\nvastaan syöksyen voittoon!" +game_menu.55="Kustomoi autoasi ja käytä\nesineitä apunasi ollaksesi\nkaikista nopein." +game_menu.56="Player Housing" +game_menu.57="Kustomoi ja rakenna omalle\nhenkilökohtaiselle tontillesi,\nhengaile kavereiden kanssa,\nvieraile muiden tonteilla ja\npaljon muuta!" +game_menu.58="Crazy Walls" +game_menu.59="16 pelaajaa tai tiimiä taistelee\nkahdessa pelimuodossa. Louhi, rakenna\nja käy vaihtokauppaa ennen kuin\nseinät tippuvat, ja ole viimeinen\npelaaja elossa!" +game_menu.60="Lucky Block -tila lisää\npeliin kaaosmaisia piirteitä!" +game_menu.61="Super Smash" +game_menu.62="Muuntaudu yhdeksi uniikeista\nsankareista ja vapauta voimasi\nTeam- tai Solo-taisteluissa\nlopullisesta herruudesta! Onnistutko\nISKEMÄÄN kilpailijasi pois\nareenalta ennen kuin he tekevät saman sinulle?" +game_menu.63="Football" +game_menu.64="Tämä on jalkapalloa, sinun pitäisi\nkyllä tietää, miten sitä pelataan!" +game_menu.65="Speed UHC" +game_menu.66="Nopeatempoinen versio suositusta\nUHC-pelimuodosta." +game_menu.67="Sisältää Kyyneliä, Suolaa ja Netherin!" +game_menu.68="Pelaa itsenäisesti tai tiimeittäin." +game_menu.69="Mini Walls" +game_menu.70="Neljä 4 hengen tiimiä ottaa\ntoisistaan mittaa tässä nopea-\ntempoisessa PvP-arcadepelissä!" +game_menu.71="Valitse yksi kolmesta kitistä ja\nsuojaa Mini Witheriäsi voidaksesi\nsyntyä uudelleen." +game_menu.72="Pelit kestävät alle 5 minuuttia!" +game_menu.73="SULJETTU BETA" +game_menu.74="SUOSITTU!" +game_menu.75="AVOIN BETA" +game_menu.76="UUSI PELI!" +game_menu.77="UUSI!" +game_menu.78="Selviytyminen" +game_menu.79="Kilpailullinen" +game_menu.80="Tiimiselviytyminen" +game_menu.81="Ammuntapeli" +game_menu.82="Rennot pelit" +game_menu.83="Hardcore-selviytyminen" +game_menu.84="Domination" +game_menu.85="Suositeltu Arcade-peli" +game_menu.86="Erikoistapahtuma" +game_menu.87="Housing" +game_menu.88="Kilpa-ajo" +game_menu.89="UUSI PÄIVITYS!" +game_menu.90="Saa eniten ääniä 16 pelaajasta voittaaksesi!" +game_menu.91="Jouluinen Build Battle" +game_menu.92="Rakastatko Build Battlea? Tämä uusi\njouluversio sisältää yli sata jouluista\naihetta ja on auki vain rajoitetun ajan!" +game_menu.93="Grinch Simulator" +game_menu.94="Pilaa kaikkien joulu varastamalla\neniten lahjoja tässä parkourin\ninspiroimassa keräilypelissä.\nVarasta enemmän lahjoja kuin\nkukaan muu voittaaksesi!" +game_menu.95="Prototype" +game_menu.96="Hullunhauskoja minipelejä\npelattavaksi kavereiden kanssa!" +game_menu.97="VAROITUS!\nTämä on todellinen hardcore-kokemus, \nei suositella uusimmille pelaajille." +game_menu.98="Pelaa Maagina, Soturina, Shamaanina tai\nPaladiinina CTF- tai Domination-\npelimuodoissa. Osallistu ennennäkemättömän \neeppisiin PvP-taisteluihin, jotka sisältävät\nkustomoituja 3D-aseita ja kypäriä \nsekä paljon muuta!" +game_menu.99="PTL on paikka uusien, hauskojen\nja luovien minipelien ja järjestelmien\ntestaamiseen Hypixelissä." +game_menu.100="Hypixel-level %%level%%" +game_menu.101="UHC Champions" +game_menu.102="Bed Wars" +game_menu.103="Zombies" +game_menu.104="Suojele sänkyäsi tiimikavereidesi\nkanssa ja tuhoa muiden sängyt\nvoittaaksesi!" +game_menu.105="Työskentele tiimikavereidesi kanssa\ntuhotaksesi zombien ja muiden\nepäkuolleiden laumat! Selviydy\nniin pitkään kuin mahdollista." +game_menu.106="Classic Lobby on keskus kaikille klassisille\nHypixelin minipeleille, kuten:" +game_menu.107="∙ VampireZ" +game_menu.108="∙ Quakecraft" +game_menu.109="∙ Paintball Warfare" +game_menu.110="∙ Arena Brawl" +game_menu.111="∙ The Walls" +game_menu.112="∙ Turbo Kart Racers" +game_menu.113="Murder Mystery" +game_menu.114="∙ Duels" +game_menu.115="∙ Murder Mystery" +game_menu.116="∙ Zombies" +game_menu.117="Smash Heroes" +game_menu.118="Cops and Crims" +game_menu.119="∙ Party Games 1 / 2 / 3" +game_menu.120="∙ Hypixel Says" +game_menu.121="∙ Pixel Painters" +game_menu.122="∙ Throw Out" +game_menu.123="∙ Football" +game_menu.124="∙ Mini Walls" +game_menu.125="JULKAISTU!" +game_menu.126="Yksi murhaaja. Yksi etsivä.\nJa koko liuta syyttömiä.\nSelviätkö tässä jännittyneessä\nsosiaalisessa petoksen ja\nmurhan pelissä?" +game_menu.127="UUSI PTL-PELI!" +game_menu.128="Arcade Games" +game_menu.129="The TNT Games" +game_menu.130="∙ Build Battle" +game_menu.131="Lisää pelejä lisätään pian!" +game_menu.132="Tulossa pian" +game_menu.133="PÄIVITETTY!" +game_menu.134="Rakenna aiheeseen liittyvä rakennelma\nvain viidessä minuutissa! Arvostele\nkilpailijoiden aikaansaannoksia\nvälillä \"Aivan kakka\" ja \"Legendaarinen\"." +game_menu.135="∙ Blitz Duels" +game_menu.136="∙ TNT Games Duels" +game_menu.137="∙ Sumo Duels" +game_menu.138="Nopeatempoiset 1v1, 2v2, 4v4 ja Tournament Duelit!" +game_menu.139="∙ King of the Hill" +game_menu.140="Tiimipohjainen selviytymispeli, jossa on 111 pelaajaa. Satunnaisesti luodut maailmat, vanilla PvP, kustomoitu työstäminen sekä uniikit kitit ja ammatit odottavat sinua." +game_menu.141="Suojele sänkyäsi tiimikavereidesi kanssa ja tuhoa muiden sängyt voittaaksesi!" +game_menu.142="Rakenna aiheeseen liittyvä rakennelma vain viidessä minuutissa! Arvostele kilpailijoiden aikaansaannoksia välillä \"Aivan kakka\" ja \"Legendaarinen\"." +game_menu.143="Taistele joukkueissa siitä, kuka pääsee sillan yli ja tekee maalin. Ensimmäinen tiimi joka saa 5 maalia voittaa!" +game_menu.144="Neljä 4 hengen tiimiä ottaa toisistaan mittaa tässä nopeatempoisessa PvP-arcadepelissä" +game_menu.145="Valitse 1 kolmesta kitistä ja puolusta Mini Witheria voidaksesi syntyä uudelleen" +game_menu.146="Pelit kestävät alle 5 minuuttia!" +game_menu.147="Suositun FPS-pelisarja Counter-Striken innoittama asepeli." +game_menu.148="Yksi murhaaja. Yksi etsivä. Ja koko liuta syyttömiä. Selviätkö tässä jännittyneessä sosiaalisessa petoksen ja murhan pelissä?" +game_menu.149="Eeppinen 100 pelaajan peli hauskoilla ja uniikeilla luokilla. Tuhoa vihollisten Wither estääksesi heitä syntymästä uudelleen." +game_menu.150="Kustomoi ja rakenna omalle henkilökohtaiselle tontillesi, hengaile kavereiden kanssa, vieraile muiden tonteilla ja paljon muuta!" +game_menu.151="Sisältää Angel of Deathin, Soul Wellin ja INSANE MODE:n!" +game_menu.152="PTL on paikka uusien, hauskojen ja luovien minipelien ja järjestelmien testaamiseen Hypixelissä." +game_menu.153="∙ Capture The Wool" +game_menu.154="∙ The Pit" +game_menu.155="Muuntaudu yhdeksi uniikeista sankareista ja vapauta voimasi Team- tai Solo-taisteluissa lopullisesta herruudesta! Onnistutko ISKEMÄÄN kilpailijasi pois areenalta ennen kuin he tekevät saman sinulle?" +game_menu.156="Nopeatempoinen versio suositusta UHC-pelimuodosta." +game_menu.157="Sisältää Kyyneliä, Suolaa ja Netherin!" +game_menu.158="Pelaa Maagina, Soturina, Shamaanina tai Paladiinina CTF- tai Domination- pelimuodoissa." +game_menu.159="Osallistu ennennäkemättömän eeppisiin PvP-taisteluihin, jotka sisältävät kustomoituja 3D-aseita ja kypäriä sekä paljon muuta!" +game_menu.160="16 pelaajaa tai tiimiä taistelee kahdessa pelimuodossa. Louhi, Rakenna ja käy vaihtokauppaa ennen kuin seinät tippuvat, ja ole viimeinen pelaaja elossa!" +game_menu.161="Lucky Block -tila lisää peliin kaaosmaisia piirteitä!" +game_menu.162="Nopeatempoiset 1v1, 2v2, 4v4 ja Tournament Duelit!" +game_menu.163="∙ The Bridge" +game_menu.164="Työskentele tiimikavereidesi kanssa tuhotaksesi zombien ja muiden epäkuolleiden laumat! Selviydy niin pitkään kuin mahdollista." +game_menu.165="The Pit-pelissä hyppäät alas ihmismassaan ja taistelet yli 50 muun ihmisen kanssa." +game_menu.166="Hypixelin nopeatempoisin taistelupeli." +game_menu.167="Mene kartan keskelle kukkulan päälle ja tienaa pisteitä joukkueellesi!" +game_menu.168="Classic Lobby on keskus kaikille klassisille Hypixelin minipeleille, kuten:" +game_menu.169="Neljä tiimiä taistelee voitosta 15 minuutin valmistelujen jälkeen. Erinomainen peli pelaajille, jotka nauttivat normaalista Minecraftin PvP:stä." +game_menu.170="Yhden osuman tapot ja tappoputket pitävät sinut taatusti hereillä!" +game_menu.171="Ihmiset vastaan vampyyrit -teemainen piiloleikki. Jos kuolet ihmisenä, synnyt uudestaan vampyyrina." +game_menu.172="Kilpaile 11 muuta kilpa-ajajaa vastaan syöksyen voittoon!" +game_menu.173="Kustomoi autoasi ja käytä esineitä apunasi ollaksesi kaikista nopein." +game_menu.174="Suositun Quake-pelin innoittama Quakecraft testaa nopeita ampumistaitojasi ja refleksejäsi!" +game_menu.175="Piiloudu NPC-massaan ja yritä huomaamattomasti suorittaa tehtäviä tässä jännittävässä sosiaalisen päättelyn pelissä." +game_menu.176="Mekään emme enää tiedä mikä on totta!" +game_menu.177="Hide and Seek" +game_menu.178="King of the Hill" +game_menu.179="The Pit" +game_menu.180="The Bridge" +game_menu.181="Blitz SG" +game_menu.182="Duels" +game_menu.183="TOWERWARS!" +game_menu.184="UUSI ESINE!" +game_menu.185="UUSI LOBBY!" +game_menu.186="➠Kaksinkertaiset kolikot + EXP -viikonloppu" +game_menu.187="TowerWars" +game_menu.188="Tower Defense" +game_menu.189="Palaa Päälobbyyn" +game_menu.190="Lobby auki!" +game_menu.191="UUSI UHC-PELIMUOTO!" +game_menu.192="UUSI TIIMIPELIMUOTO!" +game_menu.193="Aseta torneja ja kutsu hirviöitä tienatessasi rahaa voittaaksesi 5 vastustajaasi!" +game_menu.194="%%purple%%UUSI PELIMUOTO!" +game_menu.195="UUSI PÄIVITYS!" +game_menu.196="Pysyvä peli" +game_menu.197="SkyBlock" +game_menu.198="The Hypixel Pit" +game_menu.199="SkyBlock on vihdoinkin saapunut Hypixeliin! Pelaa kavereidesi kanssa (tai yksin!), rakenna yksityinen saari ja kerää kaikki esineet!" +game_menu.200="The Pit-pelissä hyppäät alas ihmismassaan ja taistelet yli 50 muun ihmisen kanssa. Hypixelin nopeatempoisin taistelupeli." +game_menu.201="Hypixelin versio tunnetusta SkyWars-pelistä. Sisältää Kuoleman enkelin, Sielukaivon sekä INSANE MODE-pelimuodon! Pelaa yksin tai tiimissä." +game_menu.202="Yksi murhaaja. Yksi etsivä. Ja koko liuta syyttömiä. Selviätkö tässä jännittyneessä sosiaalisessa petoksen ja murhan pelissä?" +game_menu.203="Hullunhauskoja minipelejä pelattavaksi kavereiden kanssa!" +game_menu.204="Rakenna aiheeseen liittyvä rakennelma vain viidessä minuutissa! Arvostele kilpailijoiden aikaansaannoksia välillä \"Aivan kakka\" ja \"Legendaarinen\". Ansaitse eniten pisteitä kuudestatoista muusta pelaajasta voittaaksesi!" +game_menu.205="Nopeatempoisia 1v1, 2v2 ja 4v4 pelejä!" +game_menu.206="∙ UHC Deathmatch" +game_menu.207="∙ SkyBlock" +game_menu.208="∙ TowerWars" +game_menu.209="Pelaa Maagina, Soturina, Shamaanina tai Paladiinina CTF- tai Domination-pelimuodoissa. Osallistu ennennäkemättömän eeppisiin PvP taisteluihin, jotka sisältävät kustomoituja 3D-aseita ja kypäriä sekä paljon muuta!" +game_menu.210="16 pelaajaa tai joukkuetta taistelevat kahdessa pelimuodossa. Louhi, rakenna, ja käy vaihtokauppaa ennen kuin seinät tippuvat ja ole viimeisenä hengissä! Lucky Block -tila lisää peliin kaaosmaisia piirteitä!" +game_menu.211="∙ Party Games" +game_menu.212="∙ Hide and Seek" +game_menu.213="Liity %%mode%%-peliin" +game_menu.214="Solo" +game_menu.215="Doubles" +game_menu.216="3v3v3v3" +game_menu.217="4v4v4v4" +game_menu.218="Solo Normal" +game_menu.219="Solo Insane" +game_menu.220="Doubles Normal" +game_menu.221="Doubles Insane" +game_menu.222="Ranked" +game_menu.223="Mega Doubles" +game_menu.224="Creeper Attack" +game_menu.225="Farm Hunt" +game_menu.226="Zombies: Dead End" +game_menu.227="Zombies: Bad Blood" +game_menu.228="Zombies: Alien Arcadium" +game_menu.229="Hide and Seek: Prop Hunt" +game_menu.230="Hide and Seek: Party Pooper" +game_menu.231="Hypixel Says" +game_menu.232="Blocking Dead" +game_menu.233="Hole In The Wall" +game_menu.234="Bounty Hunters" +game_menu.235="Dragon Wars" +game_menu.236="Ender Spleef" +game_menu.237="Galaxy Wars" +game_menu.238="Throw Out" +game_menu.239="Solo Mode" +game_menu.240="Teams Mode" +game_menu.241="Pro Mode" +game_menu.242="Guess The Build" +game_menu.243="Bow Duel" +game_menu.244="Classic Duel" +game_menu.245="Potion Duel" +game_menu.246="Combo Duel" +game_menu.247="Blitz Duel" +game_menu.248="Bow Spleef Duel" +game_menu.249="Sumo Duel" +game_menu.250="Kolmen tiimit" +game_menu.251="TNT Run" +game_menu.252="PVP Run" +game_menu.253="Bow Spleef" +game_menu.254="TNT Tag" +game_menu.255="Wizards" +game_menu.256="Standard" +game_menu.257="Defusal" +game_menu.258="Team Deathmatch" +game_menu.259="1v1v1v1" +game_menu.260="2v2" +game_menu.261="2v2v2" +game_menu.262="1v1" +game_menu.263="Capture the Flag" +game_menu.264="Solo Lucky" +game_menu.265="Teams Normal" +game_menu.266="Teams Lucky" +game_menu.267="Klikkaa avataksesi" +game_menu.268="Liity satunnaiseen peliin." +game_menu.269="Satunnainen peli" +game_menu.270="BETA" +game_menu.271="Tarkastele peliin %%game%% saatavilla olevia kuvakkeita" +game_menu.272="Valitse pelivalikon kuvake" +game_menu.273="Aseta KAIKKI mukautetut valinnat takaisin oletuksiinsa." +game_menu.274="Pelivalikon mukautetut valintasi on nollattu oletuksiksi!" +game_menu.275="Klikkaa liittyäksesi" +game_menu.276="Lobby auki!" +game_menu.277="Kaikki tässä lobbyssa on tällä hetkellä vielä kehitteillä ja ne saatetaan poistaa milloin tahansa." +game_menu.278="Oikeaklikkaa vaihtaaksesi tätä paikkaa!" +game_menu.279="Nopeatempoinen versio suositusta UHC-pelistä, joka sisältää Netherin! Pelaa yksin tai tiimissä." +game_menu.280="∙ Capture the Wool" +game_menu.281="Selviytymispeli kiteillä tiiminä tai yksin. Ole ensimmäinen, joka löytää Blitz-tähden, ja taistele tiesi voittoon!" +game_menu.282="Wool Wars" +game_menu.283="Hypixel SMP" +game_menu.284="Luo oma SMP-palvelimesi Hypixelissä ja pelaa ystäviesi kanssa." +game_menu.285="∙ OP Duels" +game_menu.286="∙ Boxing Duels" +game_menu.287="∙ Parkour Duels" +game_menu.288="Face Off" +#game_menu.289="" # No translation available +#game_menu.290="" # No translation available +game_menu.291="Sheep Wars" +game_menu.292="Capture the Wool" +#game_menu.293="" # No translation available +game_menu.294="Wool Games" +#game_menu.295="" # No translation available +#game_menu.296="" # No translation available +#game_menu.297="" # No translation available \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/general.properties b/configuration/i18n/fi_FI/official/general.properties new file mode 100644 index 000000000..ef555e189 --- /dev/null +++ b/configuration/i18n/fi_FI/official/general.properties @@ -0,0 +1,5568 @@ +general.0="Pelin alkuun %%time%% sekuntia!" +general.1="Pelin alkuun %%time%% sekunti!" +general.2="%%player%% liittyi (%%count%%)!" +general.3="Oikeaklikkaa" +general.4="Klikkaa liittyäksesi" +general.5="Tulossa pian!" +general.6="Peruuta" +general.7="Vahvista" +general.8="Sulkee tämän valikon." +general.9="Oletko varma?" +general.10="Klikkaa ostaaksesi!" +general.11="Harvinaisuus: %%rarity%%" +general.12="Hinta: %%cost%%" +general.13="Vaaditaan Hypixel-level %%level%%" +general.14="VALITTU!" +general.15="Klikkaa valitaksesi!" +general.16="Ei pelaajia, joita voisi katsoa!" +general.17="Teleportteri" +general.18=" (Sivu %%page%%)" +general.19="Sivu %%page%%" +general.20="Katsoja-asetukset" +general.21="Ei nopeutta" +general.22="Sinulla ei enää ole nopeusefektiä!" +general.23="Nopeus %%tier%%" +general.24="Sinulla on nyt Nopeus %%tier%%!" +general.25="Voit nyt nähdä muut katsojat!" +general.26="Et voi enää nähdä muita katsojia!" +general.27="Näytä katsojat" +general.28="Klikkaa näyttääksesi muut katsojat!" +general.29="Piilota katsojat" +general.30="Klikkaa piilottaaksesi muut katsojat!" +general.31="Sinulla ei enää ole yönäköä!" +general.32="Sinulla on nyt yönäkö!" +general.33="Poista yönäkö käytöstä" +general.34="Klikkaa poistaaksesi yönäkö käytöstä!" +general.35="Ota yönäkö käyttöön" +general.36="Klikkaa ottaaksesi yönäkö käyttöön!" +general.37="Et enää automaattisesti teleporttaa kohteiden luo!" +general.38="Kun valitset pelaajan kompassistasi, sinut teleportataan automaattisesti hänen luokseen!" +general.39="Ota automaattinen teleporttaus pois käytöstä" +general.40="Klikkaa poistaaksesi automaattinen teleporttaus käytöstä!" +general.41="Ota automaattinen teleporttaus käyttöön" +general.42="Klikkaa ottaaksesi automaattinen teleporttaus käyttöön!" +general.43="Voit nyt lopettaa lentämisen!" +general.44="Et voi enää lopettaa lentämistä!" +general.45="Poista jatkuva lentäminen käytöstä" +general.46="Klikkaa poistaaksesi jatkuva lentäminen käytöstä!" +general.47="Ota jatkuva lentäminen käyttöön" +general.48="Klikkaa ottaaksesi jatkuva lentäminen käyttöön!" +general.49="Kohde: " +general.50="EP: " +general.51="Luokka: " +general.52="Etäisyys: " +general.53="Teleportteri (Oikeaklikkaa)" +general.54="Oikeaklikkaa katsoaksesi pelaajia!" +general.55="Kohde kadotettiin (Oikeaklikkaa)" +general.56="Palaa lobbyyn (Oikeaklikkaa)" +general.57="Oikeaklikkaa poistuaksesi lobbyyn!" +general.58="Katsoja-asetukset (Oikeaklikkaa)" +general.59="Oikeaklikkaa muuttaaksesi katsoja-asetuksiasi!" +general.60="Pelaa uudelleen (Oikeaklikkaa)" +general.61="Oikeaklikkaa pelataksesi toisen pelin!" +general.62="Kaikki pelaajat" +general.63="Klikkaa näyttääksesi kaikki pelaajat!" +general.64="Olet jo valinnut tämän veriefektin." +general.65="Poistettiin veriefektit käytöstä." +general.66="Otettiin käyttöön veriefekti %%name%%." +general.67="Naamioiduttiin hahmoksi %%entityType%%!" +general.68="Asetettiin partikkelien laaduksi %%qualityType%%!" +general.69="Poistettiin partikkelit käytöstä!" +general.70="Sinulla on jo tämä laatutaso valittuna!" +general.71="%%frame%%" +general.72="Lue koko tarina: %%frame%%" +general.73="Lue koko tarina: [link]" +general.74="Järjestelmässä tapahtui virhe! Yritä uudelleen." +general.75="Koska olet VIP, voit luoda Guildin komennolla /guild create (nimi)" +general.76="Voit liittyä Guildiin riippumatta rankistasi. Selaile Guildeja:" +general.77="%%underline%%http://hypixel.net/forums/59" +general.78="%%DEFAULT%%%%msg%%" +general.79="Tavaraluettelon avaaminen epäonnistui, havaittiin virhe!" +general.80="Taistelutila aktivoitu!" +general.81="Odota %%color%%%%countdown%%s..." +general.82="Taistelutila deaktivoitu!" +general.83="Taistelutila peruttu!" +general.84="Teleportattiin pelaajan %%newPlayer%% luo!" +general.85="Teleporttaaminen peruttu!" +general.86="Teleportataan lobbyyn 3 sekunnissa... Klikkaa uudelleen peruaksesi teleporttaamisen!" +general.87="Hmm... Näyttäisi siltä, että musiikkisoitinta luodessa tapahtui virhe :(" +general.88="Sinulla on jo tämä ase valittuna!" +general.89="Valittiin %%gun%%!" +general.90="Puuttuvat osat: %%parts%%" +general.91="Nollaa %%name%%!" +general.92="Sinulla ei ole yhtään %%name%% valittuna!" +general.93="Olet jo ostanut tämän!" +general.94="Sinulla on jo tämä valittuna!" +general.95="Sinulla ei ole tarpeeksi kolikoita!" +general.96="Argumentteja puuttuu! Valitse olento!" +general.97="Autoa ei löydetty!" +general.98="Mene! Mene! Mene!!!!!" +general.99="Ei partikkeleita" +general.100="Poistettiin kaikki partikkelit käytöstä. Ei suositella ellei välttämätöntä!" +general.101="Matala laatu" +general.102="Vähentää merkittävästi näkemiesi partikkelien määrää." +general.103="Keskiverto laatu" +general.104="Vähentää näkemiesi partikkelien määrää." +general.105="Korkea laatu" +general.106="Näyttää kaikki partikkelit parasta pelikokemusta varten." +general.107="Klikkaa valitaksesi" +general.108="VALITTU" +general.109="Partikkelien laatu" +general.110="Partikkelien laatu" +general.111="Antaa sinun muuttaa tai poistaa käytöstä partikkeleita ja niiden määrää." +general.112="Mahdolliset arvot: %%values%%" +general.113="Ei löydetty. Mahdolliset arvot: %%values%%" +general.114="Enimmäismäärä partikkeleita pykälää kohden nyt: %%amount%%" +general.115="Guildin tiedot" +general.116="Et ole tällä hetkellä Guildissa." +general.117="Klikkaa oppiaksesi lisää!" +general.118="Nimi: %%name%%" +general.119="Guild-arvonimi: %%rank%%" +general.120="Päivittäinen raja: %%coins%%/%%max%%" +general.121="Aikaa päivittäisen rajan nollautumiseen %%timer%%" +general.122="Jäsenet: %%members%%/%%max%%" +general.123="Rank: %%rank%%" +general.124="Oletus" +general.125="Taso: %%level%%" +general.126="Tasonnousuun vaadittava experience: %%exp%%" +general.127="Saavutuspisteet: %%points%%" +general.128="Karma: %%karma%%" +general.129="Klikkaa nähdäksesi Hypixel Storen linkki." +general.130="Hahmon tiedot" +general.131="Kolikot yhteensä: %%coins%%" +general.132="Kolikot: %%coins%%" +general.133="Kauppa (Oikeaklikkaa)" +general.134="1. sija - %%player%%" +general.135="2. sija - %%player%%" +general.136="3. sija - %%player%%" +general.137="Voittaja: %%player%%" +general.138="Voittajatiimi: %%team%%" +general.139="Aktiivinen Booster" +general.140="Pelaajan %%name%% Network Booster" +general.141="%%prefix%%%%amount%% kolikkoa" +general.142="+%%amount%% kolikkoa" +general.143="Korjataan" +general.144="Taistelutila VAIN VIP!" +general.145="Pidä pohjassa %%time%% sekunnin ajan aktivoidaksesi taistelutilan." +general.146="Sallii sinun taistella muita pelaajia vastaan." +general.147="Vaatii vähintään rankin %%rank%%!" +general.148="Osta %%rank%% osoitteessa https://store.hypixel.net" +general.149="Taistelutila (Pidä pohjassa ja odota)" +general.150="Pidä pohjassa 5 sekunnin ajan aktivoidaksesi taistelutilan." +general.151="Peli alkaa %%time%% sekunnin kuluttua!" +general.152="Poistuaksesi pelistä %%game%% kirjoita /lobby" +general.153="Ei tarpeeksi pelaajia! Pelin aloitus peruttiin." +general.154="%%player%% poistui!" +general.155="Kartta: %%world%%" +general.156="Pelaajia: %%size%%/%%max%%" +general.157="Odotetaan..." +general.158="Aikaa alkuun %%time%%s" +general.159="Alkanut!" +general.160="Palvelin: %%server%%" +general.161="Oletko AFK? Sinut saatetaan potkia, jos olet AFK!" +general.162="Sinut potkittiin, sillä olit AFK pelin aikana!" +general.163="Olet jo avannut tämän tason!" +general.164="Uudelleenladataan..." +general.165="Valmis!" +general.166="Tapahtui virhe." +general.167="Sinulla on jo aktiivinen booster!" +general.168="Boosterin käyttö peruttiin." +general.169="Sinulla ei ole yhtään Boosteria pelissä %%gameType%%!" +general.170="Sinulla on jo aktiivinen Booster pelissä %%gameType%%!" +general.171="Sinulla ei ole yhtään aktivoitavaa Network Boosteria!" +general.172="Sinulla on jo aktiivinen Network Booster!" +general.173="Peruttiin boosterin aktivointi." +general.174="Et voi käyttää komentoja katsojana!" +general.175="Emme löytäneet pelaaja, jonka luokse teleportata sinut!" +general.176="Sinut teleportattiin pelaajan %%PlayerManager%% luo" +general.177="Lähetetään sinut kohteeseen %%session%%!" +general.178="Ei peliä, johon liittyä uudelleen. Tämä tapahtuu yleensä silloin, kun edellinen pelisi on jo päättynyt, eikä sinulla ole syytä huoleen." +general.179="Kokonaispisteet" +general.180="Kaikki voitot" +general.181="Kaikki tapot" +general.182="Kuukausittaiset tapot" +general.183="Viikoittaiset tapot" +general.184="Ei löydetty tulostaulukon dataa." +general.185="Tätä komentoa voi käyttää vain minipeleissä ja minipelien lobbyissa." +general.186="Tätä komentoa voi käyttää vain lobbyissa!" +general.187="Anteeksi, mutta tuo ei ole pätevä käyttäjänimi!" +general.188="En löytänyt pelaajaa tuolla nimellä!" +general.189="Klikkaa suorittaaksesi komennon /resource resurssipaketin saamiseksi!" +general.190="Hypixel-leveling -valikko on tällä hetkellä poissa käytöstä. Yritä myöhemmin uudelleen!" +general.191="Sinun täytyy olla %%rank%% voidaksesi käyttää tätä komentoa!" +general.192="Tehtävä suoritettu: Avaruustehtävä" +general.193="Sait: 1875 experienceä" +general.194="Klikkaa nähdäksesi Hypixel-level -palkinnot" +general.195="Ystävät" +general.196="Virhe havaittiin, pyydämme ottamaan yhteyttä ylläpitoon." +general.197="Ladataan..." +general.198="Ei ystäviä?" +general.199="Käytä komentoa /friend add lisätäksesi kavereita!" +general.200="Edellinen sivu" +general.201="Seuraava sivu" +general.202="Ole hyvä ja yritä uudelleen hetken kuluttua!" +general.203="Ladataan, ole hyvä ja odota..." +general.204="Jokin meni vikaan!" +general.205="Sinun täytyy olla guildissa voidaksesi käyttää tätä!" +general.206="Sinun on oltava Guildin johtaja voidaksesi käyttää tätä!" +general.207="Osta" +general.208="Peruuta" +general.209="Aktivoi yllä olevan esineen. Ei voida perua." +general.210="Sulkee tämän valikon." +general.211="30 minuuttia!" +general.212="1 tunti!" +general.213="3 tuntia!" +general.214="??? tuntia!" +general.215="%%purchaser%% aktivoi triplakolikot %%length%% ajaksi" +general.216="Ansaitse Karmaa suorittamalla /tip ja /thanks tälle pelaajalle!" +general.217="Pelaajan %%purchaser%% Network Booster päättyi!\nNetwork Boosters ovat saatavilla osoitteessa http://store.hypixel.net/" +general.218="Klikkaa siirtyäksesi seuraavalle sivulle!" +general.219="Klikkaa siirtyäksesi edelliselle sivulle!" +general.220="Pelivalikko" +general.221="Klikkaa avataksesi pelivalikon!" +general.222="Pää" +general.223="Seikkailu" +general.224="Lobbyn valinta" +general.225="Poissa päältä!" +general.226="%%name%% Lobby #%%number%%" +general.227="Pelaajia: %%players%%/%%max%%" +general.228="Olet jo täällä!" +general.229="Olet jo lobbyssa %%name%% Lobby #%%number%%" +general.230="Paikalla olevat kaverit:" +general.231="Täynnä!" +general.232="Tämä lobby on tällä hetkellä täynnä!" +general.233="Klikkaa yhdistääksesi!" +general.234="%%name%% Lobby #%%number%%" +general.235="Party on täynnä!" +general.236="Jokin meni vikaan. Yritä uudelleen." +general.237="Havaittiin virhe käsiteltäessäsi kyltin klikkaustasi. Yritä uudelleen." +general.238="Yrität tehdä tuota liian nopeasti. Yritä uudelleen hetken kuluttua." +general.239="Jono on tällä hetkellä poissa päältä. Yritä uudelleen hetken kuluttua!" +general.240="Tuossa kyltissä ei ole karttaa! Kokeile toista kylttiä!" +general.241="Hidasta hieman!" +general.242="Tulossa pian!" +general.243="Kartan valinta" +general.244="Pelaat palvelimella MC.HYPIXEL.NET" +general.245="Olet jo lunastanut tämän palkinnon!" +general.246="Et voi lunastaa tätä palkintoa!" +general.247="Jokin meni vikaan, yritä uudelleen hetken kuluttua!" +general.248="Odota hetki, kun päivitämme pelaajaasi!" +general.249="Et ole vielä avannut (tai lunastanut) tätä!" +general.250="Olet jo valinnut tämän!" +general.251="Valittu!" +general.252="Et ole enää hevonen" +general.253="Äänestyssessioita ei ole tällä hetkellä auki!" +general.254="Ei löydetty kohdetta, jota voisit äänestää! Oletko äänestänyt meitä sessiosi ulkopuolella?" +general.255="Tämä toimitus on vanhentunut!" +general.256="Olet jo lunastanut tämän toimituksen!" +general.257="Osta se osoitteessa http://store.hypixel.net" +general.258="Tämä toimitus ei ole vielä saapunut! Tule takaisin myöhemmin!" +general.259="Toiminto ei kelpaa juuri nyt! Yritä myöhemmin uudelleen!" +general.260="Virhe! Tilaa ei löydetty!" +general.261="Jokin meni vikaan!" +general.262="Tietojasi päivitetään juuri! Odota pieni hetki ja yritä uudelleen!" +general.263="Olet jo lunastanut tämän lähetyksen! Tule takaisin %%EugeneUtils%% kuluttua!" +general.264="Ilmoita tämä henkilökunnalle: PAS:%%e%%" +general.265="Ilmoita tämä henkilökunnalle: RTP:%%e%%" +general.266="Ilmoita tämä henkilökunnalle: INV:%%e%%" +general.267="Sinulla ei ole tarvittavaa rankkia tätä bonusta varten! Osta rankkeja osoitteessa http://store.hypixel.net" +general.268="Olet jo vastaanottanut tämän palkinnon!" +general.269="Jokin meni vikaan. Yritä uudelleen hetken kuluttua!" +general.270="Tälle viikolle ei vielä ole avonaista kyselyä, tai sellaista ei ole suunnitteilla. Tule takaisin myöhemmin!" +general.271="Tälle viikolle ei ole avonaista kyselyä! Normaalisti tätä virheilmoitusta ei pitäisi näkyä! Ota yhteyttä ylläpitäjään, jos et ole vielä tehnyt niin!" +general.272="Sinulle ei ole avonaista kyselyä! Seuraava toimitus: %%delivery%%" +general.273="Jotain kummallista tapahtui sisäisissä järjestelmissä!" +general.274="Kysymys: %%data%%" +general.275=" (Klikkaa vaihtoehtoa alhaalla)" +general.276="Älä käytä tätä komentoa ilman, että käytät sitä Lähettimiehen kautta." +general.277="Et ole kelvollinen suorittamaan tätä toimintoa, yritä uudelleen %%cooldown%% päästä." +general.278="Vastasit kyselyyn vastauksella \"%%response%%\"! Sait 15,000 XP ja 5,000 Arcade-kolikkoa!" +general.279="Tämä palkinto ei toimi tässä lobbyssa!" +general.280="Toiminto ei kelpaa juuri nyt, yritä myöhemmin uudelleen!" +general.281="Lisää lähetyksiä saattaa olla juuri saapunut! Tarkasta heti!" +general.282="Uusia paketteja saapui juuri!" +general.283="%%data%%" +general.284=" %%response%%. %%response%%" +general.285="Viikko: %%data%% | ID: %%data%%" +general.286="Kyselyä ei löytynyt!" +general.287="Lähettimies on tällä hetkellä poissa käytöstä! Yritä myöhemmin uudelleen!" +general.288="Tämänpäiväinen äänestyslinkki on %%url%%" +general.289="Klikkaa tästä siirtyäksesi äänestyssivulle!" +general.290="Seuraa nettisivulla olevia ohjeita lunastaaksesi 5,000 XP ja 3,000 Arcade-kolikkoa!" +general.291="Klikkaa lunastaaksesi!" +general.292="Aikaa toimituksen saapumiseen on %%arrive%%" +general.293="Vanhenee ajassa %%time%%" +general.294="Klikkaa lunastaaksesi!" +general.295="Kesä" +general.296="Vaatii rankin %%rank%%" +general.297="Olet jo lunastanut tämän toimituksen, tule myöhemmin takaisin!" +general.298="Klikkaa lunastaaksesi!" +general.299="Kysely" +general.300="Tämän viikon kysely ei ole vielä auki!" +general.301="Vastattiin viikoittaiseen kyselyyn!" +general.302="Klikkaa avataksesi vastauksen!" +general.303="Klikkaa antaaksesi vastauksen %%response%%!" +general.304="Virheellinen valinta!" +general.305="%%amount%% toimitus! " +general.306="%%amount%% toimitusta! " +general.307="%%amount%% toimitus! " +general.308="%%amount%% toimitusta! " +general.309="Ei sessioita saatavilla tällä hetkellä! Tule myöhemmin takaisin!" +general.310="Se oli siinä tältä päivältä!\nSeuraava toimitus: %ttn!" +general.311="Älä aja ajoneuvolla" +general.312="Älä lennä" +general.313="Tämä ominaisuus ei ole käytössä." +general.314="Sinun täytyy olla %%rank% voidaksesi liittyä tälle palvelimelle." +general.315="Ansaitse ilmaisia kolikoita klikkaamalla tätä viestiä" +general.316="Pelaat palvelimella %%name%%" +general.317="Sait 15,000 EXP nettisivujen käyttäjäsi yhdistämisestä!" +general.318="Sinulla on %%amount%% tasopalkinto lunastamatta!" +general.319="Klikkaa tästä katsellaksesi sitä!" +general.320="Sinulla on %%amount%% tasopalkintoa lunastamatta!" +general.321="Klikkaa tästä tarkastellaksesi niitä!" +general.322="Sinut on hiljennetty syystä %%reason%% ajaksi %%time%%." +general.323="Sinut on hiljennetty ajaksi %%time%%." +general.324="Näet nyt chatin!" +general.325="Et enää näe chattia!" +general.326="Sinulla ei ole oikeuksia käyttää tätä komentoa!" +general.327="Et ole tykännyt meistä Facebookissa! Jos tämä on virhe, kokeile kirjautua uudelleen!" +general.328="Sait 250 kolikkoa jokaiseen peliin, koska tykkäsit meistä Facebookissa!" +general.329="Väärä koodi! Jos tykkäsit meistä ihan äskettäin, kokeile uudelleen!" +general.330="Sinulla ei ole oikeuksia tehdä noin!" +general.331="Asetettu julkinen chat päälle!" +general.332="Asetettu julkinen chat pois päältä!" +general.333="Asetettu julkinen chat päälle!" +general.334="Asetettu julkinen chat pois päältä!" +general.335="Olet nyt OP." +general.336="Et ole enää OP." +general.337="/myfilter add (sana) - Lisää sanan suodattimeesi." +general.338="/myfilter remove (sana) - Poistaa sanan suodattimestasi." +general.339="/myfilter list - Näyttää kaikki sanat suodattimessasi." +general.340="/myfilter clear - Tyhjentää suodattimesi." +general.341="Syötä sana, jonka haluat lisätä!" +general.342="Sinulla on jo 16 sanaa, et voi lisätä enempää!" +general.343="Tuo sana on jo suodattimessasi!" +general.344="Sana %%word%% lisättiin suodattimeesi!" +general.345="Täydennä sana poistaaksesi!" +general.346="Tuota sanaa ei löydy suodattimestasi!" +general.347="Sana %%word%% poistettiin suodattimestasi!" +general.348="Tyhjä " +general.349="Suodatetaan: %%filter%%" +general.350="Poistettiin %%size%% sana suodattimestasi!" +general.351="Poistettiin %%size%% sanaa suodattimestasi!" +general.352="Lobbyn valinta (Oikeaklikkaa)" +general.353="Oikeaklikkaa siirtyäksesi lobbysta toiseen!" +general.354="Käytä tätä pysyäksesi ystäviesi kanssa." +general.355="Saavutukset (Oikeaklikkaa)" +general.356="Oikeaklikkaa tarkkaillaksesi saavutuksiasi!" +general.357="Asetusvalikko" +general.358="Oikeaklikkaa avataksesi asetukset" +general.359="Pelaajat: Näkyvissä (Oikeaklikkaa)" +general.360="Oikeaklikkaa näyttääksesi tai piilottaaksesi pelaajat!" +general.361="Pelaajat: Piilotettu (Oikeaklikkaa)" +general.362="Sinun on käytettävä Minecraft-versiota 1.8 pelataksesi Adventuresia!" +general.363="Sinulle annettiin pakkaus %%package%%!" +general.364="Sinulle annettiin pakkaus %%package%% pelityypissä %%type%%!" +general.365="Et voi käyttää tätä!" +general.366="Ilotulitteet ovat poissa käytöstä!" +general.367="Sinun tulee odottaa 15 sekuntia ilotulitteiden ampumisen välillä!" +general.368="Et voi käyttää TPA-komentoa juuri nyt! Ilmoitathan ylläpidolle: (CORE_LINK_DOWN)" +general.369="Lumipallo on poissa käytöstä!" +general.370="Sinun täytyy odottaa luodaksesi lisää lumipalloja!" +general.371="Sinä loit 15 lumipalloa!" +general.372="Testipalvelimelle pääsy evättiin." +general.373="Testipalvelimelle pääsy hyväksyttiin. Voit nyt yhdistää osoitteeseen test.hypixel.net" +general.374="Olet juuri nyt parkourissa. Käytä komentoa /parkour reset" +general.375="Et ole nyt parkourissa. Käytä komentoa /parkour start" +general.376="Et ole nyt parkourissa." +general.377="Tämä palvelin on vielä käynnistymässä, yritä hetken kuluttua uudelleen!" +general.378="Älä tule lyödyksi :)" +general.379="Säteilet yhä %%generosity%%" +general.380="Jalomielisyyttä" +general.381="Profiilini (Oikeaklikkaa)" +general.382="Profiilini" +general.383="Tilastojen tarkkailu" +general.384="VIRHE!" +general.385="Klikkaa avataksesi!" +general.386="Aktiivinen boosterisi on vanhentunut." +general.387="Sulje" +general.388="Palaa takaisin" +general.389="Tulossa pian!" +general.390="Päivittäinen suositus" +general.391="Kokkailemme jotain juuri sinulle!" +general.392="Pidä tiukasti kiinni!" +general.393="Sivu" +general.394="Asetukset" +general.395="Asetukset & Näkyvyys" +general.396="Sallii sinun muokata ja hallita\nhenkilökohtaisia asetuksiasi." +general.397="Klikkaa muokataksesi asetuksiasi!" +general.398="Pelaajien näkyvyys" +general.399="Piilottaa tai näyttää pelaajat." +general.400="Lemmikkien näkyvyys" +general.401="Piilottaa tai näyttää lemmikit." +general.402="Lemmikin autoluonti" +general.403="Muuttaa sitä, syntyvätkö lemmikkisi automaattisesti liittyessäsi lobbyyn" +general.404="Veri & Hurme" +general.405="Piilottaa tai näyttää veren." +general.406="Chatin näkyvyys" +general.407="Piilottaa tai näyttää chatin." +general.408="Kaveripyynnöt" +general.409="Haluatko saada kaveripyyntöjä? Vaihda tilaa tästä." +general.410="Party-kutsut" +general.411="Haluatko saada party-kutsuja? Vaihda tilaa tästä." +general.412="Guild-kutsut" +general.413="Haluatko saada guild-kutsuja? Vaihda tilaa tästä." +general.414="Chat-ilmoitukset" +general.415="/lobby -suojaus" +general.416="Vahinkojen välttämiseksi sinun tulee kirjoittaa /lobby kaksi kertaa." +general.417="%%setting%% on nyt %%state%%!" +general.418="%%setting%% ovat nyt %%state%%!" +general.419="Käytössä" +general.420="Poissa käytöstä" +general.421="Klikkaa ottaaksesi käyttöön!" +general.422="Klikkaa poistaaksesi käytöstä!" +general.423="Sinulla ei ole tarpeeksi kolikoita ostaaksesi tuota!" +general.424="Tarvitset vielä %%cost%% mysteeripölyä!" +general.425="Sinun tulee olla vähintään tasolla %%required%%!" +general.426="Sinun tulee olla vähintään %%rank%% ostaaksesi tuon!" +general.427="Omistat jo tämän esineen!" +general.428="Sinun täytyy ostaa ensin %%name%% voidaksesi ostaa tämän!" +general.429="Olet jo valinnut tämän esineen!" +general.430="Sinulla on jo tämä taso!" +general.431="Olet jo ostanut korkeimman mahdollisen tason!" +general.432="Pelaajan %%state%% triplakolikot ovat käytössä tässä pelissä!" +general.433="Network Boosters ovat saatavilla osoitteessa http://store.hypixel.net/" +general.434="Peliäsi boostattiin pelaajan %%state%% triplakolikoilla!" +general.435="Sinulla ei ole oikeuksia tehdä noin!" +general.436="Chattisi on poissa käytöstä! Ota se uudelleen käyttöön komennolla /togglechat" +general.437="Chatti on nyt poissa käytöstä tavallisilta pelaajilta!" +general.438="Chat on nyt poissa käytöstä kaikilta!" +general.439="-----------------------------------------" +general.440="Aseta näköetäisyydeksesi %%inner%%" +general.441="Sinun täytyy odottaa 3s käyttökertojen välillä!" +general.442="Pelaajat piilotettu!" +general.443="Pelaajat näkyvillä!" +general.444="Olet nyt %%packageRank%%" +general.445="Lento poissa käytöstä!" +general.446="Lento käytössä!" +general.447="Ilotulite ammuttu!" +general.448="Lyöminen on väliaikaisesti poissa käytöstä tässä lobbyssa!" +general.449="Sinun tulee odottaa ennen kuin voit taas lyödä!" +general.450="Et voi lyödä tätä henkilöä!" +general.451="Tätä henkilöä on lyöty liian monta kertaa viimeisten 60 sekunnin aikana!" +general.452="Et voi lyödä ylläpidon jäseniä partyssa!" +general.453="Saatavilla vain lobbyissa!" +general.454="Vasenklikkaa kylttiä muokataksesi sitä!" +general.455="Sinulla ei ole kylttiä valittuna! Käytä komentoa /editsign select!" +general.456="Puuttuvia tietoja! /editsign line [teksti...]" +general.457="Kyltti päivitetty!" +general.458="Sinun tulee katsoa kylttiä kohti käyttääksesi tätä!" +general.459="Kyltti valittu! Käytä komentoa /editsign line [teksti...] muokataksesi kylttiä!" +general.460="Lopetetaan kylttien muokkaaminen!" +general.461="Puuttuvia argumentteja! /editsign " +general.462="Et voi lentää aloittaessasi parkouria!" +general.463="Et voi olla kulkuvälineen sisällä aloittaessasi parkouria!" +general.464="Poistuit aiemmasta parkourhaasteesta!" +general.465="Parkourhaaste aloitettu! Käytä komentoa /parkour reset aloittaaksesi uudelleen!" +general.466="Ajastin nollattu! Selvitä tiesi maaliin!" +general.467="Et voi lentää, jos haluat päättää parkourin!" +general.468="Et voi olla kulkuvälineen sisällä, jos haluat päättää parkourin!" +general.469="Tämä on parkourin maaliviiva! Mene takaisin alkuun vain kiivetäksesi takaisin tänne!" +general.470="Uusi ennätysaika %%timeTook%%! Yritä uudelleen saadaksesi vieläkin paremman ajan!" +general.471="Saavuit Tallennuspisteelle #%%checkpoint%%. Voit käyttää komentoa /parkour checkpoint päästäksesi takaisin tähän paikkaan." +general.472="Parkourhaaste epäonnistui! %%message%%!" +general.473="Parkourhaaste epäonnistui! Sinulla kului yli 10 minuuttia!" +general.474="Pahoittelut, yritä uudelleen hetken kuluttua!" +general.475="Tätä ominaisuutta ei ole vielä julkaistu!" +general.476="Sinulla ei ole tarpeeksi mysteeripölyä työstääksesi tuota!" +general.477="Tämä peli on tulossa pian!" +general.478="Virhe ilmaantui suorittaessa tuota. Yritä uudelleen." +general.479="Onnittelut! Palkintosi on %%prize%%" +general.480="Ethän spämmää, kiitos!" +general.481="Emme ole ladanneet vielä suosituksia sinulle! Odota hetki!" +general.482="Valitettavasti sinua ei voitu teleportata tuon pelaajan luokse!" +general.483="Virhe ilmaantui, ilmoitathan siitä!" +general.484="Sinulla ei ole partya, jonka voisit hajottaa!" +general.485="Odota hetki, yritämme ladata partyasi..." +general.486="+%%karma%% Karmaa!" +general.487="Tapahtui virhe QuestStoragessa! Otathan yhteyttä ylläpitoon!" +general.488="Aktivoitiin Smash Heroes EXP Booster!" +general.489="Status:" +general.490="%%i%%. %%Utilities%% %%objective%%" +general.491="Aloitit tehtävän %%quest%%!" +general.492="Et voi aloittaa tätä tehtävää juuri nyt!" +general.493="Ostit %%quantity%% kappaletta esinettä %%allow%%!" +general.494="Ostit esineen %%allow%%!" +general.495="Sinulla on nyt Nopeus %%net%%!" +general.496="Nyt näet tapahtumat omasta näkökulmastasi!" +general.497="Kun valitset kompassilla pelaajan, voit tarkkailla tapahtumia hänen näkökulmastaan!" +general.498="%%formatted%%!" +general.499="En voi auttaa sinua juuri nyt, tule takaisin myöhemmin! :(" +general.500="%%title%%" +general.501="%%subtitle%%" +general.502="Housing on väliaikaisesti poissa käytöstä huoltokatkon vuoksi ja palaa myöhemmin taas käyttöön!" +general.503="Tämä maailma on tulossa pian!" +general.504="Yritetään teleportata sinua pelaajan %%targetName%% luo..." +general.505="Jokin meni vikaan käsiteltäessä tätä. Yritä uudelleen." +general.506="Yritetään teleportata sinua talollesi..." +general.507="Yritetään teleportata sinua pelaajan %%targetName%% talolle..." +general.508="Nyt soi: %%name%%" +general.509="Et soittanut musiikkia!" +general.510="Musiikki pysähtyi." +general.511="Ansaitsit yhteensä %%val%% experienceä!" +general.512="Saavutukset" +general.513="Saavutukset" +general.514="Klikkaa tarkastellaksesi saavutuksiasi!" +general.515="Saavutusedut" +general.516="Pelivalikko" +general.517="Saavutusvalikko" +general.518="Näytä eri pelimuotojen saavutukset!" +general.519="Saavutusedut" +general.520="Näytä edistymisesi Saavutuksissa!" +general.521="Saavutuspisteet: %%points%%" +general.522="Superperkin taso %%tier%%" +general.523="Perkin taso %%tier%%" +general.524="Lukittu!" +general.525="%%points%% Saavutuspistettä" +general.526="Klikkaa nähdäksesi edistymisesi!" +general.527="Edistyminen: %%amount%%/%%required%%" +general.528="Haarniskan värin luoja" +general.529="%%verb%% Päähine" +general.530="%%verb%% Rintapanssari" +general.531="%%verb%% housut" +general.532="%%verb%% saappaat" +general.533="Nappaa" +general.534="Punainen" +general.535="Vihreä" +general.536="Sininen" +general.537="Klikkaa lisätäksesi %%color%%25 %%type%%!" +general.538="Boosters" +general.539="Kolikkoboosterit" +general.540="Klikkaa aktivoidaksesi boosterit!" +general.541="Henkilökohtaiset Boosterit" +general.542="Klikkaa nähdäksesi saatavilla olevat henkilökohtaiset boosterit!" +general.543="Booster" +general.544="Henkilökohtaiset Boosterit" +general.545="Klikkaa nähdäksesi saatavilla olevat legacy boosterit!" +general.546="Network Boosters" +general.547="Network Boosters" +general.548="Network Boosters" +general.549="Klikkaa nähdäksesi saatavilla olevat Network Boosters!" +general.550="Sinulla ei ole yhtään Network Boosteria saatavilla!" +general.551="Voit ostaa niitä osoitteessa %%store%%" +general.552="Sinulla ei ole yhtään henkilökohtaista boosteria saatavilla!" +general.553="Klikkaa nähdäksesi saatavilla olevat Network Boosters" +general.554="Booster-jonokomento ei ole tällä hetkellä toiminnassa. Yritä uudelleen hetken kuluttua!" +general.555="Sinulla ei ole oikeuksia käyttää tuota komentoa!" +general.556="Epäkelpo pituus! Syötä pituudeksi: " +general.557="Epäkelpo kerroin! Muoto: 1.5, 2.0, 10.0, jne." +general.558="Ei löydetty pelaajaa tuolla nimellä!" +general.559="%%length%% Booster - %%multiplier%%x kolikot" +general.560="Aktiivinen toiset %%time%%" +general.561="%%length%% Booster - %%multiplier%%x kolikot" +general.562="Klikkaa aktivoidaksesi tämä booster!" +general.563="Vahvista" +general.564="Aktivoi tämän Boosterin. Ei voida kumota." +general.565="Peruuta" +general.566="Sulkee tämän valikon." +general.567="KAIKKI PELIT" +general.568="Tehtävät & Haasteet" +general.569="Kolikot" +general.570="Hypixel\nExperience" +general.571="%%Name%% suoritettu!" +general.572="Voit suorittaa vielä %%remaining%% haastetta tänään." +general.573="Haasteita ei tarvitse erikseen aloittaa! Liity vain peliin ja suorita niitä!" +general.574="Olet jo aloittanut tehtävän %%name%% !" +general.575="Palkinnot:" +general.576="Palkinto: %%line%%" +general.577="Voit suorittaa saman haasteen\nuseita kertoja päivässä, mutta vain\nkerran yhdessä pelissä." +general.578="Haasteita jäljellä tänään: " +general.579="Päivittäiset tehtävät voidaan suorittaa kerran joka päivä." +general.580="Viikoittaiset tehtävät voidaan suorittaa kerran viikossa. Nollautuu torstaiyönä." +general.581="Voit suorittaa tämän tehtävän %%time%% kuluttua" +general.582="Olet jo suorittanut tämän kertaluontoisen tehtävän!" +general.583="Tehtävä nollautuu %%time%% kuluttua" +general.584="Et voi suorittaa tätä tehtävää vielä." +general.585="Vaaditaan taso %%level%%" +general.586="Olet jo aloittanut tämän tehtävän!" +general.587="Klikkaa aloittaaksesi tämä tehtävä." +general.588="Tarkastele kaikkia saatavilla olevia tehtäviä ja haasteita, joita voit suorittaa pelaamalla peliä %%game%%." +general.589="Klikkaa katsellaksesi!" +general.590="Hyväksy tehtäviä automaattisesti: PÄÄLLÄ" +general.591="Klikkaa lopettaaksesi tehtävien\nhyväksyminen aina liittyessäsi\npelin lobbyyn." +general.592="Hyväksy tehtäviä automaattisesti: POIS" +general.593="Klikkaa hyväksyäksesi automaattisesti\ntehtäviä aina liittyessäsi\npelin lobbyyn." +general.594="Hyväksy tehtäviä automaattisesti: POIS" +general.595="Vaatii rankin %%rank%%" +general.596="Tehtäviä ei enää hyväksytä automaattisesti!" +general.597="Tehtäviä hyväksytään nyt automaattisesti!" +general.598="Sinun tulee olla %%rank%% käyttääksesi tätä ominaisuutta!" +general.599="Kieleksi asetettiin %%name%%!" +general.600="%%name%%" +general.601="Asetettiin kieleksi %%name%%!" +general.602="Valitse kieli" +general.603="Asetettiin oletuskieli koko palvelimelle." +general.604="Klikkaa tästä jos haluat, että havaitsemme kielesi automaattisesti kun liityt Hypixeliin." +general.605="Klikkaa tästä jos haluat, että emme havaitse kieltäsi automaattisesti kun liityt Hypixeliin." +general.606="Automaattinen kielen havaitseminen: Kyllä" +general.607="Automaattinen kielen havaitseminen: Ei" +general.608="Emme enää havaitse kieltäsi automaattisesti!" +general.609="Havaitsemme kielesi nyt automaattisesti!" +general.610="Matkusta jonkun toisen talolle" +general.611="Hyppää kuumailmapalloon ja\nvieraile muiden taloilla." +general.612="Voit nähdä ihmiset, joiden taloissa\nvoit vierailla, kuten JULKINEN\ntai VAIN KAVEREILLE" +general.613="Klikkaa nähdäksesi taloja, joissa voit vierailla!" +general.614="Etsi tunnisteiden avulla" +general.615="Etsi taloja niiden omistajan\nasettamien tunnisteiden avulla" +general.616="Klikkaa tästä valitaksesi kategorian!" +general.617="Ei hakutuloksia" +general.618="Yksikään aktiivinen talo ei\nsopinut valitsemaasi\nhakutunnisteeseen!" +general.619="Klikkaa tästä hakeaksesi uudelleen!" +general.620="Kenelläkään ei ole taloa\njossa voisit juuri nyt vierailla!\nYritä myöhemmin uudelleen!" +general.621="Klikkaa tästä palataksesi päävalikkoon!" +general.622="Satunnainen talo" +general.623="Klikkaa vierallaksesi satunnaisella talolla" +general.624="Klikkaa vieraillaksesi!" +general.625="Talot joissa voi vierailla" +general.626="Suositellut maailmat" +general.627="Matkusta suositeltuun maailmaan" +general.628="Hyppää kuumailmapalloon ja\nvieraile suositellussa maailmassa.\nVoit liittyä maailmaan vaikka\nsen omistaja ei olisi paikalla." +general.629="Klikkaa nähdäksesi maailmat, joissa voit vierailla!" +general.630="Roolipeli" +general.631="Yleinen" +general.632="Parkour" +general.633="Ylläpito" +general.634="Sokkelo" +general.635="Chat" +general.636="Guild Hangout" +general.637="Ylläpito / Youtubettajat" +general.638="Klikkaa tyhjentääksesi\nsuodattimesi." +general.639="Klikkaa etsiäksesi\ntaloja, joiden omistaja on\nylläpidossa tai Youtubettaja!" +general.640="Klikkaa tyhjentääksesi\ntunnistesuodattimesi." +general.641="Klikkaa etsiäksesi taloja\ntällä tunnisteella." +general.642="Palaa takaisin" +general.643="Virhe!" +general.644="Klikkaa järjestääksesi Keksien määrän perusteella!" +general.645="Klikkaa palataksesi oletusjärjestykseen!" +general.646="Keksijärjestys" +general.647="Omistaja: %%name%%" +general.648="pelaajan %%owner%% talo" +general.649="Tämä talo on auki julkisesti." +general.650="Olet tämän henkilön partyssa." +general.651="Olet tämän henkilön kaveri." +general.652="Olet tämän henkilön guildissa." +general.653="Tämä talo on yksityinen." +general.654="Salasana vaaditaan." +general.655="Vierailusäännöt: " +general.656="Tunnisteet: %%wrapped%%" +general.657="Keksit: %%cookies%%" +general.658="Palikoita avattu: " +general.659="Vieraita nyt: " +general.660="Matkusta talollesi" +general.661="Hyppää kuumailmapalloon\nja matkusta Talollesi!" +general.662="Klikkaa mennäksesi talollesi!" +general.663="Seuraava toimitus: " +general.664="Suorittamalla tehtäviä ja haasteita\nansaitset %%coins%%, %%exp%% ja paljon muuta!\n\nVoit suorittaa enintään %%max%% \nhaastetta joka päivä.\n\nHaasteita suoritettu tänään: %%color%%%%completed%%\n\nKlikkaa nähdäksesi Tehtävät & Haasteet" +general.665="Veteraanipalkinnot" +general.666="Olet jo lunastanut tämän palkinnon!" +general.667="Klikkaa lunastaaksesi!" +general.668="Et voi lunastaa tätä vielä!" +general.669="Sinun tulee olla MVP+ lunastaaksesi tämän!" +general.670="%sHypixel-level -palkinto %d" +general.671="Hypixel-leveling" +general.672="Kolikkokerroin" +general.673="Avattu!" +general.674="Sinun tulee olla tasolla %%level%% avataksesi tämän perkin." +general.675="Kasvattaa ansaitsemiesi kolikoiden\nmäärää pelatessasi pelejä." +general.676="Sinulla on jo tämä, koska\nostit rankin %%rank%% ennen elokuuta 2014." +general.677="Avautuu automaattisesti saavuttaessasi\nvaaditun tason." +general.678="Arcade-kolikkoa" +general.679="Arcade-kolikoita voi vaihtaa\nmuiden pelien kolikoiksi\nArcade-lobbyssa." +general.680="+ %%banner%%-viiri" +general.681="Henkilökohtainen kolikkoboosteri" +general.682="Aktivoidaksesi kolikkoboosterin, mene\nProfiilini > Kolikkoboosterit tai kirjoita\n/booster" +general.683="Keltainen" +general.684="Vaaleanvioletti" +general.685="Valkoinen" +general.686="Tummanvihreä" +general.687="Tummanpunainen" +general.688="Turkoosi" +general.689="Tummanvioletti" +general.690="Tummanharmaa" +general.691="Musta" +general.692="+%%name%% %%color%%+ -vaihtoehto rankille %%rank%%" +general.693="Pelaamalla pelejä ja suorittamalla tehtäviä\nansaitset Hypixel-experienceä,\njota tarvitset noustaksesi tasoissa ylöspäin\nja saavuttaaksesi uusia etuja ja palkintoja!" +general.694="Tasonnousuun vaadittava experience: %%exp%%" +general.695="Klikkaa nähdäksesi palkintosi!" +general.696="Palkintoja kaikkein omistautuneimmille\npelaajille!" +general.697="Sinun tulee olla vähintään Hypixel-level 100\ntarkastellaksesi tätä valikkoa!" +general.698="Klikkaa nähdäksesi veteraanipalkintosi!" +general.699="Tehtävämuistio" +general.700="Suorittamalla tehtäviä ansaitset\nkolikoita, Hypixel-experienceä ja\npaljon muuta!" +general.701="Juttele Tehtävämestareille\npelien lobbyissa hyväksyäksesi tehtäviä." +general.702="Klikkaa nähdäksesi tehtävän edistyminen!" +general.703="MVP+-rankin väri" +general.704="Vaihda %%rank%%-rankin plussan\nväriksi %%name%%, jolloin tuloksena on MVP%%color%%+" +general.705="Näkyvillä tab-listassa sekä chatissa\nja liittyessä lobbyihin." +general.706="Oletusväri rankille %%rank%%." +general.707="Avautuu Hypixel-levelillä %%level%%" +general.708="Valittuna nyt!" +general.709="Onnittelut parkourin läpäisemisen johdosta! Aikasi oli %%timeTook%%! Yritä uudelleen parantaaksesi tulostasi!" +general.710="Aikasi %%timeTook%% ei rikkonut aiempaa ennätysaikaasi %%prevBestTime%%! Yritä uudelleen rikkoaksesi ennätyksesi!" +general.711="Kielenasettamiskomento on tällä hetkellä poissa käytöstä! Ole hyvä ja yritä myöhemmin uudelleen!" +general.712="Valittu kieli: %%language%%" +general.713="Valittu kieli: %%name%%" +general.714="Klikkaa linkkiä vieraillaksesi nettisivuillamme ja lunastaaksesi palkintosi: " +general.715="Klikkaa vieraillaksesi nettisivuillamme" +general.716="Olet jo lunastanut tämän palkinnon ja sinulla ei ole palkintomerkkejä! Palaa takaisin %%time%% kuluttua!" +general.717="Käytetään yksi palkintomerkki sillä olet jo lunastanut ilmaisen päivittäisen palkintosi! Sinulla on nyt %%tokens%% palkintomerkki!" +general.718="Käytetään yksi palkintomerkki sillä olet jo lunastanut ilmaisen päivittäisen palkintosi! Sinulla on nyt %%tokens%% palkintomerkkiä!" +general.719="Osta Network Boosters osoitteesta https://store.hypixel.net\n " +general.720="\n%%purchaser%% aktivoi 3x kolikot tähän peliin! Ansaitse XP ja kolikoita " +general.721="\nPeliäsi boostattiin pelaajan %%purchaser%% 3x kolikoiden Network Boosterilla! Ansaitse XP ja kolikoita " +general.722="KLIKKAAMALLA TÄSTÄ!" +general.723="Klikkaa suorittaaksesi /tip all" +general.724="Ladataan..." +general.725="Päivittäinen palkinto" +general.726="Päivittäinen palkinto" +general.727="Klikkaa tästä saadaksesi linkin chattiin!" +general.728="Olet lunastanut tämän palkinnon ja sinulla ei ole palkintomerkkejä! Palaa takaisin %%time%% kuluttua!" +general.729="\n%%purchaser%% aktivoi 3x kolikot tähän peliin! Ansaitse XP ja kolikoita komennolla » /TIP ALL«" +general.730="Osta Network Boosters osoitteesta https://store.hypixel.net\n " +general.731="✘ Pelaajan %%purchaser%% Network Booster vanhentui!\nOsta Network Boosters osoitteesta https://store.hypixel.net\n " +general.732="%%purchaser%% aktivoi 3x kolikot tähän peliin! Ansaitse XP ja kolikoita komennolla » /TIP ALL«" +general.733="Hypixel-experienceä" +general.734="SkyWars-sieluja" +general.735="Sinulla ei ole oikeuksia tehdä tuota!" +general.736="Sinulla ei ole oikeuksia tuohon komentoon!" +general.737="Tämä pelaaja ei ole paikalla!" +general.738="Komento: %%command%%" +general.739="Tavaraluettelosi tyhjennettiin!" +general.740="Sinulla ei ole oikeuksia tehdä tuota!" +general.741="Virheellinen syöte %%input%%, ole hyvä ja anna numero" +general.742="Virheellinen syöte %%input%%" +general.743="Oikeaklikkaa" +general.744="Vasenklikkaa" +general.745="Klikattava" +general.746="taivas" +general.747="aihe" +general.748="biomi" +general.749="sääntö" +general.750="sää" +general.751="ryhmä" +general.752="oikeus" +general.753="arvo" +general.754="pelaaja" +general.755="esine" +general.756="data" +general.757="rivi" +general.758="viesti" +general.759="teksti" +general.760="syy" +general.761="pelimuoto" +general.762="kolikot" +general.763="Chat on mykistetty %%time%% sekunnin ajaksi." +general.764="Automaattisesti aktivoitu: %%name%%" +general.765="Pysäytä kappale" +general.766="Pysäytä nykyinen kappale." +general.767="Salanimesi on nollattu!" +general.768="Sinulla ei ole salanimeä. Ota sellainen käyttöösi komennolla /nick (nimi)" +general.769="Tämä nimi on liian pitkä tai lyhyt käytettäväksi salanimenä!" +general.770="Salanimissä ei voi olla erikoismerkkejä!" +general.771="Salanimesi ei voi olla NPC-hahmon nimi! Valitse toinen nimi!" +general.772="Et voi käyttää salanimenäsi olemassa olevan pelaajan nimeä!" +general.773="Käytä komentoa:" +general.774="/nick - Aseta itsellesi satunnainen salanimi" +general.775="/nick reset - Nollaa salanimesi" +general.776="/nick check (nimi) - Tarkista kenellä on käytössään valittu salanimi" +general.777="Olet jo äänestänyt tätä karttaa!" +general.778="Äänesi on rekisteröity! %%text%%" +general.779="Klikkaa äänestääksesi!" +general.780="Arvostele tämä kartta klikkamalla:" +general.781="Suorittamalla tehtäviä ja haasteita\nansaitset %%coins%%, %%exp%% ja paljon muuta!" +general.782="Saavutukset: %%name%%" +general.783="Näytä %%achievements%%" +general.784="Näyttää sinun tilastosi\npelikohtaisesti ja yhteenvetona." +general.785="Pelaajat, joilla on MVP tai korkeampi\nvoivat käyttää komentoa /stats (nimi)\ntarkastellakseen muiden tilastoja" +general.786="Klikkaa tarkastellaksesi tilastojasi!" +general.787="Voit suorittaa enintään %%max%% \nhaastetta joka päivä." +general.788="Haasteita suoritettu tänään: %%color%%%%completed%%" +general.789="Klikkaa nähdäksesi Tehtävät & Haasteet" +general.790="Hidasta vähän!" +general.791="OIKEAKLIKKAA" +general.792="OIKEAKLIKKAA" +general.793="Uusi päivittäinen palkinto!" +general.794="%%tokens%% päivittäinen palkintomerkki!" +general.795="%%tokens%% päivittäistä palkintomerkkiä!" +general.796="%%amount%% toimitus!" +general.797="%%amount%% toimitusta!" +general.798="Alku" +general.799="Loppu" +general.800="Tallennuspiste" +general.801="Hypixel tukee käännöksiä seuraaville peleille:" +general.802="Päätit olla vaihtamatta kieltäsi!" +general.803="Klikkaa katsoaksesi!" +general.804="Klikkaa näyttääksesi vain tiimin %%team%%!" +general.805="Pahoittelemme, että sinulla on ongelmia resurssipaketin kanssa. Varmista, että olet sallinut resurssipaketit palvelimen asetuksissa.\n\nVoit myös käyttää komentoa %%command%% yrittääksesi pakottaa resurssipaketin lataamisen\n\nJos tarvitset lisää apua, klikkaa alla olevaa linkkiä:\n%%link%%" +general.806="Osta %%rank%% osoitteessa https://store.hypixel.net voidaksesi luoda Guildin." +general.807="Sinun täytyy olla %%rank%% voidaksesi valita tämän!" +general.808="Sinun täytyy olla %%rank%% voidaksesi valita tämän!" +general.809="Sinulla täytyy olla vähintään %%rank%% voidaksesi lunastaa tämän toimituksen!" +general.810="Sinun tulee olla %%rank%% käyttääksesi pikaliittymisominaisuutta! Voit tosin aina käyttää kylttejä!" +general.811="Sinun on oltava %%rank%% käyttääksesi tätä levysoitinta! Osta %%rank%% osoitteessa http://store.hypixel.net/" +general.812="Voit liittyä Guildiin komennolla /guild join\nhuolimatta rankistasi." +general.813="Pelaajat, joilla on %%rank%% tai korkeampi\nvoivat luoda Guildeja komennolla /guild create." +general.814="Lähettimies" +general.815="Saavutus avattu:" +general.816="Tehtävämestari" +general.817="TULOSSA PIAN" +general.818="2000 XP -toimitus" +general.819="Ansaitse 2000 experienceä joka päivä!\nKlikkaa lunastaaksesi!" +general.820="2000 XP -toimitus" +general.821="Olet jo lunastanut tämän tänään!\nSeuraava toimitus: r(time)" +general.822="Kaksi ilmaista neliboosteria" +general.823="Tykkää meistä Facebookissa ja vastaanota kaksi ILMAISTA kolmen tunnin neliboosteria!\n&eKlikkaa lunastaaksesi!" +general.824="Kaksi ilmaista neliboosteria" +general.825="Olet jo tykännyt meistä Facebookissa ja saanut ilmaiset boosterisi!" +general.826="Verkkosivujen linkki" +general.827="Luo foorumitili ja linkitä se pelitiliisi komennolla /linkaccount ansaitaksesi 15 000 XP" +general.828="Verkkosivujen linkki" +general.829="Olet linkittänyt tilisi foorumeilla" +general.830="Ansaitsit 2000 experienceä!" +general.831="Et ole r(rank)!" +general.832="Sinun tulee odottaa! Seuraava toimitus: r(time)!" +general.833="Saadaksesi lunastuskoodisi vieraile osoitteessa http://hypixel.net/quad ja seuraa ohjeistusta! Käytä sitten pelissä komentoa /redeem (koodi) saamallasi koodilla!" +general.834="Olet suorittanut tämän tehtävän!" +general.835="Vastaanottaaksesi tämän toimituksen käytä komentoa \"/linkaccount\" ja linkitä foorumitilisi pelitiliisi! Jos sinulla ei ole foorumitiliä, luo sellainen ja liity yhteisöön! Tämän jälkeen saat 15,000 XP seuraavalla kerralla kun kirjaudut palvelimelle!" +general.836="Klikkaa nähdäksesi Guildin jäsenet." +general.837="Voit ostaa Network Boosters osoitteessa %%store%%" +general.838="%%player%% säteilee Jalomielisyyttä!" +general.839="%%amount%% Saatavilla" +general.840="Kumoa" +general.841="Kumoa" +general.842="Parkourhaaste" +general.843="Tätä kieltä ei juuri nyt tueta! Yritä myöhemmin uudelleen!" +general.844="TULOSSA PIAN" +general.845="Tarkastele edistymistäsi, kun avaat\nSaavutuksia ja keräät pisteitä." +general.846="Olet jo lunastanut tämän kuukauden palkinnon!" +general.847="Jokin meni vikaan! Yritä uudelleen hetken kuluttua!" +general.848="Boosterisi aktivoitiin. Sinulla on nyt %%b%%x kolikot %%time%%s ajan." +general.849="Avaa" +general.850="Haluaisitko asettaa käyttöösi kielen\n%%language%%?" +general.851="KYLLÄ" +general.852="EI" +general.853="Klikkaa asettaaksesi käyttöösi kielen %%language%%!" +general.854="Klikkaa pitääksesi käytössäsi kielen %%language%%!" +general.855="Hypixel Tutorial" +general.856="tammikuu" +general.857="helmikuu" +general.858="maaliskuu" +general.859="huhtikuu" +general.860="toukokuu" +general.861="kesäkuu" +general.862="heinäkuu" +general.863="elokuu" +general.864="syyskuu" +general.865="lokakuu" +general.866="marraskuu" +general.867="joulukuu" +general.868="Tykkää meistä Facebookissa ja vastaanota kaksi ILMAISTA neliboosteria!\nKlikkaa lunastaaksesi!" +general.869="Klikkaa vaihtaaksesi kielesi!" +general.870="Tällä hetkellä saatavilla:" +general.871="Tulossa pian" +general.872="Auta meitä kääntämään Hypixeliä" +general.873="Klikkaa tätä kuvaketta saadaksesi nettisivujen linkin." +general.874="Klikkaa alla olevaa linkkiä saadaksesi tietoa Hypixelin kääntämisestä:" +general.875="Klikkaa tätä linkkiä auttaaksesi Hypixelin kääntämisessä:" +general.876="Vaihda kielesi." +general.877="Aseta kieleksesi %%language%%." +general.878="Klikkaa poistaaksesi käytöstä!" +general.879="Klikkaa ottaaksesi käyttöön!" +general.880="Lisää kieliä tulossa pian!" +general.881="Hei %%player%%," +general.882="Sinulla on uusi päivittäinen palkinto lunastettavana!" +general.883="Vieraile Lähettimiehen luona tai %%click_here%%" +general.884="klikkaa tästä" +general.885="%%visit_the_delivery_man_or_click_here%% valitaksesi %%exp%%, %%souls%%, %%coins%%, %%dust%% tai muita ILMAISIA palkintoja!" +general.886="Tätä kieltä ei tueta vielä, mutta se on tulossa pian!" +general.887="Voit nopeuttaa tätä auttamalla meitä kääntämään!" +general.888="Huomasimme, ettet ole lunastanut ilmaista päivittäistä palkintoasi vielä!" +general.889="Valitaksesi palkintosi sinun tulee klikata linkkiä vieraillaksesi nettisivuillamme! Muistutuksena tässä on päivän linkkisi:" +general.890="Oikeaklikkaa selataksesi tehtäviä,\ntarkastellaksesi saavutuksia, Network Boostereita ja paljon muuta!" +general.891="Jokin meni vikaan käsitellessä pelaajadataasi!" +general.892="Jokin meni vikaan käsitellessä ostotapahtumaa!" +general.893="Sinulla ei ole tarpeeksi %%color%%mysteeripölyä" +general.894="Päivittäinen palkinto" +general.895="Ilmaiset 2000 Network Experienceä ja 3000 Arcade-kolikkoa!" +general.896="Klikkaa tästä lunastaaksesi!" +general.897="Olet lunastanut tämän palkinnon vasta! Palaa takaisin %%time%% kuluttua!" +general.898="Olet onnistuneesti lunastanut %%exp%% ja %%coins%%!" +general.899="Käsitellään jo tätä ostotapahtumaa!" +general.900="Klikkaa asettaaksesi talot järjestykseen sen mukaan, kuinka monta keksiä omistaja on saanut tällä viikolla!" +general.901="Klikkaat liian nopeasti! Ole hyvä ja hidasta hieman!" +general.902="Muuta" +general.903="Tämä peli on tällä hetkellä suljetussa betassa." +general.904="Klikkaa avataksesi Hypixel-leveling -valikon" +general.905="Klikkaa tästä lunastaaksesi palkintosi!" +general.906="Klikkaa tästä nähdäksesi kaikki Hypixel-leveling -palkinnot!" +general.907="Älä käytä vempaimia!" +general.908="Äänestys: %%poll%%" +general.909="Kysymys: %%question%%" +general.910="Vastaus: %%answer%%" +general.911="Aikaa jäljellä: %%color%%%%time%%" +general.912="Ääniä nyt: %%color%%%%percentage%%!" +general.913="Äänten prosenttiosuudet näytetään oikealla palkissa." +general.914="Klikkaa äänestääksesi vaihtoehtoa %%option%%!" +general.915="Mikä aihe?" +general.916="Joulu" +general.917="Kartta: %%map%%" +general.918="Jonossa: %%players%%/%%max%%" +general.919="Pelimuoto: Faceoff" +general.920="Pelimuoto: Teams (%%maps%%)" +general.921="Pelimuoto: Solo" +general.922="Pelaajia yhteensä: %%players%%" +general.923="%%color%%Sinun tulee olla %%rank%% %%color%%tai\n%%color%%korkeampi käyttääksesi\n%%color%%pikaliittymisominaisuutta!" +general.924="Klikkaa pelataksesi!" +general.925="Pelaa %%game%%" +general.926="Suorittamalla tehtäviä ja haasteita\nansaitset %%coins%%, %%exp%% ja paljon muuta!" +general.927="Aloitit tehtävän %%name%%!" +general.928="www.hypixel.net" +general.929="Loputon" +general.930="Kuoleman enkeli" +general.931="Jonossa! Käytä sänkyä palataksesi lobbyyn!" +general.932="Jonossa! Käytä sänkyä peruaksesi!" +general.933="Ruoka: %%food%%" +general.934="Ilmainen päivittäinen palkinto!" +general.935="tunti" +general.936="Mysteeripöly yhteensä: " +general.937="Klikkaa vaihtaaksesi!" +general.938="päivä" +general.939="Tervetuliaispakkaus" +general.940="Tämä koodi ei kelpaa!" +general.941="Lunasta koodi" +general.942="Klikkaa lunastaaksesi koodin!" +general.943="Olet jo lunastanut tämän!" +general.944="Pelaa niin, että sinulla on 1 minuutti vahvistuksia jäljellä Ender Spleef -pelin lopussa" +general.945="MiniWalls-voittaja" +general.946="Maatilan herruus" +general.947="Tiimityötä" +general.948="Ammattilaispelaaja" +general.949="Lyö viittä pelaajaa \"Teroitetulla miekalla\" yhden kilpailun aikana" +general.950="Voittaja!" +general.951="Tapa vähintään 2 pelaajaa yhdellä Tulipallolla" +general.952="Tapa vampyyri kun sinulla on vain puolikas sydän" +general.953="Voita Feeniksinä peli, jossa sinä ja ainakin neljä henkiin herättämääsi tiimitoveria olette yhä elossa" +general.954="Valmista rautamiekka ja hanki 7 viimeistelytappoa sillä miekalla ilman kuolemia, kun pelaat Hämähäkillä" +general.955="Riko 20 000 puupalaa Golemina" +general.956="Hanki 20 VT tai VA yhdessä pelissä Hämähäkkinä" +general.957="Hanki 10 viimeistelytappoa Mystisellä räjähdyksellä Mystikkona" +general.958="Hanki 20 VT tai VA yhdessä pelissä Merirosvona" +general.959="Hanki 20 VT tai VA yhdessä pelissä Creeperinä" +general.960="Hanki 20 VT tai VA yhdessä pelissä Roihuna" +general.961="Hanki Roihuna 9 viimeistelytappoa tulipalloilla yhdessä pelissä" +general.962="Kerää 2 stackia TNT:tä keräämistaidollasi ennen kuin seinät laskeutuvat" +general.963="Palauta 10000 EP rautamalmin louhimisesta Roihuna" +general.964="Hanki 20 VT tai VA yhdessä pelissä Mystikkona" +general.965="Hanki 20 VT tai VA yhdessä pelissä Herobrinenä" +general.966="Kerää kaivamalla 8 imeytymisen taikajuomaa ja käytä ne kaikki yhdessä pelissä Kalmarina" +general.967="Aktivoi Myrsky 5 kertaa peräkkäin menettämättä Nopeus III -vaikutusta" +general.968="Hanki 20 VT tai VA yhdessä pelissä Myyrämiehenä" +general.969="Luo 5000 sutta Shamaanina" +general.970="Paranna tiimitovereita yhteensä 1500 EP edestä käyttämällä Infernoa Feeniksinä" +general.971="Hanki yhteensä 15 puolustavaa VT ja VA Kalmarina" +general.972="Tee yhteensä 100 000 wither-vahinkoa Pelon herrana" +general.973="Hanki 20 VT tai VA yhdessä pelissä Sikamiehenä" +general.974="Vahingoita viittä eri pelaajaa yhdellä Loiskauksella Kalmarina" +general.975="Työstä 2500 leipää Pelon herrana" +general.976="Kerää 50 paistia yhdessä pelissä tappamalla pelaajia." +general.977="Riko 15 000 palikkaa Räjäytyksellä Creeperinä" +general.978="Hanki yhteensä 5 viimeistelytappoa Minionillasi Creeperinä" +general.979="Hanki yhteensä 200 viimeistelytappoa takaapäin Endermanina" +general.980="Hanki yhteensä 7 lähitaistelu-VT yhdessä pelissä Luurankona" +general.981="Hanki yhteensä 25 VT Papukaijoilla Merirosvona" +general.982="Hanki 20 VT tai VA yhdessä pelissä Pelon herrana" +general.983="Suden isku" +general.984="Hanki 10 viimeistelytappoa epäsuoralla osumalla käyttäen Lykantropiaa." +general.985="Syö 10,000 paistia Ihmissutena" +general.986="Osu vastustajaan kanuunalla yli 50 palikan päästä Merirosvona" +general.987="Hyökkää Endermanina jokaista viholliswitheriä kohtaan kahden minuutin sisällä seinien laskeutumisen jälkeen" +general.988="Anna 10000 rautapanssarin osaa tiimillesi joulukuun aikana" +general.989="Teleporttaa yhteensä 5000 pelaajan luo Endermanina" +general.990="Aseta yhteensä 25 000 palikkaa valmisteluaikana Myyrämiehenä" +general.991="Hanki 20 VT tai VA yhdessä pelissä Endermanina" +general.992="Hanki 20 VT tai VA yhdessä pelissä Kalmarina" +general.993="Hanki 20 VT tai VA yhdessä pelissä Shamaanina" +general.994="Luottamuksen kehä" +general.995="Vahingoita 10 henkilöä yhtä aikaa yhdellä Sikamiehen kuplalla" +general.996="Hanki 20 VT tai VA yhdessä pelissä Ihmissutena" +general.997="Hanki 30 VT susillasi Shamaanina." +general.998="Hanki 20 VT tai VA yhdessä pelissä Luurankona" +general.999="Marttyyrikuolema" +general.1000="Hanki yhteensä 10 VT pesähämähäkeilläsi Hämähäkkinä" +general.1001="Hanki 5 viimeistelytappoa seitsemässä sekunnissa Pelon herrana" +general.1002="Työstä ja aseta sänky 100 pelissä Zombina" +general.1003="Kerää yhteensä 1500 panssarin osaa Pigmanina" +general.1004="Matkusta 100 000 palikkaa Nopeusvaikutuksen alaisena Ihmissutena" +general.1005="Hanki 5 viimeistelytappoa seitsemässä sekunnissa Herobrinenä" +general.1006="Kaiva 100 timanttimalmia Luurankona" +general.1007="Puhalletaan kuplia" +general.1008="Aktivoi 6 Pigmanin kuplaa 25 sekunnin sisällä" +general.1009="Palauta ainakin 240 sydäntä tiimitovereillesi yhdessä pelissä Zombina." +general.1010="Hanki 40 VT yli 50 palikan päästä Luurankona" +general.1011="Aktivoi aarteenetsijäkyky 1000 kertaa Merirosvona" +general.1012="Tuntuu pahalta...?" +general.1013="Hanki viimeistelytappo vihollisesta pudottautumalla tämän päälle ja kuolemalla samalla itse" +general.1014="Palauta yhteensä 25 000 EP Kalmarina" +general.1015="Hanki 20 VT tai VA yhdessä pelissä Zombina" +general.1016="Hanki 10 VT Eläinystävällä Metsästäjänä" +general.1017="Hanki 20 VT tai VA yhdessä pelissä Feeniksinä" +general.1018="Vahingoita kuutta eri pelaajaa yhdellä Iskulla Golemina" +general.1019="Hanki 20 VT tai VA yhdessä pelissä Golemina" +general.1020="Hanki 20 VT tai VA yhdessä pelissä Metsästäjänä" +general.1021="Ei tämä ole SkyWarsia" +general.1022="Tapa 5 pelaajaa kymmenessä sekunnissa" +general.1023="Tapa 10 pelaajaa yhdessä pelissä" +general.1024="Voita peli käyttämällä Gun of Darknessia" +general.1025="Pelaajat, joilla on %%rank%% voivat vaihtaa +-merkkinsä väriä ja avata uusia värejä." +general.1026="Pieni pussi Hypixel-experienceä" +general.1027="Keskikokoinen pussi Hypixel-experienceä" +general.1028="Suuri pussi Hypixel-experienceä" +general.1029="Mysteeripöly" +general.1030="store.hypixel.net" +general.1031="https://store.hypixel.net" +general.1032="Mysteeripöly: %%dust%%" +general.1033="Tehtäviä suoritettu: %%quests%%" +general.1034="Extreme-laatu" +general.1035="Poistaa kaikki partikkelien rajoitukset. Suositellaan vain tehokkaille koneille ja nopeille internet-yhteyksille." +general.1036="Musta savu" +general.1037="Classic" +general.1038="Timantti" +general.1039="Munat" +general.1040="Smaragdi" +general.1041="Lumoaminen" +general.1042="Chunky" +general.1043="Tuli" +general.1044="Sydämet" +general.1045="Nuotit" +general.1046="Ei mitään" +general.1047="Sateenkaari" +general.1048="Punainen pöly" +general.1049="Ruusut" +general.1050="Lima" +general.1051="Lumi" +general.1052="Valkoinen savu" +general.1053="Oikeaklikkaa poistuaksesi lobbyyn!" +general.1054="Valitsee veriefektin %%blood_effect%%, joka näytetään aina veren sijaan." +general.1055="+%%amount%% Maaginen avain" +general.1056="+%%amount%% Maagista avainta" +general.1057="+%%amount%% Sielu" +general.1058="%%amount%% pelin Smash Heroes EXP Booster" +general.1059="%%amount%% pelin Smash Heroes EXP Booster" +general.1060="+%%amount%% Rikkinäinen ase" +general.1061="+%%amount%% Rikkinäistä asetta" +general.1062="+%%amount%% Taikajauhetta" +general.1063="+%%amount%% Tyhjyyssiru" +general.1064="+%%amount%% Tyhjyyssirua" +general.1065="+%%amount%% Hypixel-experienceä" +general.1066="+%%amount%% mysteeripölyä" +general.1067="Voita 2 TNT Wizards -peliä" +general.1068="Voita 15 TNT Wizards -peliä" +general.1069="Tapa yhteensä 50 pelaajaa" +general.1070="Tilastojen katselu" +general.1071="#Unranked" +general.1072="%%name%% Lobby #%%number%% on juuri nyt poissa päältä!" +general.1073="päivä" +general.1074="minuutti" +general.1075="kuukausi" +general.1076="vuosi" +general.1077="noin " +general.1078="noin sekunnin" +general.1079="tunti" +general.1080=" ja " +general.1081=" ja yksi päivä" +general.1082=" ja yksi kuukausi" +general.1083=" ja yksi tunti" +general.1084=" päivää" +general.1085=" tuntia" +general.1086=" minuuttia" +general.1087=" kuukautta" +general.1088=" sekuntia" +general.1089=" vuotta" +general.1090="Komento epäonnistui: Komentoa ei voi käyttää vielä! Yritä uudelleen %%time%% kuluttua!" +general.1091="Luuranko" +general.1092="Zombi" +general.1093="Creeper" +general.1094="Enderman" +general.1095="Hämähäkki" +general.1096="Kalmari" +general.1097="Roihu" +general.1098="1v1-tapot" +general.1099="1v1-voitot" +general.1100="2v2-tapot" +general.1101="2v2-voitot" +general.1102="4v4-tapot" +general.1103="4v4-voitot" +general.1104="Blocking Dead: Tapot" +general.1105="Blocking Dead: Voitot" +general.1106="Pommeja purettu" +general.1107="Pommeja viritetty" +general.1108="Bounty Hunters: Voitot" +general.1109="Bow Spleef -laukaukset" +general.1110="Bow Spleef -voitot" +general.1111="Laatikoita kerätty" +general.1112="Pronssipalkinnot" +general.1113="Build Battle: Solo-voitot" +general.1114="Build Battle: Teams-voitot" +general.1115="Luokka" +general.1116="Creeper Attack: Paras aalto" +general.1117="CTF-voitot" +general.1118="Defusal-tapot" +general.1119="Defusal-voitot" +general.1120="Domination-voitot" +general.1121="Doubles-tapot" +general.1122="Doubles-voitot" +general.1123="Dragon Wars: Voitot" +general.1124="Ender Spleef: Voitot" +general.1125="Farm Hunt: Voitot eläimenä" +general.1126="Farm Hunt: Ulostetta kerätty" +general.1127="Football: Voitot" +general.1128="Galaxy Wars: Voitot" +general.1129="Kultapalkinnot" +general.1130="Päitä syöty" +general.1131="Pääosumat" +general.1132="Hole in the Wall: Voitot" +general.1133="Tapot ihmisistä" +general.1134="Voitot ihmisenä" +general.1135="Hypixel Says: Voitot" +general.1136="Solo-tapot" +general.1137="Teams-tapot" +general.1138="Kierroksia suoritettu" +general.1139="Mega-tapot" +general.1140="Mega-voitot" +general.1141="Mini Walls: Voitot" +general.1142="Party Games: Voitot" +general.1143="Pixel Painters: Voitot" +general.1144="PVP Run -tapot" +general.1145="PVP Run -voitot" +general.1146="Ranked-tapot" +general.1147="Ranked-sijoitus" +general.1148="Ranked-pisteet" +general.1149="Ranked-voitot" +general.1150="Erävoittoja" +general.1151="Laukauksia ammuttu" +general.1152="Hopeapalkinnot" +general.1153="Smash Level" +general.1154="Solo-tapot" +general.1155="Solo-voitot" +general.1156="TDM-tapot" +general.1157="TDM-voitot" +general.1158="Teams-tapot" +general.1159="Team War -tapot" +general.1160="Team War -voitot" +general.1161="Teams-voitot" +general.1162="Throw Out: Voitot" +general.1163="TNT Run -voitot" +general.1164="TNT Tag -voitot" +general.1165="Tapot vampyyreista" +general.1166="Voitot" +general.1167="Solo-voitot" +general.1168="Teams-voitot" +general.1169="Wizard-tapot" +general.1170="Wizard-voitot" +general.1171="Yhteistilastot" +general.1172="%%game%% Tilastot" +general.1173="Parkourhaaste" +general.1174="Oletus" +general.1175="ADMIN" +general.1176="MODERAATTORI" +general.1177="%%playerCount%% pelaajaa!" +general.1178="http://store.hypixel.net" +general.1179="Bed Wars -experience" +general.1180="[KATSOJA]" +general.1181="[TIIMI]" +general.1182="%%playerCount%% pelaajaa!" +general.1183="%%prefix%%%%amount%% kolikkoa!%%builder%%%%reason%%" +general.1184="Tätä henkilöä on lyöty liian monta kertaa viimeisten 30 sekunnin aikana!" +general.1185="Rating" +general.1186="Avaimet" +general.1187="Tappoputket" +general.1188="Olet tällä hetkellä %%states%%" +general.1189="NÄKYMÄTÖN" +general.1190="NAAMIOITUNUT" +general.1191="Valitettavasti sinulla ei ole oikeuksia suorittaa tätä komentoa. Otathan yhteyttä ylläpitoon, mikäli uskot tämän olevan virhe." +general.1192="%%prefix%%%%amount%% kolikko!%%builder%%%%reason%%" +general.1193="+%%amount%% kolikko" +general.1194="Et saanut palkintoja riippuvuuden ehkäisemiseksi." +general.1195="Palkintosi puolitettiin riippuvuuden ehkäisemiseksi." +general.1196="Kertoimesi on tällä hetkellä %%multiplier%% riippuvuuden ehkäisemiseksi." +general.1197="[emoten nimi]" +general.1198="[eleen nimi]" +general.1199="[lobbyn numero]" +general.1200="[nimi]" +general.1201="[sana]" +general.1202="Voit käyttää chattia vain 3 sekunnin välein! Osta VIP ohittaaksesi tämän rajoituksen!" +general.1203="Kunnioita muita pelaajia" +general.1204="Et voi sanoa samaa viestiä kahdesti!" +general.1205="Kiroileminen ja suodattimen ohittaminen on sääntöjen vastaista." +general.1206="Mainostaminen on sääntöjen vastaista. Sinulle annetaan pysyvä porttikielto palvelimelle, mikäli yrität mainostaa." +general.1207="Liiallinen capsin käyttö on sääntöjen vastaista." +general.1208="Ethän spämmää chattiin turhia merkkejä." +general.1209="HypixelCapes on huijausyritys." +general.1210="Estettiin lähettämäsi automaattinen viesti, jossa luki 'minechat' tai 'mimecraft connect'" +general.1211="Estettiin automaattiset päivitysviestit käyttäjältäsi." +general.1212="Vältäthän pelaajien tarpeetonta syyttelemistä. Mikäli näet jonkun rikkovan sääntöjä, ilmoitathan heistä foorumeilla tai komennolla /watchdogreport !" +general.1213="Ladataan..." +general.1214="Voit käyttää tätä komentoa vain pelissä!" +general.1215="Annoit itsellesi ukkoskepin! Bzzzzz!" +general.1216="%%giver%% antoi kaikille Ukkoskepin!" +general.1217="%%giver%% antoi sinulle Ukkoskepin!" +general.1218="Annoit pelaajalle %%target%% Ukkoskepin!" +general.1219="Ukkoskeppi" +general.1220="Tesla olisi onnellinen!" +general.1221="Kohdepelaajaa ei löytynyt!" +general.1222="Sinun tulee olla vähintään %%rank%% käyttääksesi tätä komentoa!" +general.1223="%%underline%%Klikkaa vaihtaaksesi!" +general.1224="Elinvoima: %%health%%" +general.1225="Pelissä %%game%% palvelimella %%color%%MC.HYPIXEL.NET" +general.1226="Virheelliset argumentit, yritä: %%usage%%" +general.1227="/nick check salanimi" +general.1228="Tämä komento on väliaikaisesti poissa käytöstä. Yritä myöhemmin uudelleen." +general.1229="Et voi käyttää tätä komentoa ollessasi mukana pelissä!" +general.1230="Voit käyttää tätä komentoa vain lobbyissa!" +general.1231="Syötä haluamasi\nnimi tähän" +general.1232="Olet viimeistellyt salanimesi asettamisen!" +general.1233=" %%underline%%YRITÄ UUDELLEEN" +general.1234="Klikkaa tästä syöttääksesi eri nimen." +general.1235="Olemme luoneet sinulle satunnaisen käyttäjänimen:" +general.1236=" %%underline%%KÄYTÄ NIMEÄ" +general.1237="Klikkaa tästä käyttääksesi tätä nimeä." +general.1238="Klikkaa tästä luodaksesi uuden nimen." +general.1239="Tai syötä käytettävä nimi." +general.1240="Klikkaa tästä syöttääksesi käytettävän nimen." +general.1241="Oho! Tapahtui virhe yrittäessä luoda sinulle nimeä." +general.1242="➤ Yritä uudelleen" +general.1243="Klikkaa tästä yrittääksesi uudelleen." +general.1244="➤ Syötä nimi" +general.1245="Klikkaa tästä jos haluaisit syöttää käytettävän nimen." +general.1246="Asetetaanpa sinulle salanimi!" +general.1247="Ensiksi sinun tulee valita RANK, jona haluat esiintyä naamioituneena." +general.1248="Mahtavaa! Nyt, mitä SKINIÄ haluaisit käyttää naamioituneena?" +general.1249="➤ Tavallinen skinini" +general.1250="Klikkaa tästä käyttääksesi tavallista skiniäsi" +general.1251="➤ Steve/Alex skin" +general.1252="Klikkaa tästä käyttääksesi Steven/Alexin skiniä" +general.1253="➤ Satunnainen skin" +general.1254="Klikkaa tästä käyttääksesi satunnaista skiniä" +general.1255="Okei, nyt sinun täytyy valita käytettävä NIMI!" +general.1256="Klikkaa tästä syöttääksesi käytettävän nimen" +general.1257="➤ Käytä satunnaista nimeä" +general.1258="Klikkaa tästä käyttääksesi satunnaisesti luotua nimeä" +general.1259="➤ Käytä nimeä '%%name%%'" +general.1260="Klikkaa tästä käyttääksesi nimeä '%%name%%'" +general.1261="Palataksesi takaisin omaksi itseksesi kirjoita:" +general.1262="Klikkaa tästä näyttääksesi itselläsi rankin %%rank%%" +general.1263="Asetettiin salarankiksesi %%rank%%!" +general.1264="Tuntematon rank!" +general.1265="Tämä on jo salanimesi!" +general.1266="Tämä nimi on liian pitkä tai lyhyt käytettäväksi salanimenä!" +general.1267="Toinen pelaaja käyttää tätä salanimenään!" +general.1268="Salanimesi on nyt %%name%%!" +general.1269="Salanimen tulee olla 4-16 merkkiä pitkä!" +general.1270="Salanimet voivat sisältää vain kirjaimia, numeroita ja alaviivoja!" +general.1271="Tämä nimi kuuluu NPC-hahmolle!" +general.1272="Tämä nimi kuuluu Hypixelin pelaajalle!" +general.1273="Joku toinen käyttää tätä juuri nyt salanimenään!" +general.1274="/nick skin random, /nick skin real tai /nick skin reset" +general.1275="Tuntematon skin, kokeile komentoa /nick skin random saadaksesi satunnaisen hahmon." +general.1276="Näyt nyt muille pelaajille Stevenä/Alexina." +general.1277="Käytössäsi on nyt oman Minecraft-hahmosi skin myös naamioituneena!" +general.1278="Hahmosi ulkonäöksi asetettiin %%skin%%." +general.1279="Ostit esineen %%item%%!" +general.1280="Kivi" +general.1281="Graniitti" +general.1282="Kiillotettu graniitti" +general.1283="Dioriitti" +general.1284="Kiillotettu dioriitti" +general.1285="Andesiitti" +general.1286="Kiillotettu andesiitti" +general.1287="Ruohokuutio" +general.1288="Multa" +general.1289="Karkea multa" +general.1290="Podsoli" +general.1291="Mukulakivi" +general.1292="Tammilankut" +general.1293="Kuusilankut" +general.1294="Koivulankut" +general.1295="Viidakkopuulankut" +general.1296="Akaasialankut" +general.1297="Tummat tammilankut" +general.1298="Tammen taimi" +general.1299="Kuusen taimi" +general.1300="Koivun taimi" +general.1301="Viidakkopuun taimi" +general.1302="Akaasian taimi" +general.1303="Tumman tammen taimi" +general.1304="Peruskallio" +general.1305="Vesi (leviämätön)" +general.1306="Vesi" +general.1307="Laava (leviämätön)" +general.1308="Laava" +general.1309="Hiekka" +general.1310="Pumainen hiekka" +general.1311="Sora" +general.1312="Kultamalmi" +general.1313="Rautamalmi" +general.1314="Hiilimalmi" +general.1315="Tammipuu" +general.1316="Kuusipuu" +general.1317="Koivupuu" +general.1318="Viidakkopuu" +general.1319="Tammenlehdet" +general.1320="Kuusenlehdet" +general.1321="Koivunlehdet" +general.1322="Viidakkopuunlehdet" +general.1323="Pesusieni" +general.1324="Märkä pesusieni" +general.1325="Lasi" +general.1326="Lasuriittimalmi" +general.1327="Lasuriittikuutio" +general.1328="Jakelulaite" +general.1329="Hiekkakivi" +general.1330="Kaiverrettu hiekkakivi" +general.1331="Sileä hiekkakivi" +general.1332="Sointukuutio" +general.1333="Sänky" +general.1334="Kiihdytinraide" +general.1335="Tunnistinraide" +general.1336="Tarttumamäntä" +general.1337="Verkko" +general.1338="Puska" +general.1339="Ruoho" +general.1340="Saniainen" +general.1341="Kuollut pensas" +general.1342="Mäntä" +general.1343="Mäntä (pää)" +general.1344="Villa" +general.1345="Oranssi villa" +general.1346="Purppura villa" +general.1347="Vaaleansininen villa" +general.1348="Keltainen villa" +general.1349="Limetinvihreä villa" +general.1350="Vaaleanpunainen villa" +general.1351="Harmaa villa" +general.1352="Vaaleanharmaa villa" +general.1353="Syaani villa" +general.1354="Violetti villa" +general.1355="Sininen villa" +general.1356="Ruskea villa" +general.1357="Vihreä villa" +general.1358="Punainen villa" +general.1359="Musta villa" +general.1360="Voikukka" +general.1361="Ruusu" +general.1362="Sininen orkidea" +general.1363="Laukka" +general.1364="Keijunsilmä" +general.1365="Punainen tulppaani" +general.1366="Oranssi tulppaani" +general.1367="Valkoinen tulppaani" +general.1368="Vaaleanpunainen tulppaani" +general.1369="Päivänkakkara" +general.1370="Ruskea sieni" +general.1371="Punainen sieni" +general.1372="Kultakuutio" +general.1373="Rautakuutio" +general.1374="Kivilaatta (Tupla)" +general.1375="Hiekkakivilaatta (Tupla)" +general.1376="Puulaatta (Tupla)" +general.1377="Mukulakivilaatta (Tupla)" +general.1378="Tiililaatta (Tupla)" +general.1379="Kivitiililaatta (Tupla)" +general.1380="Nether-tiililaatta (Tupla)" +general.1381="Kvartsilaatta (Tupla)" +general.1382="Sileä kivilaatta (Tupla)" +general.1383="Sileä hiekkakivilaatta (Tupla)" +general.1384="Kivilaatta" +general.1385="Hiekkakivilaatta" +general.1386="Puulaatta" +general.1387="Mukulakivilaatta" +general.1388="Tiililaatta" +general.1389="Kivitiililaatta" +general.1390="Nether-tiililaatta" +general.1391="Kvartsilaatta" +general.1392="Tiili" +general.1393="TNT" +general.1394="Kirjahylly" +general.1395="Sammalkivi" +general.1396="Obsidiaani" +general.1397="Soihtu" +general.1398="Tammiportaat" +general.1399="Arkku" +general.1400="Redstone-johto" +general.1401="Timanttimalmi" +general.1402="Timanttikuutio" +general.1403="Työpöytä" +general.1404="Venhä (Kasvi)" +general.1405="Viljelysmaa" +general.1406="Uuni" +general.1407="Uuni (sulattaa)" +general.1408="Kyltti (kuutio)" +general.1409="Puuovi (kuutio)" +general.1410="Tikkaat" +general.1411="Raiteet" +general.1412="Kiviportaat" +general.1413="Kyltti (seinällä)" +general.1414="Vipu" +general.1415="Painelaatta" +general.1416="Rautaovi (kuutio)" +general.1417="Redstone-malmi" +general.1418="Redstone-malmi (hehkuva)" +general.1419="Redstone-soihtu" +general.1420="Redstone-soihtu (päällä)" +general.1421="Nappi" +general.1422="Jää" +general.1423="Lumikuutio" +general.1424="Kaktus" +general.1425="Savikuutio" +general.1426="Sokeriruoko (kuutio)" +general.1427="Levysoitin" +general.1428="Aita" +general.1429="Kurpitsa" +general.1430="Netherrack" +general.1431="Sieluhiekka" +general.1432="Hehkukivi" +general.1433="Portaali" +general.1434="Kurpitsalyhty" +general.1435="Kakku (kuutio)" +general.1436="Redstone-toistin (poissa päältä)" +general.1437="Redstone-toistin (päällä)" +general.1438="Värjätty lasi" +general.1439="Puuluukku" +general.1440="Hirviönmunakivi" +general.1441="Hirviömunamukulakivi" +general.1442="Hirviömunakivitiili" +general.1443="Sammaleinen hirviömunakivitiili" +general.1444="Murtunut hirviömunakivitiili" +general.1445="Veistetty hirviömunakivitiili" +general.1446="Kivitiili" +general.1447="Sammaleinen kivitiili" +general.1448="Murtunut kivitiili" +general.1449="Veistetty kivitiili" +general.1450="Ruskea sieni (kuutio)" +general.1451="Punainen sieni (kuutio)" +general.1452="Kalterit" +general.1453="Lasipaneeli" +general.1454="Meloni (kuutio)" +general.1455="Kurpitsan varsi" +general.1456="Melonin varsi" +general.1457="Köynnös" +general.1458="Portti" +general.1459="Tiiliportaat" +general.1460="Kivitiiliportaat" +general.1461="Sienirihmasto" +general.1462="Lumpeenlehti" +general.1463="Nether-tiili" +general.1464="Nether-tiiliaita" +general.1465="Nether-tiiliportaat" +general.1466="Nether-pahka" +general.1467="Lumouspöytä" +general.1468="Hautumateline (kuutio)" +general.1469="Pata (kuutio)" +general.1470="End-portaali" +general.1471="End-portaalin kehys" +general.1472="End-kivi" +general.1473="Lohikäärmeen muna" +general.1474="Redstone-lamppu (poissa päältä)" +general.1475="Redstone-lamppu (päällä)" +general.1476="Kaksoispuulaatta" +general.1477="Tammilaatta" +general.1478="Kuusilaatta" +general.1479="Koivulaatta" +general.1480="Viidakkopuulaatta" +general.1481="Akaasialaatta" +general.1482="Tumma tammilaatta" +general.1483="Kaakaokasvi" +general.1484="Hiekkakiviportaat" +general.1485="Smaragdimalmi" +general.1486="Ender-arkku" +general.1487="Ansalankakoukku" +general.1488="Ansalanka" +general.1489="Smaragdikuutio" +general.1490="Kuusiportaat" +general.1491="Koivuportaat" +general.1492="Viidakkopuuportaat" +general.1493="Komentokuutio" +general.1494="Merkkivalo" +general.1495="Mukulakivimuuri" +general.1496="Sammaleinen mukulakivimuuri" +general.1497="Kukkaruukku" +general.1498="Porkkanat" +general.1499="Perunat" +general.1500="Pää" +general.1501="Alasin" +general.1502="Hieman vaurioitunut alasin" +general.1503="Pahasti vaurioitunut alasin" +general.1504="Ansoitettu arkku" +general.1505="Painotettu painolaatta (kevyt)" +general.1506="Painotettu painelaatta (painava)" +general.1507="Redstone-komparaattori (poissa päältä)" +general.1508="Redstone-komparaattori (päällä)" +general.1509="Päivänvalotunnistin" +general.1510="Redstone-kuutio" +general.1511="Nether-kvartsimalmi" +general.1512="Suppilo" +general.1513="Kvartsikuutio" +general.1514="Kaiverrettu kvartsikuutio" +general.1515="Kvartsipilarikuutio" +general.1516="Kvartsiportaat" +general.1517="Aktivointiraide" +general.1518="Pudottaja" +general.1519="Värjätty savi" +general.1520="Värjätty lasipaneeli" +general.1521="Akaasianlehdet" +general.1522="Tumman tammenlehdet" +general.1523="Akaasiapuu" +general.1524="Tumma tammipuu" +general.1525="Akaasiaportaat" +general.1526="Tummat tammiportaat" +general.1527="Limakuutio" +general.1528="Este" +general.1529="Rautaluukku" +general.1530="Prismariini" +general.1531="Prismariinitiili" +general.1532="Tumma prismariini" +general.1533="Merilyhty" +general.1534="Heinäpaali" +general.1535="Matto" +general.1536="Kovetettu savikuutio" +general.1537="Hiilikuutio" +general.1538="Pakkautunut jää" +general.1539="Auringonkukka" +general.1540="Syreeni" +general.1541="Pitkä ruoho" +general.1542="Suuri saniainen" +general.1543="Ruusupensas" +general.1544="Pioni" +general.1545="Punahiekkakivi" +general.1546="Kaiverrettu punahiekkakivi" +general.1547="Sileä punahiekkakivi" +general.1548="Punahiekkakiviportaat" +general.1549="Punahiekkakivilaatta" +general.1550="Kuusiportti" +general.1551="Koivuportti" +general.1552="Viidakkopuuportti" +general.1553="Tumma tammiportti" +general.1554="Akaasiaportti" +general.1555="Kuusiaita" +general.1556="Koivuaita" +general.1557="Viidakkopuuaita" +general.1558="Tumma tammiaita" +general.1559="Akaasia-aita" +general.1560="Rautalapio" +general.1561="Rautahakku" +general.1562="Rautakirves" +general.1563="Tulukset" +general.1564="Omena" +general.1565="Jousi" +general.1566="Nuoli" +general.1567="Hiili" +general.1568="Puuhiili" +general.1569="Rautaharkko" +general.1570="Kultaharkko" +general.1571="Rautamiekka" +general.1572="Puumiekka" +general.1573="Puulapio" +general.1574="Puuhakku" +general.1575="Puukirves" +general.1576="Kivimiekka" +general.1577="Kivilapio" +general.1578="Kivihakku" +general.1579="Kivikirves" +general.1580="Timanttimiekka" +general.1581="Timanttilapio" +general.1582="Timanttihakku" +general.1583="Timanttikirves" +general.1584="Keppi" +general.1585="Kulho" +general.1586="Sienimuhennos" +general.1587="Kultamiekka" +general.1588="Kultalapio" +general.1589="Kultahakku" +general.1590="Kultakirves" +general.1591="Lanka" +general.1592="Höyhen" +general.1593="Ruuti" +general.1594="Puukuokka" +general.1595="Kivikuokka" +general.1596="Rautakuokka" +general.1597="Timanttikuokka" +general.1598="Kultakuokka" +general.1599="Siemenet" +general.1600="Vehnä" +general.1601="Leipä" +general.1602="Nahkakypärä" +general.1603="Nahkarintapanssari" +general.1604="Nahkahousut" +general.1605="Nahkasaappaat" +general.1606="Rengashaarniskan kypärä" +general.1607="Rengashaarniskan rintapanssari" +general.1608="Rengaspanssarin housut" +general.1609="Rengaspanssarin saappaat" +general.1610="Rautakypärä" +general.1611="Rautarintapanssari" +general.1612="Rautahousut" +general.1613="Rautakengät" +general.1614="Timanttikypärä" +general.1615="Timanttirintapanssari" +general.1616="Timanttihousut" +general.1617="Timanttisaappaat" +general.1618="Kultakypärä" +general.1619="Kultarintapanssari" +general.1620="Kultahousut" +general.1621="Kultasaappaat" +general.1622="Piikivi" +general.1623="Raaka porsaankyljys" +general.1624="Paistettu porsaankyljys" +general.1625="Maalaus" +general.1626="Kultainen omena" +general.1627="Kultaomena (lumottu)" +general.1628="Kyltti" +general.1629="Puuovi" +general.1630="Ämpäri" +general.1631="Vesiämpäri" +general.1632="Laavaämpäri" +general.1633="Kaivosvaunu" +general.1634="Satula" +general.1635="Rautaovi" +general.1636="Redstone" +general.1637="Lumipallo" +general.1638="Vene" +general.1639="Nahka" +general.1640="Maitoämpäri" +general.1641="Savi" +general.1642="Sokeriruoko" +general.1643="Paperi" +general.1644="Kirja" +general.1645="Limapallo" +general.1646="Varastokaivosvaunu" +general.1647="Moottoroitu kaivosvaunu" +general.1648="Muna" +general.1649="Kompassi" +general.1650="Onkivapa" +general.1651="Rannekello" +general.1652="Hehkukivijauhe" +general.1653="Raaka kala" +general.1654="Raaka lohi" +general.1655="Vuokkokala" +general.1656="Pallokala" +general.1657="Paistettu kala" +general.1658="Paistettu lohi" +general.1659="Mustepussi" +general.1660="Ruusunpunainen" +general.1661="Kaktuksenvihreä" +general.1662="Kaakaopapu" +general.1663="Lasuriitti" +general.1664="Violetti väriaine" +general.1665="Syaani väriaine" +general.1666="Vaaleanharmaa väriaine" +general.1667="Harmaa väriaine" +general.1668="Vaaleanpunainen väriaine" +general.1669="Limetinvihreä väriaine" +general.1670="Narsissinkeltainen" +general.1671="Vaaleansininen väriaine" +general.1672="Purppura väriaine" +general.1673="Oranssi väriaine" +general.1674="Luujauhe" +general.1675="Luu" +general.1676="Sokeri" +general.1677="Kakku" +general.1678="Redstone-toistin" +general.1679="Keksi" +general.1680="Kartta" +general.1681="Keritsimet" +general.1682="Meloni" +general.1683="Kurpitsansiemenet" +general.1684="Meloninsiemenet" +general.1685="Raaka pihvi" +general.1686="Paisti" +general.1687="Raaka kana" +general.1688="Paistettu kana" +general.1689="Mädäntynyt liha" +general.1690="Ender-helmi" +general.1691="Roihusauva" +general.1692="Ghastin kyynel" +general.1693="Kultahippu" +general.1694="Vesipullo" +general.1695="Kiusallinen taikajuoma" +general.1696="Sakea taikajuoma" +general.1697="Tavanomainen taikajuoma" +general.1698="Elpymisen taikajuoma (0:45)" +general.1699="Nopeuden taikajuoma (3:00)" +general.1700="Tulenkestävyyden taikajuoma (3:00)" +general.1701="Myrkyllinen taikajuoma (0:45)" +general.1702="Parantava taikajuoma" +general.1703="Heikkouden taikajuoma (1:30)" +general.1704="Vahvuuden taikajuoma (3:00)" +general.1705="Hitauden taikajuoma (1:30)" +general.1706="Loikkaamisen taikajuoma (3:00)" +general.1707="Vahingoittava taikajuoma" +general.1708="Elpymisen taikajuoma II (0:22)" +general.1709="Nopeuden taikajuoma II (1:30)" +general.1710="Myrkyllinen taikajuoma II (0:22)" +general.1711="Parantava taikajuoma II" +general.1712="Pimeänäön taikajuoma (3:00)" +general.1713="Vahvuuden taikajuoma II (1:30)" +general.1714="Loikkaamisen taikajuoma (1:30)" +general.1715="Vahingoittava taikajuoma II" +general.1716="Vedenhengityksen taikajuoma (3:00)" +general.1717="Näkymättömyyden taikajuoma (3:00)" +general.1718="Elpymisen taikajuoma (2:00)" +general.1719="Nopeuden taikajuoma (8:00)" +general.1720="Tulenkestävyyden taikajuoma (8:00)" +general.1721="Myrkyllinen taikajuoma (2:00)" +general.1722="Pimeänäön taikajuoma (8:00)" +general.1723="Heikkouden taikajuoma (4:00)" +general.1724="Vahvuuden taikajuoma (8:00)" +general.1725="Hitauden taikajuoma (4:00)" +general.1726="Vedenhengityksen taikajuoma (8:00)" +general.1727="Näkymättömyyden taikajuoma (8:00)" +general.1728="Roiskahtava tulenkestävyyden taikajuoma (2:15)" +general.1729="Roiskahtava elpymisen taikajuoma (0:33)" +general.1730="Roiskahtava nopeuden taikajuoma (2:15)" +general.1731="Roiskahtava myrkyllinen taikajuoma (0:33)" +general.1732="Roiskahtava parantava taikajuoma" +general.1733="Roiskahtava heikkouden taikajuoma (1:07)" +general.1734="Roiskahtava vahvuuden taikajuoma (2:15)" +general.1735="Roiskahtava hitauden taikajuoma (1:07)" +general.1736="Roiskahtava vahingoittava taikajuoma" +general.1737="Roiskahtava nopeuden taikajuoma II (1:07)" +general.1738="Roiskahtava myrkyllinen taikajuoma II (0:16)" +general.1739="Roiskahtava parantava taikajuoma II" +general.1740="Roiskahtava pimeänäön taikajuoma (2:15)" +general.1741="Roiskahtava vahvuuden taikajuoma II (1:07)" +general.1742="Roiskahtava vahingoittava taikajuoma II" +general.1743="Vedenhengityksen roiskahtava taikajuoma (2:15)" +general.1744="Roiskahtava näkymättömyyden taikajuoma (2:15)" +general.1745="Roiskahtava elpymisen taikajuoma (1:30)" +general.1746="Roiskahtava nopeuden taikajuoma (6:00)" +general.1747="Roiskahtava tulenkestävyyden taikajuoma (6:00)" +general.1748="Roiskahtava myrkyllinen taikajuoma (1:30)" +general.1749="Roiskahtava pimeänäön taikajuoma (6:00)" +general.1750="Roiskahtava heikkouden taikajuoma (3:00)" +general.1751="Roiskahtava vahvuuden taikajuoma (6:00)" +general.1752="Roiskahtava hitauden taikajuoma (3:00)" +general.1753="Roiskahtava vedenhengityksen taikajuoma (6:00)" +general.1754="Roiskahtava näkymättömyyden taikajuoma (6:00)" +general.1755="Roiskahtava elpymisen taikajuoma II (0:16)" +general.1756="Lasipullo" +general.1757="Hämähäkinsilmä" +general.1758="Käynyt hämähäkinsilmä" +general.1759="Roihujauhe" +general.1760="Magmavoide" +general.1761="Hautumateline" +general.1762="Pata" +general.1763="Ender-silmä" +general.1764="Kimalteleva meloninsiivu" +general.1765="Luontimuna" +general.1766="Luo creeper" +general.1767="Luo luuranko" +general.1768="Luo hämähäkki" +general.1769="Luo zombi" +general.1770="Luo lima" +general.1771="Luo ghast" +general.1772="Luo sikamies" +general.1773="Luo enderman" +general.1774="Luo luolahämähäkki" +general.1775="Luo sokeritoukka" +general.1776="Luo roihu" +general.1777="Luo magmakuutio" +general.1778="Luo lepakko" +general.1779="Luo noita" +general.1780="Luo endermite" +general.1781="Luo vartija" +general.1782="Luo sika" +general.1783="Luo lammas" +general.1784="Luo lehmä" +general.1785="Luo kana" +general.1786="Luo kalmari" +general.1787="Luo susi" +general.1788="Luo mooshroom" +general.1789="Luo oselotti" +general.1790="Luo hevonen" +general.1791="Luo jänis" +general.1792="Luo kyläläinen" +general.1793="Lumouspullo" +general.1794="Tulipallo" +general.1795="Kirja ja sulkakynä" +general.1796="Kirjoitettu kirja" +general.1797="Smaragdi" +general.1798="Kehys" +general.1799="Porkkana" +general.1800="Peruna" +general.1801="Paistettu peruna" +general.1802="Myrkyllinen peruna" +general.1803="Tyhjä kartta" +general.1804="Kultaporkkana" +general.1805="Kalloesine" +general.1806="Luurangon pääkallo" +general.1807="Wither-luurangon pääkallo" +general.1808="Zombin pää" +general.1809="Creeperin pää" +general.1810="Porkkana kepin päässä" +general.1811="Nether-tähti" +general.1812="Kurpitsapiirakka" +general.1813="Ilotulitusraketti" +general.1814="Ilotulituspanos" +general.1815="Lumottu kirja" +general.1816="Redstone-komparaattori" +general.1817="Nether-kvartsi" +general.1818="TNT-kaivosvaunu" +general.1819="Suppilokaivosvaunu" +general.1820="Prismariinisirpale" +general.1821="Prismariinikristallit" +general.1822="Raaka jäniksenliha" +general.1823="Paistettu jäniksenliha" +general.1824="Jänismuhennos" +general.1825="Jäniksenkäpälä" +general.1826="Jäniksen nahka" +general.1827="Rautainen hevosen panssari" +general.1828="Kultainen hevosen panssari" +general.1829="Timanttinen hevosen panssari" +general.1830="Talutushihna" +general.1831="Nimilappu" +general.1832="Komentokuutiokaivosvaunu" +general.1833="Raaka lampaanliha" +general.1834="Paistettu lampaanliha" +general.1835="Kuusiovi" +general.1836="Koivuovi" +general.1837="Viidakkopuuovi" +general.1838="Akaasiaovi" +general.1839="Tumma tammiovi" +general.1840="Musiikkilevy (13)" +general.1841="Musiikkilevy (Cat)" +general.1842="Musiikkilevy (Blocks)" +general.1843="Musiikkilevy (Chirp)" +general.1844="Musiikkilevy (Far)" +general.1845="Musiikkilevy (Mall)" +general.1846="Musiikkilevy (Mellohi)" +general.1847="Musiikkilevy (Stal)" +general.1848="Musiikkilevy (Strad)" +general.1849="Musiikkilevy (Ward)" +general.1850="Musiikkilevy (11)" +general.1851="Musiikkilevy (wait)" +general.1852="MOD" +general.1853="HELPER" +general.1854="MVP+" +general.1855="MVP" +general.1856="VIP+" +general.1857="VIP" +general.1858="%%playerCount%% pelaajaa" +general.1859="Valitse kenelle tämä bundle lähetetään!" +general.1860="Oranssi" +general.1861="Purppura" +general.1862="Vaaleansininen" +general.1863="Limetinvihreä" +general.1864="Vaaleanpunainen" +general.1865="Harmaa" +general.1866="Hopea" +general.1867="Syaani" +general.1868="Violetti" +general.1869="Ruskea" +general.1870="Pelaajan asetukset: %%player%%" +general.1871="Klikkaa tästä kopioidaksesi nimen!" +general.1872="Klikkaa tästä avataksesi yhteisövalikon!" +general.1873="Klikkaa tästä avataksesi käyttäjän tiedot!" +general.1874="Nimen kopiointi" +general.1875="Yhteisövalikko" +general.1876="Käyttäjän tiedot" +general.1877="Valmis?" +general.1878="MENE!" +general.1879="Odotetaan lisää pelaajia..." +general.1880="Pelissä %%game%% palvelimella %%color%%MC.HYPIXEL.NET" +general.1881="Tämän ominaisuuden avulla voit luoda julkisen partyn, johon kuka tahansa voi liittyä. Voit siis antaa katsojiesi pelata helposti pelejä kanssasi!" +general.1882="Julkiset partyt ovat juuri nyt BETASSA" +general.1883="Sinun tulee syöttää numero väliltä 2-100!" +general.1884="Valitse partysi pelaajien enimmäismäärä:" +general.1885="Klikkaa asettaaksesi pelaajien enimmäismääräksi %%count%%" +general.1886="Mukautettu" +general.1887="Klikkaa syöttääksesi mukautetun pelaajien enimmäismäärän" +general.1888="Katsojasi voivat liittyä partyyn komennolla %%command%%" +general.1889="/party join %%player%%" +general.1890="Aseta chat PÄÄLLE" +general.1891="Aseta chat POIS PÄÄLTÄ" +general.1892="Muuta pelaajien enimmäismäärää" +general.1893="Sulje party" +general.1894="Tyhjennä party" +general.1895="Hajota party" +general.1896="Voit myös käyttää kaikki partyn komentoja - katso /party help" +general.1897="Puumiekka" +general.1898="Heikkous" +general.1899="Näkymättömyys" +general.1900="Hämmennys\n" +general.1901="Sokeus" +general.1902="Tulenkestävyys" +general.1903="Myrkky" +general.1904="Imeytyminen" +general.1905="Kylläisyys" +general.1906="Nälkä" +general.1907="KLIKKAA PELATAKSESI" +general.1908="Klikkaa saadaksesi linkin!" +general.1909="Vikailmoitukset on hidastettu! Voit lähettää uuden tälle palvelimelle %%seconds%% sekunnin kuluttua." +general.1910="Luodaan virheilmoitusta..." +general.1911="Hups! Jokin meni vikaan luodessa vikailmoitustasi! Ole hyvä ja yritä myöhemmin uudelleen." +general.1912="Vikailmoitukslomakkeesi on luotu!" +general.1913="Klikkaa [TÄSTÄ] täyttääksesi sen kun olet valmis." +general.1914="Viimeistele vikailmoituksesi nettisivuillamme!" +general.1915="Klikkaa vaihtaaksesi!" +general.1916="Kaikki" +general.1917="Tämä kuukausi" +general.1918="Tämä viikko" +general.1919="Sienilehmä" +general.1920="Veriefekti käytössä!" +general.1921="Veriefekti poissa käytöstä!" +general.1922="Lunasta palkintosi lobbyssa!" +general.1923="Olet nyt Hypixel-levelillä %%level%%!" +general.1924="TASONNOUSU!" +general.1925="%%multipier%%x kolikkokerroin avattu!" +general.1926="TASONNOUSU" +general.1927="+%%amount%% Sielua" +general.1928="Sika" +general.1929="Rautagolemi" +general.1930=" vuosi" +general.1931=" kuukausi" +general.1932=" viikko" +general.1933=" viikkoa" +general.1934=" päivä" +general.1935=" tunti" +general.1936=" minuutti" +general.1937=" sekunti" +general.1938="Housing-teemat" +general.1939="Muodonmuutokset" +general.1940="Vempaimet" +general.1941="Hatut" +general.1942="Lemmikit" +general.1943="Asun osat" +general.1944="Eleet" +general.1945="Emotet" +general.1946="Kaavut" +general.1947="Yleinen" +general.1948="Harvinainen" +general.1949="Eeppinen" +general.1950="Legendaarinen" +general.1951="d " +general.1952="h " +general.1953="m " +general.1954="s" +general.1955="Kallokuningas" +general.1956="Vesivipellys" +general.1957="Hetkinen! Et voi käyttää nimeä %%name%% salanimenäsi!" +general.1958="TNT Wizard -haaste" +general.1959="Puuttuvia argumentteja! Komento: %%usage%%" +general.1960="Kissa" +general.1961="Kana" +general.1962="Lehmä" +general.1963="Hevonen" +general.1964="Kani" +general.1965="Lammas" +general.1966="Kyläläinen" +general.1967="Susi" +general.1968="Jouluerikoinen" +general.1969="Voima" +general.1970="Elpyminen" +general.1971="Roiskahtava taikajuoma" +general.1972="Roiskahtavat taikajuomat" +general.1973="Tuplahypyt" +general.1974="Tuplahyppy" +general.1975="Kolikko" +general.1976="Näytetään tilastot: %%name%%!" +general.1977="Kartta" +general.1978="Käytä tätä Karttaa navigoidaksesi maailmassa." +general.1979="Et voi hypätä tämän pelaajan selkään juuri nyt!" +general.1980="Et voi käyttää /me-komentoa hiljennettynä." +general.1981="Ohitit liian monta tallennuspistettä!" +general.1982="Virhe ilmaantui tallentaessa tuloksiasi, ole hyvä ja ilmoita tästä ylläpidolle: %%time%%" +general.1983="Murhaajana tapa etsivä 15 sekunnin kuluessa siitä kun olet saanut aseesi" +general.1984="Anna murhaajan huitoa sinua miekallaan kun olet haavoittumaton" +general.1985="???" +general.1986="Salainen saavutus" +general.1987="Voita %s peli murhaajana" +general.1988="Voita %s peli viattomana tai etsivänä kuolematta" +general.1989="Tappoja yhteensä: " +general.1990="Voittoja yhteensä: " +general.1991="Kolikot: " +general.1992="%%counter%%. %%value%%" +general.1993="Kauppa" +general.1994="Kosmeettiset esineeni" +general.1995="Klikkaa selataksesi!" +general.1996="Ammusjälki" +general.1997="Ammusjäljet" +general.1998="Voitontanssi" +general.1999="Voitontanssit" +general.2000="Viimeistelyefekti" +general.2001="Viimeistelyefektit" +general.2002="Symboli" +general.2003="Symbolit" +general.2004="Suihke" +general.2005="Suihkeet" +general.2006="Viimeinen sana" +general.2007="Viimeiset sanat" +general.2008="Puukko" +general.2009="Puukot" +general.2010="Tappolaput" +general.2011="Tappolappu" +general.2012="Ei tarpeeksi tilaa tämän %%category%% suorittamiseksi!" +general.2013="Siisti tanssi" +general.2014="Taputuksia" +general.2015="Hienoa työtä!" +general.2016="Siistiä" +general.2017="GGWP!" +general.2018="Kiitä vastustajiasi hyvästä pelistä tällä taputuseleellä!" +general.2019="Valitsemalla tämän asetuksen, poistat käytöstä %%category%%." +general.2020="Ele" +general.2021="Pää räjähtää" +general.2022="Pää...RÄJÄHTÄÄ!" +general.2023="Räjäytä muiden pelaajien päät tällä vaikuttavalla eleellä!" +general.2024="Valitse %%category%%: %%name%%" +general.2025="Sydän" +general.2026="Vihaiset kasvot" +general.2027="Creeperin kirkaisu" +general.2028="Itkevät kasvot" +general.2029="Nro. 1" +general.2030="RIP" +general.2031="Pääkallo" +general.2032="Hymynaama" +general.2033="Järkyttyneet kasvot" +general.2034="Peukut alas" +general.2035="Peukut ylös" +general.2036="Vinkkaavat kasvot" +general.2037="Spektri" +general.2038="Hei" +general.2039="Huutavat kasvot" +general.2040="Myrsky" +general.2041="Miekka" +general.2042="Kyllä" +general.2043="Polte" +general.2044="Päivänkakkara" +general.2045="Ei" +general.2046="Pronssinen kilpi" +general.2047="Hopeinen kilpi" +general.2048="Kultainen kilpi" +general.2049="Tähti" +general.2050="Valitse partikkelikuva, joka näkyy pääsi yläpuolella kun aktivoit sen." +general.2051="Veriräjähdys" +general.2052="Tulikengät" +general.2053="Jalkasi syttyvät tuleen tappaessasi vihollisen." +general.2054="Nuotio" +general.2055="Nuotio ilmestyy maahan tappaessasi vihollisen." +general.2056="Keksilähde" +general.2057="Keksejä lentelee ympäriinsä tappaessasi vihollisen." +general.2058="Kokemuspallo" +general.2059="Kokemuspalloja sataa tappamasi vihollisen ruumiin ylle." +general.2060="Viimeinen isku" +general.2061="Ilotulite" +general.2062="Ilotulite laukaistaan tappaessasi vihollisen." +general.2063="Pääraketti" +general.2064="Sydänaura" +general.2065="Rakkaus ympäröi sinut tappaessasi vihollisen." +general.2066="Valitse vaikutus, joka aktivoituu, kun tapat murhaajan viimeisenä viattomana." +general.2067="Salamanisku" +general.2068="Thor herää unestaan tappaessasi vihollisen." +general.2069="Piñata" +general.2070="Rekt" +general.2071="%%killer%% #rektasi pelaajan %%deadedededed%% tässä" +general.2072="Voittoasi kunnioittava hologrammi ilmestyy tappaessasi vihollisen." +general.2073="Hymiö" +general.2074="Hymysi loistaa taivaalla tappaessasi pelaajan." +general.2075="Kalmariohjus" +general.2076="Uusi ystävä syntyy tappaessasi vihollisen." +general.2077="Vihollisen tappaminen synnyttä pyörteen!" +general.2078="Tornado" +general.2079="Vaihda ammusjälkesi." +general.2080="Taika" +general.2081="Nuotit" +general.2082="Vihreä tähti" +general.2083="Ender" +general.2084="Taikajuoma" +general.2085="Sininen pöly" +general.2086="Violetti pöly" +general.2087="Vihainen kyläläinen" +general.2088="Satunnainen" +general.2089="Hypixel Logo" +general.2090="Sängynrikkoja" +general.2091="Sängyn kilpi" +general.2092="GG WP" +general.2093="Rakastan sinua" +general.2094="Anteeksi" +general.2095="Kiitos" +general.2096="Hei hei" +general.2097="Golemratsastus" +general.2098="Näkymättömyyden taikajuoma" +general.2099="Loikkaamisen taikajuoma" +general.2100="TNT-pudotus" +general.2101="VIP" +general.2102="VIP+" +general.2103="MVP" +general.2104="MVP+" +general.2105="Valitse pelissä käytettävä suihke, jolla voit merkitä oman alueesi." +general.2106="Alasinsade" +general.2107="Erityiset ilotulitteet" +general.2108="Lohikäärmeratsastaja" +general.2109="Lohikäärmeratsastaja %%name%%" +general.2110="Ilotulitteet" +general.2111="Vartijat" +general.2112="Meteorisade" +general.2113="Valitse tapasi juhlia voittaessasi pelin." +general.2114="Wither-ratsastaja" +general.2115="Wither-ratsastaja %%name%%" +general.2116="pelaajan %%name%% viimeiset sanat:" +general.2117="Nyt valittuna:" +general.2118="Avattu:" +general.2119="Klikkaa katsellaksesi!" +general.2120="(Sivu %%number%%)" +general.2121="Siirry sivulle %%number%%" +general.2122="Edellinen sivu" +general.2123="Seuraava sivu" +general.2124="YLEINEN" +general.2125="HARVINAINEN" +general.2126="EEPPINEN" +general.2127="Yleisin ensin" +general.2128="Harvinaisin ensin" +general.2129="Järjestää harvinaisuuden mukaan: %%name%%" +general.2130="Ö - A" +general.2131="A - Ö" +general.2132="Asettaa aakkosjärjestykseen %%name%%." +general.2133="Seuraava järjestys: %%next%%" +general.2134="Vasenklikkaa käyttääksesi!" +general.2135="Omistetut esineet ensin: %%color%%%%option%%" +general.2136="Oikeaklikkaa vaihtaaksesi!" +general.2137="Järjestys: %%method%%" +general.2138="Oikeaklikkaa esikatsellaksesi!" +general.2139="Vaaditaan Hypixel-level %%level%%" +general.2140="Avautuu rankin %%rank%% mukana!" +general.2141="Saatavilla kaupasta!" +general.2142="VALITTU!" +general.2143="Klikkaa valitaksesi!" +general.2144="Hardcore" +general.2145="Assassins" +general.2146="Ohitit tallennuspisteen!" +general.2147="Teleportattiin sinut parkourin alkuun!" +general.2148="Teleporttasit" +general.2149="Nopeus" +general.2150="Vastustus" +general.2151="Kiire" +general.2152="Voima" +general.2153="Elpyminen" +general.2154="Tuntematon" +general.2155="Automaattijono" +general.2156="Haluatko olla automaattisesti jonossa seuraavaan peliin edellisen päätyttyä. Vaihda tilaa tästä." +general.2157="Hopea villa" +general.2158="Violetti savi" +general.2159="Purppura savi" +general.2160="Vaaleanpunainen savi" +general.2161="Punainen savi" +general.2162="Oranssi savi" +general.2163="Keltainen savi" +general.2164="Limetinvihreä savi" +general.2165="Vihreä savi" +general.2166="Syaani savi" +general.2167="Vaaleansininen savi" +general.2168="Sininen savi" +general.2169="Ruskea savi" +general.2170="Musta savi" +general.2171="Harmaa savi" +general.2172="Hopea savi" +general.2173="Valkoinen savi" +general.2174="Violetti lasipaneeli" +general.2175="Purppura lasipaneeli" +general.2176="Vaaleanpunainen lasipaneeli" +general.2177="Punainen lasipaneeli" +general.2178="Oranssi lasipaneeli" +general.2179="Keltainen lasipaneeli" +general.2180="Limetinvihreä lasipaneeli" +general.2181="Vihreä lasipaneeli" +general.2182="Syaani lasipaneeli" +general.2183="Vaaleansininen lasipaneeli" +general.2184="Sininen lasipaneeli" +general.2185="Ruskea lasipaneeli" +general.2186="Musta lasipaneeli" +general.2187="Harmaa lasipaneeli" +general.2188="Hopea lasipaneeli" +general.2189="Valkoinen lasipaneeli" +general.2190="Violetti lasi" +general.2191="Purppura lasi" +general.2192="Vaaleanpunainen lasi" +general.2193="Punainen lasi" +general.2194="Oranssi lasi" +general.2195="Keltainen lasi" +general.2196="Limetinvihreä lasi" +general.2197="Vihreä lasi" +general.2198="Syaani lasi" +general.2199="Vaaleansininen lasi" +general.2200="Sininen lasi" +general.2201="Ruskea lasi" +general.2202="Musta lasi" +general.2203="Harmaa lasi" +general.2204="Hopea lasi" +general.2205="Valkoinen lasi" +general.2206="Violetti matto" +general.2207="Purppura matto" +general.2208="Vaaleanpunainen matto" +general.2209="Punainen matto" +general.2210="Oranssi matto" +general.2211="Keltainen matto" +general.2212="Limetinvihreä matto" +general.2213="Vihreä matto" +general.2214="Syaani matto" +general.2215="Vaaleansininen matto" +general.2216="Sininen matto" +general.2217="Ruskea matto" +general.2218="Musta matto" +general.2219="Harmaa matto" +general.2220="Hopea matto" +general.2221="Valkoinen matto" +general.2222="Kaakaopapu [ruskea väriaine]" +general.2223="Saa eniten tappoja Assassins Modessa." +general.2224="Valitse pelissä käytettävien eleiden valikoimasta yksi ele komennolla /gesture härnätäksesi muita pelaajia." +general.2225="Kartan valinta (%%mode%%)" +general.2226="Osta " +general.2227="Palaa edelliseen valikkoon." +general.2228="Osta %%name%% hintaan %%cost%% kolikkoa" +general.2229="Vahvista ostosi" +general.2230="Sulje" +general.2231="Kauppa" +general.2232="Ostit esineen %%item%%!" +general.2233="Klikkaa laittaaksesi päälle!" +general.2234="Jokin meni vikaan käsiteltäessä. Yritä vaihtaa lobbya." +general.2235="Alasimia sataa taivaalta." +general.2236="Kirjoita nimesi taivaalle!" +general.2237="Ratsasta lohikäärmeellä, joka voi tuhota koko kartan." +general.2238="Juhli voittoasi upealla ilotulituksella!" +general.2239="Suorita vartijoiden kutsurituaali." +general.2240="Meteoriparvi sataa alas taivaalta." +general.2241="Ratsasta Witherillä suoraan Endistä - klikkaa ampuaksesi Witherin kalloja." +general.2242="Poistutaan katsojatilasta" +general.2243="Katsotaan pelaajaa %%player%%" +general.2244="VASENKLIKKAA nähdäksesi valikon KYYKKÄÄ poistuaksesi" +general.2245="Käytät nyt oletuksena kolmannen persoonan katselua!" +general.2246="Käytät nyt oletuksena ensimmäisen persoonan katselua!" +general.2247="Poista ensimmäinen persoona käytöstä" +general.2248="Ota ensimmäinen persoona käyttöön" +general.2249="Klikkaa ottaaksesi käyttöön ensimmäisen persoonan katselun käyttäessäsi kompassia!" +general.2250="Klikkaa poistaaksesi ensimmäisen persoonan katselu käytöstä käyttäessäsi kompassia!" +general.2251="Voit myös oikeaklikata pelaajaa katsellaksesi peliä tämän näkökulmasta." +general.2252="Oikeaklikkaa ilmiantaaksesi!" +general.2253="Et voi liittyä tälle palvelimelle." +general.2254="Aiemmin seuraamasi pelaaja ei ole enää elossa, joten katsot nyt pelaajaa %%player%%." +general.2255="Sulje" +general.2256="%%playerCount%% pelaaja" +general.2257="Pelaa uudestaan?" +general.2258="Vasenklikkaa katsoaksesi!" +general.2259=" %%rank%% päättyy %%currentEnd%%" +general.2260="Tunnisteen valinta" +general.2261="Piirakka" +general.2262="Sait seuraavat esineet:" +general.2263="ja %%count%% lisää" +general.2264="Klikkaa näyttääksesi kaikki ostamasi esineet" +general.2265="Jos sinulla on ongelmia, %%url%%ota yhteyttä tukeen%%url%%." +general.2266="Klikkaa ottaaksesi yhteyttä tukeen" +general.2267="Kaikki esineet:" +general.2268="Olet jo lunastanut tämän tässä kuussa!" +general.2269="Ostotapahtumasi on käsitelty!" +general.2270="Sinun täytyy ostaa %%rank%% käyttääksesi tätä!" +general.2271="Et voi käyttää tätä täällä." +general.2272="Valitsit esineen %%value%%!" +general.2273="Et omista tätä esinettä!" +general.2274="Toistetaan" +general.2275="JULKAISTU!" +general.2276="UUSI PTL-PELI!" +general.2277="Ei saatavilla juuri nyt!" +general.2278="Ei ostettavissa juuri nyt!" +general.2279="Vaatimukset eivät täyty!" +general.2280="Tuo 66 kurpitsaa takaisin mille tahansa kauppiaalle. Kurpitsoja putoaa pelaajatapoista Halloweenin aikana." +general.2281="Tarjolla vain rajoitetun ajan!" +general.2282="+KERTALUONTEINEN PALKINTO: %%reward%%" +general.2283="+%%reward%%" +general.2284="Iloinen kurpitsa -saarikoriste" +general.2285="Et voi suorittaa parkouria asun ollessa päällä" +general.2286="Vaikutit jääneen jumiin maailman rajan ulkopuolelle, joten sinut teleportattiin spawnille!" +general.2287="Tämä ominaisuus on poissa käytöstä tässä lobbyssa." +general.2288="%%game%% -kauppa" +general.2289="Valitsit esineen %%item%%!" +general.2290="https://store.hypixel.net" +general.2291="PÄIVITETTY!" +general.2292="Tonneittain kloonejasi ilmestyy twerkkaamaan." +general.2293="Et ole tuntenut pelkoa ennen kuin olet ollut yksin pimeässä ja ajatellut tätä voitontanssia." +general.2294="Ghast-ratsastaja" +general.2295="Twerk-apokalypsi" +general.2296="Halla" +general.2297="Yeehaw" +general.2298="Yövuoro" +general.2299="Kauhu" +general.2300="Sateenkaari-Dolly" +general.2301="Luo Dolly-lammas. Kun lyöt Dollya, tämä monistautuu." +general.2302="Nyt on päivä, nyt on yö, nyt on päivä, nyt on yö." +general.2303="Ratsasta hevosella kuin olisi vuosi 1876." +general.2304="Jäädytä alue ympäriltäsi absoluuttiseen nollapisteeseen." +general.2305="Sinulla on %%amount%% saavutuspalkintoa lunastamatta!" +general.2306="Voi ei!" +general.2307="Saavutusta ei löytynyt!" +general.2308="Tälle saavutukselle ei löytynyt valikkoa!" +general.2309="Avataan %%count%% pisteen Saavutuspalkinnolla!" +general.2310="Tämä avataan Saavutuspalkinnoissa!" +general.2311="Keskitä uudelleen" +general.2312="Tämän pelaajan profiili ei ole saatavilla!" +general.2313="VALMIS!" +general.2314="Et syöttänyt hakusanaa!" +general.2315="Ei järjestystä" +general.2316="Avatut ensin" +general.2317="Lukitut ensin" +general.2318="Suoritusten järjestys: %%option%%" +general.2319="Oikeaklikkaa pyörittääksesi!" +general.2320="Klikkaa avataksesi Saavutuspalkinto-valikon" +general.2321="Sinulla on %%amount%% lunastamatonta saavutuspalkintoa!" +general.2322="Sinulla on %%amount%% lunastamatonta saavutuspalkintoa!" +general.2323="Kaapuja voi ottaa käyttöön työkalupalkistasi löytyvästä Keräilyesineet-valikosta." +general.2324="Sekalaisia kosmeettisia esineitä voi käyttää työkalupalkistasi löytyvästä Keräilyesineet-valikosta." +general.2325="Erityinen" +general.2326="Viirejä voi ottaa käyttöön työkalupalkistasi löytyvästä Keräilyesineet-valikosta." +general.2327="Upea" +general.2328="Merkittävä" +general.2329="Vähäinen" +general.2330="%%reward%% %%what%%" +general.2331="Saavutuspalkinto" +general.2332="Hattuja voi ottaa käyttöön työkalupalkistasi löytyvästä Keräilyesineet-valikosta." +general.2333="+%%name%%" +general.2334="Pelaaja: %%name%%" +general.2335="Hypixelin saavutusten suoritus" +general.2336="Jokin meni vikaan lunastaessasi palkintoasi!" +general.2337="Aloitustaso" +general.2338="Kultataso" +general.2339="Lasuriittitaso" +general.2340="Redstone-taso" +general.2341="Smaragditaso" +general.2342="Timanttitaso" +general.2343="Sinulla ei ole tarpeeksi pisteitä lunastaaksesi tätä palkintoa!" +general.2344="Lunastettiin %%points%% saavutuspisteen palkinto!" +general.2345="Olet jo lunastanut tämän palkinnon!" +general.2346="Saavutuspalkinnot" +general.2347="Avaa erityisiä palkintoja metsästämällä uutterasti saavutuksia" +general.2348="Vaaditut pisteet: %%points%%" +general.2349="Palkinto: " +general.2350="Palkinnot: " +general.2351="Olet jo lunastanut tämän palkinnon!" +general.2352="Et voi lunastaa tätä vielä!" +general.2353="Klikkaa keskittääksesi valikon viimeisimmän palkintosi kohdalle" +general.2354="Vieritä yhdellä" +general.2355="Siirry loppuun" +general.2356="Palaa alkuun" +general.2357="Vieritä oikealle" +general.2358="Vieritä vasemmalle" +general.2359="Vasenklikkaa: %%action%%" +general.2360="Oikeaklikkaa: %%action%%" +general.2361="%s+%s%d%s Hypixel-experienceä" +general.2362="Klikkaa näyttääksesi 'Saavutukset: %%holder%%'!" +general.2363="Pisteet: %%points%%" +general.2364="Edistyminen: %%progress%%" +general.2365="Saavutus avattu!" +general.2366="Saavutus lukittu!" +general.2367="Taso avattu!" +general.2368="Taso lukittu!" +general.2369="Näytä Tasosaavutukset" +general.2370="Klikkaa näyttääksesi 'Tasosaavutukset: %%title%%'" +general.2371="Haastesaavutukset" +general.2372="Tasosaavutukset" +general.2373="Näytä Haastesaavutukset" +general.2374="Klikkaa näyttääksesi 'Haastesaavutukset: %%title%%'" +general.2375="Avatut saavutukset ensin: %%option%%" +general.2376="Asettaa aakkosjärjestykseen A-Ö" +general.2377="Eniten suoritettuja tasoja" +general.2378="Asettaa laskevaan järjestykseen suoritettujen tasojen mukaan." +general.2379="Eniten pisteitä" +general.2380="Järjestää saavutuspisteiden mukaan suurimmasta pienimpään." +general.2381="Vähiten pisteitä" +general.2382="Järjestää saavutuspisteiden mukaan pienimmästä suurimpaan." +general.2383="Vähiten suoritettuja tasoja" +general.2384="Asettaa nousevaan järjestykseen suoritettujen tasojen mukaan." +general.2385="Asettaa aakkosjärjestykseen Ö-A" +general.2386="Classic Games" +general.2387="Suoritus yhteensä" +general.2388="Klikkaa tarkastellaksesi saavutuksia!" +general.2389="Klassiset Saavutukset" +general.2390="Haastesaavutukset" +general.2391="Tasosaavutukset" +general.2392="Hakutulokset: " +general.2393="Ei löytynyt vastaavia saavutuksia!" +general.2394="Klikkaa nähdäksesi lisää %%name%% -saavutuksia!" +general.2395="Syötä hakusanasi!" +general.2396="Haku" +general.2397="Etsi saavutus nimen, kuvauksen tai pisteiden mukaan." +general.2398="Haastesaavutukset: %%title%%" +general.2399="Tasosaavutukset: %%title%%" +general.2400="Avattu: %%count%%/%%total%% (%%percent%%)" +general.2401="Pisteet: %%count%%/%%total%% (%%percent%%)" +general.2402="Saavutukset: %%title%%" +general.2403="Haastesaavutukset voidaan suorittaa yhden kerran." +general.2404="Tasosaavutukset koostuvat useista eri tasoista." +general.2405="Viirit" +general.2406="Saavutukset" +general.2407="Saavutuspalkinnot" +general.2408="+1 Toteemipaikka (%%height%% yhteensä)" +general.2409="Toteemin osa: %%part%%" +general.2410="Kustomoi Saavutustoteemiasi uusilla osilla saavutuspalkintovalikossa." +general.2411="+Legendaarinen Saavutustoteemi-companion" +general.2412="Saavutustoteemi on erityinen companion, jota voi kustomoida saavutuspalkintovalikossa." +general.2413="Et ole avannut tätä toteemipaikkaa vielä!" +general.2414="Valittu: %%type%%" +general.2415="Klikkaa valitaksesi osan!" +general.2416="Tämä paikka avataan %%required%% pisteen saavutuspalkintona!" +general.2417="Toteemin muokkaus" +general.2418="Kustomoi Saavutustoteemiasi!" +general.2419="%%required%% pisteellä voit avata Saavutustoteemi-companionin." +general.2420="Palaa takaisin silloin muokataksesi sen ulkonäköä!" +general.2421="Et ole vielä avannut Saavutustoteemia!" +general.2422="Toteemin osa: %%slot%%" +general.2423="Et ole avannut tätä osaa vielä!" +general.2424="Valitsit osan %%what%% paikalle %%slot%%!" +general.2425="Osa lukittu!" +general.2426="Vaaditut pisteet: %%points%%" +general.2427="Harvinaisuus: %%name%%" +general.2428="Lintupää" +general.2429="Nuolirunko" +general.2430="Matorunko" +general.2431="Outo runko" +general.2432="Ensimmäinen paikka" +general.2433="Toinen paikka" +general.2434="Kolmas paikka" +general.2435="Neljäs paikka" +general.2436="Viides paikka" +general.2437="Kuudes paikka" +general.2438="Seitsemäs paikka" +general.2439="Valloita tiesi tähtiin tällä erityisellä saavutustoteemilla. Voit kustomoida tätä companionia Saavutuspalkintovalikossa!" +general.2440="Saavutustoteemi" +general.2441="Klikkaa lopettaaksesi seurannan!" +general.2442="Klikkaa seurataksesi!" +general.2443="Saavutusseuranta" +general.2444="Et seuraa yhtään saavutusta." +general.2445="Selaa tasosaavutuksia ja klikkaa niitä, joita haluat seurata." +general.2446="Täällä ei ole mitään!" +general.2447="Vasenklikkaa lopettaaksesi seurannan!" +general.2448="Oikeaklikkaa näyttääksesi 'Saavutukset: %%holder%%'!" +general.2449="Sinun tulee olla vähintään %%rank%% , jotta voit käyttää saavutusseurantaominaisuutta!" +general.2450="Saavutusseuranta %%rank%%" +general.2451="Seuraa saavutuksia päästäksesi niihin nopeasti tässä valikossa ja saadaksesi välitöntä palautetta edistymisestäsi" +general.2452="Saavutuksen '%%achievement%%' edistyminen: %%progress%%" +general.2453="Seurantaviestit" +general.2454="Käytössä: %%yesNo%%" +general.2455="Näyttää edistymisesi joka kerta kun teet jotain saavutuksen suorittamiseksi" +general.2456="Vieritä paljon" +general.2457="Lunasta %%required%% pisteen palkinto avataksesi Saavutustoteemi-companionin." +general.2458="Toteemin väri: %%slot%%" +general.2459="Et ole avannut tätä väriä vielä!" +general.2460="Valitsit värin %%what%% paikalle %%slot%%!" +general.2461="Osa: %%type%%" +general.2462="Väri: %%color%%" +general.2463="Vasenklikkaa valitaksesi osan!" +general.2464="Oikeaklikkaa valitaksesi värin!" +general.2465="Tumma" +general.2466="Ei mitään!" +general.2467="Kuvioitu runko" +general.2468="Kulmarunko" +general.2469="Kuutiorunko" +general.2470="Raitarunko" +general.2471="Lukkorunko" +general.2472="Reaktorirunko" +general.2473="Iloinen pää" +general.2474="Pong-runko" +general.2475="Ikkunarunko" +general.2476="Huono aamu -pää" +general.2477="Surullinen pää" +general.2478="Yhteysrunko" +general.2479="Kissapää" +general.2480="Retropää" +general.2481="A-runko" +general.2482="Retrorunko" +general.2483="B-runko" +general.2484="Ylikasvanut pää" +general.2485="Juhlarunko" +general.2486="Päivänkakkararunko" +general.2487="Roosarunko" +general.2488="Ruohorunko" +general.2489="Steampunk-pää" +general.2490="Putkirunko" +general.2491="Uunirunko" +general.2492="Ydinrunko" +general.2493="Ylikasvanut" +general.2494="Steampunk" +general.2495="Retro" +general.2496="Tyyli: %%color%%" +general.2497="Oikeaklikkaa valitaksesi tyylin!" +general.2498="Toteemin tyyli: %%slot%%" +general.2499="Toteemin tyyli" +general.2500="Et ole avannut tätä tyyliä vielä!" +general.2501="Valitsit tyylin %%what%% paikalle %%slot%%!" +general.2502="Tyyliä ei ole vielä avattu!" +general.2503="%%style%% Toteemin tyyli" +general.2504="Toteemityyleillä voit vaihtaa toteemisi väriä ja ulkonäköä. Jokainen tyyli on saatavilla kaikille toteemin osillesi." +general.2505="Sinun tulee olla vähintään %%rank%% , jotta voit käyttää seurantaominaisuutta!" +general.2506="Et voi lähettää viestejä tälle pelaajalle." +general.2507="Nykyinen tila: %%color%%%%state%%" +general.2508="Klikkaa vaihtaaksesi tilaksi %%color%%%%state%%!" +general.2509="%%setting%% on nyt %%color%%%%state%%!" +general.2510="Korkein" +general.2511="Korkea" +general.2512="Keskitaso" +general.2513="Matala" +general.2514="Ylläpito ja kaverit voivat lähettää sinulle viestejä." +general.2515="Ylläpito, kaverit ja Guildin jäsenet voivat lähettää sinulle viestejä." +general.2516="Ylläpito, kaverit, guildin jäsenet ja partyn jäsenet voivat lähettää sinulle viestejä." +general.2517="Kuka tahansa voi laittaa sinulle viestiä." +general.2518="Ylläpito ja kaverit voivat lähettää sinulle party-kutsuja." +general.2519="Ylläpito, kaverit ja guildin jäsenet voivat lähettää sinulle party-kutsuja." +general.2520="Kuka tahansa voi lähettää sinulle party-kutsuja." +general.2521="Ylläpito ja kaverit voivat lähettää sinulle guild-kutsuja." +general.2522="Ylläpito, kaverit ja partyn jäsenet voivat lähettää sinulle guild-kutsuja." +general.2523="Kuka tahansa voi lähettää sinulle guild-kutsuja." +general.2524="Vain ylläpito voi lähettää sinulle kaveripyyntöjä." +general.2525="Ylläpito ja guildin jäsenet voivat lähettää sinulle kaveripyyntöjä." +general.2526="Ylläpito, guildin jäsenet ja partyn jäsenet voivat lähettää sinulle kaveripyyntöjä." +general.2527="Kuka tahansa voi lähettää sinulle kaveripyyntöjä." +general.2528="Kirosanasuodattimen taso" +general.2529="Muuta chatin kirosanasuodattimen vahvuutta." +general.2530="Yksityisviestien yksityisyys" +general.2531="Party-kutsujen yksityisyysasetukset" +general.2532="Guild-kutsujen yksityisyysasetukset" +general.2533="Kaveripyyntöjen yksityisyysasetukset" +general.2534="Muuta sitä, kuka voi lähettää sinulle party-kutsuja." +general.2535="Muuta sitä, kuka voi lähettää sinulle guild-kutsuja." +general.2536="Muuta sitä, kuka voi lähettää sinulle kaveripyyntöjä." +general.2537="Vahva suodatin" +general.2538="Heikko suodatin" +general.2539="Pois" +general.2540="Tapahtu virhe käsiteltäessä pyyntöäsi. Yritä myöhemmin uudelleen!" +general.2541="Sinä" +general.2542="Hyvää joulua! Lahjoja on ilmestynyt ympäri karttaa!" +general.2543="Palkintoja voi lunastaa enintään sekunnin välein!" +general.2544="Tätä osaa ei näytetä." +general.2545="Erityinen päivittäinen tehtävä: SkyWars - Pohjoisnapa" +general.2546="YLEINEN Lahja" +general.2547="HARVINAINEN Lahja" +general.2548="EEPPINEN Lahja" +general.2549="LEGENDAARINEN Lahja" +general.2550="Löydä 30 ympäri karttoja siroteltuja arkkua" +general.2551="Oikea joulupukki" +general.2552="Löydä kaikki lobby -lahjat jokaisesta lobbysta. " +general.2553="Joulu 2017" +general.2554="Ei, ei ole joulu enää (tai vielä)!" +general.2555="Hypixel-lahjat" +general.2556="Löydä ympäri lobbyja sirotellut lahjapaketit!" +general.2557="Lahjoista saat kolikoita ja experienceä." +general.2558="Tila:" +general.2559="Päälobby" +general.2560="Löydä kaikki lahjat ansaitaksesi Oikea joulupukki -saavutuksen!" +general.2561="Kausittaiset" +general.2562="Kausittaiset saavutukset" +general.2563="Animoitu Joe-pingviini -hattu" +general.2564="Animoitu Sammy-keksi -hattu" +general.2565="Animoitu Comet-poro -hattu" +general.2566="+%%amount%% %%name%%" +general.2567="Joulutodistevempain" +general.2568="Adventtikalenteri" +general.2569="Hyvää joulua" +general.2570="Puhu Jouluoppaalle Päälobbyssa" +general.2571="Metsästys alkakoon" +general.2572="Löydä kaksi lahjaa lobbysta" +general.2573="Palauta esineet jokaiselle Jouluhahmolle yhdessä Bed Wars -pelissä" +general.2574="Joulutehtävien suorittaja" +general.2575="Suorita 5 joulutehtävää" +general.2576="Käytä komentoa /booster käyttääksesi henkilökohtaisia boostereitasi, jotka väliaikaisesti lisäävät ansaitsemiesi kolikoiden määrää" +general.2577="+%%amount%% päivittäinen palkintomerkki" +general.2578="Käytä Palkintomerkkejä Lähettimiehen luona missä tahansa lobbyssa lunastaaksesi ylimääräisiä päivittäisiä palkintoja" +general.2579="Adventtikalenteri 2017" +general.2580="HYVÄÄ JOULUA TOIVOO HYPIXEL" +general.2581="Klikkaa avataksesi Adventtikalenteri-valikon" +general.2582="Voit lunastaa tämän päivän Adventtikalenterin palkinnon!\nKlikkaa tästä lunastaaksesi!" +general.2583="Hypixelin adventtikalenteri" +general.2584="Hypixelin adventtikalenteri %%year%%" +general.2585="Adventtikalenteri %%year%%" +general.2586="Päiviä jouluun: SE ON TÄNÄÄN!" +general.2587="Päiviä jouluun: %%remaining%%" +general.2588="Ei, ei enää ole lahjojen aika (tai vielä)!" +general.2589="Jouluopas" +general.2590="HYVÄÄ JOULUA JA ONNELLISTA UUTTA VUOTTA" +general.2591="Joulu-ukko" +general.2592="Kauhu-ukko" +general.2593="Joulu-ukko" +general.2594="Kauhu-ukko" +general.2595="Löysit %%coins%% kolikkoa tästä lahjasta!" +general.2596="Löysit %%xp%% Hypixel-experienceä tästä lahjasta!" +general.2597="KLIKKAA TÄSTÄ saadaksesi lisätietoa lahjajahdista!" +general.2598="Kokeile myös: /presents" +general.2599="Lähettimies" +general.2600="Löysit kaikki lahjat tästä lobbysta!" +general.2601="Löysit Päälobbyn lahjan! %%count%%" +general.2602="Löysit lahjan! %%count%%" +general.2603="Joulutapahtuma" +general.2604="Löysit %%coins%% pelin %%gametype%% kolikkoa tästä lahjasta!" +general.2605="Olet jo löytänyt tämän lahjapaketin!" +general.2606="Avataan %%count%% pisteen Saavutuspalkinnolla!" +general.2607="Guildin tarkistaminen epäonnistui, yritä myöhemmin uudelleen!" +general.2608="Ratsasta Witherillä suoraan Netheristä - klikkaa ampuaksesi Witherin kalloja." +general.2609="Tapahtui virhe! Yritä uudelleen!" +general.2610="+%%amount%% polettia" +general.2611="Valikkoon %%menu%%" +general.2612="Käytä satunnaista %%cosmetic%%!" +general.2613="Poistutaan jonosta!" +general.2614="Tämän ominaisuuden avulla voit löytää helposti tietyn esineen." +general.2615="Päätä peli olemalla kolmen parhaan joukossa." +general.2616="Kärkikolmikkohaaste" +general.2617="Arvailijahaaste" +general.2618="Arvaa 5 aihetta oikein Guess The Build -pelimuodossa." +general.2619="Avaa \"Mestarirakentajan hattu\"" +general.2620="%%rank%%-rankkisi" +general.2621="%%rank%%-rankkisi vanhenee %%time%% kuluttua." +general.2622="Pitääksesi rankin %%rank%% ja kaikki sen tuomat ominaisuudet osta lisäaikaa kaupasta." +general.2623="Sinun %%rank%% Rank Addon vanhentuu %%time%% kuluttua. Tämän jälkeen rankiksesi palautetaan %%old%%." +general.2624="Pitääksesi rankin %%rank%% ja kaikki sen tuomat ominaisuudet osta lisäaikaa kaupasta:" +general.2625="VIERAILE KAUPASSA" +general.2626="Vanhenee ajassa: %%time%%" +general.2627="%%player%% ei voi olla Guildin johtaja sillä hän ei ole ostanut rankkia" +general.2628="Sosiaalisen median palkinnot" +general.2629="Klikkaa nähdäksesi kaikki saatavilla olevat sosiaalisen median palkinnot!" +general.2630="Huomasimme, että sinulla on edelleen salanimi käytössäsi. Tällöin MVP+-partikkelisi eivät välttämättä näy!" +general.2631="Saavutuspisteet-kaapu" +general.2632="Guildit" +general.2633="Partyt" +general.2634="Parkourhaaste aloitettu! Käytä komentoa /parkour reset aloittaaksesi alusta tai komentoa /parkour checkpoint teleportataksesi edelliselle tallennuspisteelle!" +general.2635="Läpäisit tämän parkourin osion ajassa %%time%% (henkilökohtainen ennätys: %%pb%%)." +general.2636="Läpäisit tämän parkourin osion ajassa %%time%% ja löit henkilökohtaisen ennätyksesi (%%pb%%)!" +general.2637="Läpäisit tämän parkourin osion ajassa %%time%%." +general.2638="Hanki %s voiton putki" +general.2639="Saavutukset: Classic Games" +general.2640="Derperino" +general.2641="Nuuh" +general.2642="Vikinä" +general.2643="Pääsiäismuna" +general.2644="Pääsiäismunat" +general.2645="Pupuräjähdys" +general.2646="Pääsiäispupuja ilmestyy tappaessasi vihollisen." +general.2647="Kanatorni" +general.2648="Vihollisen tappaminen synnyttää kanatornin." +general.2649="Pääsiäismunavarkaus" +general.2650="Pääsiäismunia putoilee ympäriinsä tappaessasi vihollisen." +general.2651="Piip!" +general.2652="Munakuljetus" +general.2653="Suklaajuhla" +general.2654="Pääsiäiscreeper" +general.2655="Suuri munajahti" +general.2656="Väärät munat" +general.2657="Pääsiäispupu" +general.2658="Pääsiäispuput" +general.2659="Luo joukon pääsiäispupuja, jotka munivat munia." +general.2660="Kori" +general.2661="Nopeatempoiset 1v1, 2v2 ja 4v4 Duelit!" +general.2662="∙ UHC Duels" +general.2663="∙ SkyWars Duels" +general.2664="∙ Mega Walls Duels" +general.2665="∙ Combo Duels" +general.2666="∙ NoDebuff Duels" +general.2667="∙ Classic Duels" +general.2668="∙ Bow Duels" +general.2669="Avaa: %%item%%" +general.2670="Hinta: %%coins%%" +general.2671="Vahvuuden taikajuoma +20% (%%seconds%%s)" +general.2672="Roiskahtava tulenkestävyyden taikajuoma" +general.2673="Roiskahtava nopeuden taikajuoma" +general.2674="Roiskahtava nopeuden taikajuoma II" +general.2675="Roiskahtava elpymisen taikajuoma" +general.2676="Elpymisen taikajuoma (16s)" +general.2677="Mestarin timanttimiekka" +general.2678="Roiskahtava parantumisen taikajuoma" +general.2679="Valkoinen nahkahattu" +general.2680="Valkoiset nahkasaappaat" +general.2681="Liekehtivä" +general.2682="Tulisuojaus" +general.2683="Elpymisen taikajuoma" +general.2684="Roiskahtava myrkyn ja hitauden taikajuoma" +general.2685="Roiskahtava sokeuden taikajuoma" +general.2686="Korotetun vahingon taikajuoma" +general.2687="Suorittamalla tehtäviä ja haasteita\nansaitset %%coins%%, %%exp%% ja paljon muuta!" +general.2688="Paras voittoputki" +general.2689="Pisteet" +general.2690="Pro Mode -voitot" +general.2691="Guess the Build -voitot" +general.2692="Oikeat arvaukset" +general.2693="Ääniä yhteensä" +general.2694="Voittobonus" +general.2695="Kaikki pelimuodot" +general.2696="Laitettiin sinut jonoon palvelimelle, jossa %%player%% on..." +general.2697="∙ OP Duels" +general.2698="Saavutuspisteet: %%points%%" +general.2699="Top Hypixelin Guildit" +general.2700="Guild Experience" +general.2701="%%suffix%% (%%time%%)" +general.2702="Hanki 5 VT tai VA seitsemässä sekunnissa Herobrinenä" +general.2703="Hanki yhteensä 200 VT tai VA takaapäin Endermanina" +general.2704="Hanki 25 VT tai VA yli 50 palikan päästä Luurankona" +general.2705="Vaikuta viiteen tiimitoveriin yhdellä Palauttavalla siemauksella deathmatchin aikana Lehmänä" +general.2706="EMP" +general.2707="Osu kuuteen viholliseen yhdellä A-23 Protokollalla" +general.2708="Kerää 8000 energiaa tappamalla vihollisia" +general.2709="Pidä 12 lunastettua taikajuomaa tavaraluettelossasi Luopiona" +general.2710="Tee yhteensä 50 000 wither-vahinkoa Pelon herrana" +general.2711="Hanki 3 viimeistelytappoa kuudessa sekunnissa Pelon herrana" +general.2712="Hanki yhteensä 10 VT tai VA pesähämähäkeilläsi Hämähäkkinä" +general.2713="Valmista rautamiekka ja hanki 7 VT sillä miekalla ilman kuolemia, kun pelaat Hämähäkillä" +general.2714="+%%amount%% Myyttistä suosiota" +general.2715="Hanki yhteensä 15 VT Ihmissutena, kun sinulla on alle 5 EP" +general.2716="%%points%% Saavutuspistettä" +general.2717="Palkinto:" +general.2718="Voita Feeniksinä peli, jossa sinä ja henkiin herättämäsi tiimitoveri olette yhä elossa" +general.2719="Tapa 500 pelaajaa niin, että sinä ja uhrisi olette vedessä." +general.2720="Asetit %%block%% pelaajalle %%name%%!" +general.2721="%%builder%% asetti %%block%% sinulle" +general.2722="Tätä pelaajaa ei löytynyt!" +general.2723="ruusun" +general.2724="räjähteitä" +general.2725="piikikästä tavaraa" +general.2726="kakun" +general.2727="jotain vihreää" +general.2728="Valitse pelimuoto" +general.2729="Et voi haastaa itseäsi Dueliin!" +general.2730="Ei löydetty pelaajaa nimellä '%%target%%'" +general.2731="Klikkaa kutsuaksesi pelaaja %%player%% guildiin %%name%%!" +general.2732="Pelaa %%name%%" +general.2733="%%count%% pelaamassa juuri nyt!" +general.2734="Pelaa %%name%%" +general.2735="Pelaajalla %%name%% on %%mode%%-kutsut poissa käytöstä!" +general.2736="Luo mysteeriolento" +general.2737="Pelaa Duels" +general.2738="DUELS %%mode%%" +general.2739="Tämä Duels-pelimuodon tuloksia ei lasketa pelin %%mode%% yleisiin tilastoihin, saavutuksiin tai tehtäviin." +general.2740="Klikkaa pelataksesi peliä %%name%%!" +general.2741="UUSI" +general.2742="PALAAVA KARTTA!" +general.2743="Katniss Everdeenin tyyliin" +general.2744="Pelaajia ei liittynyt tarpeeksi, joten peli ei käynnistynyt. Yritä myöhemmin uudelleen." +general.2745="Tarpeeksi pelaajia ei liittynyt! Aloitus peruutettiin." +general.2746="Tarvitaan vähintään %%amount%% pelaajaa, jotta peli voi alkaa." +general.2747="Pelaajien vähimmäismäärä ei täyttynyt, ole hyvä ja yritä liittyä peliin uudelleen myöhemmin." +general.2748="Pelaajien vähimmäismäärä ei täyttynyt! Lähetetään viesti lobbyihin." +general.2749="Pelaajien vähimmäismäärä ei täyttynyt. Lähetetään viesti lobbyihin ja lisätään ajastimen aikaa." +general.2750="Ladataan..." +general.2751="Virhe ladattaessa" +general.2752="Rajoita kokoa" +general.2753="Klikkaa suodattaaksesi Guildeja niiden jäsenmäärän mukaan" +general.2754="Ei rajoitusta" +general.2755="Näytä kaikki Guildit riippumatta siitä, kuinka monta jäsentä niissä on." +general.2756="%%amount%% pelaajaa" +general.2757="Näyttää vain Guildit, joissa on %%amount%% jäsentä." +general.2758="Guildien listaa päivitetään jo!" +general.2759="Aseta suodattimia" +general.2760="Järjestä tulokset" +general.2761="Valitse, kuinka haluat järjestää tulokset." +general.2762="Järjestä jäsenmäärän mukaan" +general.2763="Näytä jäsenmäärältään suurimmat Guildit ensin" +general.2764="Näytä jäsenmäärältään pienimmät Guildit ensin" +general.2765="Järjestä Guildin tason mukaan" +general.2766="Näytä tasoltaan suurimmat Guildit ensin" +general.2767="Näytä tasoltaan pienimmät Guildit ensin" +general.2768="Järjestä satunnaisesti" +general.2769="Näytä Guildit satunnaisessa järjestyksessä" +general.2770="Valitse pelit" +general.2771="Klikkaa suodattaaksesi Guildit niiden pelaamien pelien mukaan.\nNäytämme sinulla vain Guildit, jotka pelaavat kaikkia valitsemiasi pelejä." +general.2772="VALITTU" +general.2773="Klikkaa valitaksesi" +general.2774="Tallenna ja palaa takaisin" +general.2775="Oletusarvonimi" +general.2776="Tämä arvonimi on jo oletuksena! Muuttaaksesi tätä valitse toinen arvonimi oletukseksi." +general.2777="Oletusarvonimi" +general.2778="Aseta tämä oletusarvonimeksi" +general.2779="Et voi enää luoda uusia arvonimiä" +general.2780="Sinulla voi olla korkeintaan %%amount%% omaa guildin arvoa!" +general.2781="Luo uusi arvonimi" +general.2782="Klikkaa luodaksesi uuden arvonimen" +general.2783="Et voi enää luoda uusia arvonimiä!" +general.2784="Tapahtui virhe avattaessa oikeusvalikkoa! (%%error%%)" +general.2785="Sinulla ei ole guildia!" +general.2786="Syötä arvonimen" +general.2787="arvonimi tähän!" +general.2788="Arvonimessä täytyy olla vähintään kaksi merkkiä!" +general.2789="Guildin johtaja" +general.2790="GUILDIN JOHTAJA" +general.2791="Et voi antaa uudelle arvolle tätä nimeä!" +general.2792="Arvonimi saa sisältää ainoastaan numeroita, kirjaimia ja välilyöntejä!" +general.2793="Tämä arvonimi on jo käytössä sinulla!" +general.2794="Luotiin arvonimi %%name%%!" +general.2795="Muokkaa Guildin nimeä" +general.2796="Vaihda guildisi nimeä" +general.2797="Muokkaa Guildin tervetuloviestiä" +general.2798="Vaihda guildisi päivän viestiä" +general.2799="Muokkaa Guildin tunnistetta" +general.2800="Vaihda guildisi tunnistetta" +general.2801="Muokkaa arvonimiä" +general.2802="Jäsenien ylentäminen tai alentaminen (omaan arvonimeen asti)" +general.2803="Guild-etsimen asetukset" +general.2804="Muokkaa sitä kuinka guildisi näytetään Guild-etsimessä, jos ollenkaan" +general.2805="Sihteerien chat" +general.2806="Lähetä ja vastaanota viestejä sihteerien chatissa" +general.2807="Potki jäseniä" +general.2808="Potki jäseniä guildistasi" +general.2809="Hiljennä jäseniä" +general.2810="Hiljennä guildisi jäseniä" +general.2811="Kutsu jäseniä" +general.2812="Kutsu jäseniä guildiisi" +general.2813="Et voi muokata arvonimeä %%rank%%!" +general.2814="Klikkaa muuttaaksesi arvon %%rank%% oikeuksia" +general.2815="Klikkaa poistaaksesi käytöstä" +general.2816="Klikkaa ottaaksesi käyttöön" +general.2817="Tämänhetkinen prioriteetti: %%priority%%" +general.2818="VASENKLIKKAA nostaaksesi prioriteettia" +general.2819="OIKEAKLIKKAA laskeaksesi prioriteettia" +general.2820="Vaihda prioriteettia" +general.2821="Tällä arvonimellä on jo suurin prioriteetti!" +general.2822="Tällä arvonimellä on jo pienin prioriteetti!" +general.2823="Guildin arvonimiin" +general.2824="Sinulla ei ole oletusarvonimiä!" +general.2825="Aseta olemassa oleva rank oletukseksi ennen kuin voit poistaa tämän!" +general.2826="Poista arvonimi" +general.2827="Et voi poistaa tätä arvonimeä, sillä se on oletusarvonimi! Aseta jokin toinen arvonimi oletukseksi voidaksesi poistaa tämän." +general.2828="Poista tämä guild-arvonimi" +general.2829="Arvonimen tunnisteessa täytyy olla vähemmän kuin viisi merkkiä!" +general.2830="Arvonimen tunniste saa sisältää ainoastaan numeroita, kirjaimia ja välilyöntejä!" +general.2831="Tämä arvonimen tunniste on jo käytössä sinulla!" +general.2832="Asetit tunnisteen tyhjäksi, joten poistimme sen tältä guildin arvonimeltä." +general.2833="tunniste tähän!" +general.2834="Muokkaa tunnistetta" +general.2835="Muokkaa tämän arvonimen tunnistetta. Tällä hetkellä: %%tag%%" +general.2836="Palaa edelliselle sivulle" +general.2837="Siirry seuraavalle sivulle" +general.2838="Siinäkö kaikki?!" +general.2839="Zombies-voittaja" +general.2840="Zombies-pikapeli" +general.2841="Mestarietsijä" +general.2842="Party Pooper" +general.2843="Yritetään toimittaa sinulle resurssipakettia..." +general.2844="Resurssipaketti" +general.2845="Tämä peli käyttä resurssipakettia siistejä tekstuureja ja malleja varten, mutta sen lataaminen voi viedä jonkin aikaa." +general.2846="Klikkaa ladataksesi!" +general.2847="Lataa resurssipaketti" +general.2848="Tarvitsetko apua? Klikkaa tästä!" +general.2849="Avaa resurssipakettiopas" +general.2850="Ansaitsemasi kolikot juuri TUPLAANTUIVAT Guildin tasopalkintona!" +general.2851="Arvonimi: %%rank%%" +general.2852="Päivittäinen Exp: %%exp%%" +general.2853="Klikkaa muokataksesi!" +general.2854="Guildisi ei ole avannut tätä!" +general.2855="Guildin tunnisteen väri" +general.2856="Guildin oikeudet" +general.2857="Vain guildin johtaja voi käyttää tätä!" +general.2858="Klikkaa muokataksesi!" +general.2859="Muokkaa guildisi arvonimiä ja niiden oikeuksia" +general.2860="Vain guildin johtaja voi käyttää tätä!" +general.2861="Voivatko pelaajat löytää guildin Guild-etsimestä ja pyytää lupaa liittyä." +general.2862="Klikkaa vaihtaaksesi!" +general.2863="Valitse Guildin pelit" +general.2864="Muuttaa Guild-etsimessä näkyvää Guildin kuvausta." +general.2865="Klikkaa tästä suorittaaksesi komennon /guild settings description ja vaihtaaksesi kuvausta!" +general.2866="Henkilökohtaiset asetukset" +general.2867="Omat Guild-asetukset" +general.2868="Guildin paikalla-tila" +general.2869="Näytä vain paikalla olevat jäsenet käyttäessäsi komentoa /guild list" +general.2870="Guild-ilmoitukset" +general.2871="Vastaanota viestejä siitä, kun guildisi jäsenet tulevat paikalle tai poistuvat" +general.2872="käytössä" +general.2873="poissa käytöstä" +general.2874="Ei aktiivista tehtävää" +general.2875="Tällä hetkellä ei ole aktiivista Guildin tehtävää." +general.2876="Et ole guildissa" +general.2877="Et ole guildissa, joten et voi osallistua Guild tehtäviin." +general.2878="Tehtävän suorittamiseksi on Guildin jäsenten suoritettava haasteita missä tahansa pelissä." +general.2879="Taso %%tier%%: " +general.2880="Palkinto: %%amount%% Guild Experienceä" +general.2881="Viikoittainen Guild-tehtävä" +general.2882="Guildin tasopalkinnot" +general.2883="Tason %%tier%% Guild-kaapu" +general.2884="Guildin jäsenillä on mahdollisuus käytää tason %%tier%% Guild-kaapua lobbyssa." +general.2885="Avautuu tasolla %%level%%" +general.2886="%%chance%% kaksinkertaiset kolikot" +general.2887="Aina kun Guildin jäsen pelaa peliä, on tällä %%chance%%% mahdollisuus saada kaksinkertaisesti kolikoita aina ansaitessaan niitä." +general.2888="%%chance%% kaksinkertainen exp" +general.2889="Aina kun Guildin jäsen pelaa peliä, on tällä %%chance%%% mahdollisuus saada kaksinkertaisesti experienceä koko pelin ajan." +general.2890="Tason %%tier%% foorumikuvake" +general.2891="Kaikki Guildin jäsenet saavat Tason %%tier%% foorumikuvakkeen Hypixelin foorumeille." +general.2892="Guildin tunnisteen enimmäispituutta on kasvatettu 7 merkkiin." +general.2893="Guildin tunnisteen pituus" +general.2894="Guildin jäsenillä voi olla %%color%% Guildin tunniste näkyvillä nimensä vieressä lobbyissa." +general.2895="Guildeilla, joilla oli jo Guildin tunniste ennen guild-päivitystä, tämä avautuu automaattisesti." +general.2896="%%color%% Guildin tunniste" +general.2897="%%a%%- ja %%b%%- partikkelipakkaukset" +general.2898="Guildin jäsenillä on mahdollisuus käyttää %%a%% ja %%b%% -partikkelipaketteja lobbyissa." +general.2899="Kritit" +general.2900="Liekki" +general.2901="Pilvi" +general.2902="Pallo" +general.2903="Sormus" +general.2904="Guildin tasot" +general.2905="Guildin taso: %%level%%" +general.2906="Exp seuraavalle tasolle: %%exp%% (%%percent%%%%%gray%%)" +general.2907="Guildin saavutukset" +general.2908="Saavutuksia suoritettu: %%achieved%%/%%total%%" +general.2909="Virhe" +general.2910="Edistyminen: %%progress%%/%%required%%" +general.2911="Saavuta Guildin taso %%var%%" +general.2912="Experience-kuninkaat" +general.2913="Hanki %%var%% Guild Exp:tä yhdessä päivässä" +general.2914="Voittajat" +general.2915="Voita %%var%% peliä Guildina päivässä" +general.2916="Klikkaa liittyäksesi Discordiin!" +general.2917="Jos Guildillasi on Discord-palvelin, voit lisätä linkin tähän, jotta guildin jäsenet voivat liittyä sinne helposti." +general.2918="Klikkaa asettaaksesi!" +general.2919="Guildin Discord" +general.2920="Guildisi johtaja ei ole asettanut Discord-palvelinta." +general.2921="Guildillasi on Discord-palvelin, johon Guildin jäsenet voivat liittyä." +general.2922="Klikkaa nähdäksesi kutsulinkin" +general.2923="Oikeaklikkaa muokataksesi" +general.2924="Esikatselu: %%preview%%" +general.2925="Klikkaa valitaksesi tämän värin!" +general.2926="Guildin saavutukset" +general.2927="Käänteinen" +general.2928="Normal" +general.2929="Klikkaa vaihtaaksesi!" +general.2930="Tietoja ei löytynyt." +general.2931="Et ole guildissa." +general.2932="Guildia ei ole enää olemassa." +general.2933="Guild" +general.2934="Level" +general.2935="Experience" +general.2936="Top Hypixelin Guildit" +general.2937="Jos Guildillasi on Discord-palvelin, voit lisätä sen linkin tähän, jotta guildin jäsenet voivat liittyä sinne helposti." +general.2938="KLIKKAA NÄHDÄKSESI TILASTOT" +general.2939="Parkourhaaste peruttu!" +general.2940="Parkourhaaste aloitettu!\nKäytä komentoa /parkour checkpoint teleportataksesi edelliselle tallennuspisteelle tai komentoa /parkour cancel lopettaaksesi!" +general.2941="Tee 300k vahinkoa ja palauta 300k elämäpistettä yhdessä pelissä" +general.2942="Herätä 6 pelaajaa henkiin yhdellä kuolemattomien armeijalla" +general.2943="Avaa kirja aina." +general.2944="Älä näytä uudestaan!" +general.2945="Resurssipaketti ladataan nyt automaattisesti." +general.2946="Resurssipaketti ei lataudu automaattisesti." +general.2947="Klikkaa tästä" +general.2948="Avaa resurssipakettikirja!" +general.2949="%%playerCount%% jonossa" +general.2950="Avaa tämä kirja ennen\nkuin lataat resurssipaketin" +general.2951="Lataa resurssipaketti\navaamatta tätä kirjaa" +general.2952="Alkaa %%time%% kuluttua, jos" +general.2953="%%amount%% pelaajaa lisää liittyy" +general.2954="Alkaa %%time%% kuluttua," +general.2955="jotta enemmän pelaajia" +general.2956="voi liittyä" +general.2957="%%amount%% pelaajaa vaaditaan lisää pelin alkamiseksi." +general.2958="%%amount%% pelaaja vaaditaan lisää pelin alkamiseksi." +general.2959="Klikkaa pelataksesi" +general.2960="Satunnainen kartta" +general.2961="Saatavilla olevat palvelimet" +general.2962="Kertoja liitytty" +general.2963="Oikeaklikkaa asettaaksesi suosikiksi!" +general.2964="30 pistettä tapoista/avustuksista vihollislipun kantajaa vastaan" +general.2965="15 pistettä tapoista/avustuksista vihollislipun kantajan lähellä" +general.2966="100 pistettä lipun keräämisestä" +general.2967="30 pistettä hallintapisteen valtaamisesta" +general.2968="5 pistettä TDM-tapoista/avustuksista" +general.2969="Suurmestari" +general.2970="Aikaa nollautumiseen: %%time%%" +general.2971="Guild ansaitsee exp:tä %%rate%%%%%gray%% tahdilla!" +general.2972="Klikkaa nähdäksesi tasopalkinnot!" +general.2973="%%days%% päivää" +general.2974="%%hours%% tuntia" +general.2975="%%minutes%% minuuttia" +general.2976="Tämän päivän exp < %%val%% → %%percent%%%" +general.2977="Tämän päivän exp >= %%val%% → %%percent%%%" +general.2978="Tämän päivän exp: %%exp%%" +general.2979="Nimeä arvonimi uudelleen" +general.2980="Jokin on saattanut mennä vikaan, tarkistathan!" +general.2981="Nimeä uudelleen arvonimi %%rank%%." +general.2982="Klikkaa muokataksesi arvonimeä %%rank%%" +general.2983="Vaihda tunnisteen tilaa" +general.2984="Klikkaa asettaaksesi Guildin johtajan tunnisteen pois päältä." +general.2985="Klikkaa asettaaksesi Guildin johtajan tunnisteen päälle." +general.2986="Vaihda tunnisteen tilaa" +general.2987="Palaa Päälobbyyn." +general.2988="Arvonimen tunnisteessa voi olla enintään %%length%% merkkiä!" +general.2989="Avataan 10 000 saavutuspisteellä" +general.2990="Kultainen saavutusvalikko" +general.2991="Poista Kultainen saavutusvalikko käytöstä" +general.2992="Ota Kultainen saavutusvalikko käyttöön" +general.2993="Vaihtaa valikon saavutukset kultaisiksi." +general.2994="Kultainen saavutusvalikko" +general.2995="Lohikäärme" +general.2996="Tiki" +general.2997="Egyptiläinen" +general.2998="Runko A" +general.2999="Runko B" +general.3000="Runko C" +general.3001="Runko D" +general.3002="Bridge" +general.3003="Bridge Doubles" +general.3004="Bridge Teams" +general.3005="Hahmosi ulkonäkö on nollattu." +general.3006="Näyt nyt muille pelaajille Alexina." +general.3007="Näyt nyt muille pelaajille Stevenä." +general.3008="Et voi käyttää /shout-komentoa katsojana." +general.3009="Klikkaa saadaksesi linkin kauppaan!" +general.3010="Tapahtui virhe ladatessa viimeisimmän turnauksen sijoitustasi" +general.3011="Avataan Tournament Hallissa!" +general.3012="Avataan Tournament Hallissa!" +general.3013="Bridge Duel" +general.3014="Bridge Duels" +general.3015="Pelaa %%mode%%!" +general.3016="Klikkaa pelataksesi!" +general.3017="%%playing%% pelaamassa juuri nyt" +general.3018="Voit äänestää vain ollessasi pelissä" +general.3019="Yksityisyysasetukset" +general.3020="Yksityisyysasetukset " +general.3021="Chatin asetukset" +general.3022="Chatin asetukset" +general.3023="Vaatii rankin %%rank%%" +general.3024="%%suffix%% (%%time%%)" +general.3025="Ingame Store" +general.3026="Kultaiset kit-esineiden nimet" +general.3027="Kultainen kitin nimi" +general.3028="Satunnainen %%time%% ajan" +general.3029="%%name%%" +general.3030="Klikkaa vaihtaaksesi väriksi %%color%%" +general.3031="Valittu: %%color%%" +general.3032="%%name%%" +general.3033="UUSI PÄIVITTÄINEN TEHTÄVÄ: %%mission%%" +general.3034="MVP+-rankin väri" +general.3035="Vaihda etuliitteen värin tilaa" +general.3036="Huomautus: Statukset eivät näy naamioituneena!" +general.3037="%%season%% Battle Pass" +general.3038="Vaihtoehtoinen Pelivalikon asettelu" +general.3039="akvamariini" +general.3040="Turkoosi" +general.3041="Autotip" +general.3042="sininen" +general.3043="tummanvihreä" +general.3044="tummanvioletti" +general.3045="tummanpunainen" +general.3046="Aasi" +general.3047="Duel-kutsujen yksityisyysasetukset" +general.3048="Ansaitse yli 100 palkintoa suorittamalla tehtäviä ja korottamalla Battle Passisi tasoa." +general.3049="Jokainen lyönti 20 sekunnin ajan aktivoinnin jälkeen antaa Wither III -vaikutuksen kolmeksi sekunniksi." +general.3050="Saa Nopeus II 15 sekunniksi sekä 1,5❤!" +general.3051="kultaa" +general.3052="vihreä" +general.3053="Guild-chatin näkyvyys" +general.3054="Guild-viestien äänet" +general.3055="Guildin kirosanasuodattimen taso" +general.3056="Lobbyn liittymisviesti (Oma)" +general.3057="Party-viestien äänet" +general.3058="Partyn kirosanasuodattimen taso" +general.3059="YV-kierosanasuodattimen taso" +general.3060="Kunniatasopilkka" +general.3061="Yksityisviestien ilmoitusäänet" +general.3062="Julkisen chatin kirosanasuodattimen taso" +general.3063="Rankin väri" +general.3064="punainen" +general.3065="Vaatii rankin %%rank%%!" +general.3066="Aseta pääsi päällä kaikissa lobbyissa näkyvä status." +general.3067="Esittele kunniatasoasi." +general.3068="Ylläpito ja kaverit voivat lähettää sinulle Duel-kutsuja." +general.3069="Status" +general.3070="Teleporttaa lähimmän pelaajan luo ja vie puolet tämän elinvoimasta." +general.3071="Määritä, kuuletko ilmoitusäänen saadessasi guild-viestejä." +general.3072="Määritä, kuuletko ilmoitusäänen saadessasi party-viestejä." +general.3073="Määritä, kuuletko ilmoitusäänen saadessasi yksityisviestin." +general.3074="Aseta lobbyn liittymisviestit kohdaltasi päälle tai pois." +general.3075="Piilottaa tai näyttää guild chatin." +general.3076="Aseta päivitysilmoitukset kohdaltasi päälle tai pois." +general.3077="Aseta automaattinen boostereista kiittäminen päälle tai pois." +general.3078="Vaihda vanhan ja uuden Pelivalikon (kompassi) asettelun välillä." +general.3079="Sininen Tron-jälki" +general.3080="Avaa uniikit Tappolaskurit, joilla voit esitellä edistymistäsi." +general.3081="Päivitysilmoitus" +general.3082="(Kaksinkertaiset kolikot + EXP -viikonloppu)" +general.3083="Ruokapöydän tuoli" +general.3084="Korkeaselkäinen ruokapöydän tuoli" +general.3085="Jakkara" +general.3086="Keltainen nojatuoli" +general.3087="Vihreä nojatuoli" +general.3088="Valkoinen nojatuoli" +general.3089="Valkoinen toimistotuoli" +general.3090="Musta toimistotuoli" +general.3091="Punainen sohva" +general.3092="Musta sohva" +general.3093="Vaaleanpunainen sohva" +general.3094="Ruokapöytä" +general.3095="Kahvipöytä" +general.3096="Pitkä pöytä" +general.3097="Pöytä ja tietokone" +general.3098="Jääkaappi-pakastin" +general.3099="Liesi" +general.3100="Pesukone" +general.3101="Kaappi" +general.3102="Nuotio" +general.3103="Jalkalamppu" +general.3104="Taulutelevisio" +general.3105="Koripallokori" +general.3106="Pieni akvaario" +general.3107="Vessa" +general.3108="Lavuaari" +general.3109="Kylpy" +general.3110="Suihkukoppi" +general.3111="Valaspatsas" +general.3112="Koirapatsas" +general.3113="Ritaripatsas" +general.3114="Kaikki" +general.3115="Ammu valtava Kurpitsalaser joka tuhoaa kaiken tieltään! Varo, ase potkaisee." +general.3116="Tappamasi vihollisen sielu repeytyy hänen kehostaan ja jää hetkeksi leijumaan maanpäälliseen maailmaan." +general.3117="Viimeistelymäärääsi esittelevä hologrammi ilmestyy tappaessasi vihollisen." +general.3118="Kun tuhoat sängyn, näytä valittu Symbolisi sen yläpuolella." +general.3119="Siirretään sinut kohteeseen %%session%%" +general.3120="Klikkaa nähdäksesi Hypixelin nettisivut" +general.3121="Nuolista valuu verta niiden osuessa" +general.3122="Avataan Halloween Bundlessa!" +general.3123="Hytalen traileri" +general.3124="%%var%% guildin jäsentä paikalla samanaikaisesti!" +general.3125="Perhe" +general.3126="Iske vihollista Varjoräjähdyksellä yli 35 palikan etäisyydeltä" +general.3127="Ylläpito, kaverit ja guildin jäsenet voivat lähettää sinulle Duel-kutsuja." +general.3128="Kuka tahansa voi lähettää sinulle Duel-kutsuja." +general.3129="Kaikki pelit" +general.3130="Yleiset" +general.3131="Double Up!" +general.3132="Infection V2" +general.3133="Tulossa pian" +general.3134="Lisää palkintoja on tulossa pian!" +general.3135="Lisää palkintoja on tulossa pian!" +general.3136="+%%amount%% Hypixel-experienceä" +general.3137="Hytalen traileri" +general.3138="Tämänpäiväinen äänestyslinkki on" +general.3139="KLIKKAA LUNASTAAKSESI!" +general.3140="Klikkaa tätä linkkiä ja valitse sitten YES kun sinua pyydetään vierailemaan nettisivuillamme!" +general.3141="Salanimet sallivat sinun pelaavan eri käyttäjänimellä tunnistamisen välttämiseksi." +general.3142="Klikkaa tästä jatkaaksesi" +general.3143="Tutustu Hypixel Studiosin uuden itsenäisen pelin traileriin!" +general.3144="1. sija - %%player%%" +general.3145="2. sija - %%player%%" +general.3146="Party Games" +general.3147="Hinta: %%cost%%" +general.3148="Klikkaa tästä päästäksesi Hypixel Storeen: https://store.hypixel.net" +general.3149="Enkelin suosio" +general.3150="Tunnus" +general.3151="Tämä komento on juuri nyt poissa käytöstä!" +general.3152="ENSIVILKAISU" +general.3153="Kaikki säännöt pätevät yhä. Sinut voidaan edelleen ilmiantaa ja kaikki nimihistoria tallennetaan." +general.3154="➤ Ymmärrän, aseta salanimeni" +general.3155="Teleporttaa edelliselle tallennuspisteelle" +general.3156="Nollaa" +general.3157="Saavuit Tallennuspisteelle #%%checkpoint%% ajassa %%current%%." +general.3158="Klikkaa tätä linkkiä ja valitse sitten YES\nkun sinua pyydetään vierailemaan nettisivuillamme!" +general.3159="➤ Käytä nimeä '%%name%%' uudelleen" +general.3160="Klikkaa tästä käyttääksesi nimeä '%%name%%' uudelleen" +general.3161="➤ Käytä skiniä %%skin%% uudelleen" +general.3162="Klikkaa tästä käyttääksesi edellistä skiniäsi uudelleen" +general.3163="%%gametype%% Network Boosters eivät ole saatavilla." +general.3164="Sinulle ei ole yhtään %%gametype%% boosters!" +general.3165="Voit ostaa Network Boosters osoitteessa store.hypixel.net." +general.3166="Klikkaa saadaksesi lisätietoja!" +general.3167="Käyttämätön Booster" +general.3168="Tätä boosteria ei ole vielä käytetty." +general.3169="Klikkaa aktivoidaksesi!" +general.3170=" HYTALEN TRAILERI" +general.3171="Hypixel on työstänyt omaa itsenäistä peliään jo muutamia vuosia." +general.3172="Katso traileri Hytalen nettisivuilla!" +general.3173="Klikkaa vieraillaksesi nettisivuilla!\n(valmistaudu)" +general.3174=" KATSO TRAILERI" +general.3175="Tämä on erikoinen lobby, joka on auki vain rajoitettuina aikoina turnauksien aikana." +general.3176="Pysy valppaana turnausilmoitusten varalta! Kaikki voivat osallistua ja tienata Tribuutteja, joilla voi ostaa Hypixelin arvokkaimpia palkintoja!" +general.3177="Tuleva: %%mode%%" +general.3178="Päivämäärä: %%day%% %%month%%ta" +general.3179="Päivämäärä: %%start%%–%%end%% %%month%%ta" +general.3180="LIVE! %%mode%%" +general.3181="Kokeile sinäkin!" +general.3182="Viimeisin turnaus: %%mode%%" +general.3183="Tapahtui %%month%%ssa %%year%%" +general.3184="Lobby auki!" +general.3185="Lobby kiinni" +general.3186="Tournament Hall" +general.3187="Erikoistapahtumat" +general.3188="Klikkaa yhdistääksesi" +general.3189="KATSO TRAILERI" +general.3190="UUSI PELIMUOTO" +general.3191="UUSI PÄIVITYS" +general.3192="Kaikki tässä lobbyssa on juuri nyt" +general.3193="kehitysvaiheessa, ja ominaisuuksia saatetaan" +general.3194="poistaa koska tahansa." +general.3195="[WATCHDOG-ILMOITUS]" +general.3196="Watchdog on antanut porttikiellon %%ban_count%% pelaajalle viimeisten 7 päivän aikana." +general.3197="Lisäksi henkilökunta on antanut porttikiellon %%staff_ban_count%% pelaajalle viimeisen 7 päivän aikana." +general.3198="Kielletyt pelimodifikaatiot saattavat johtaa porttikieltoon!" +general.3199="Kerää hauskoja kosmeettisia esineitä!" +general.3200="Veri virtaa nuolista" +general.3201="osuttuasi niillä pelaajaan" +general.3202="Avataan Halloween Bundlessa!" +general.3203="Tämä tappoilmoitus kertoo" +general.3204="viimeistelyjesi määrän." +general.3205="Guildin kuvaus" +general.3206="Ei saatavilla palvelimia tässä pelimuodossa! Yritä kohta uudelleen!" +general.3207="Pyrypallo" +general.3208="Vihollisen tappaminen luo musikaalisen pyrypallon joka soittaa yhden kuudesta juhlasävelestä." +general.3209="Sammuta kaikki valot!" +general.3210="OIKEAKLIKKAA" +general.3211="3x KOLIKOT" +general.3212="Juuri nyt käytössä" +general.3213="Juuri nyt poissa käytöstä" +general.3214="Pidä ylläsi kaikkia neljää Fuusiopanssarin osaa" +general.3215="Kitin valinta (Oikeaklikkaa)" +general.3216="Parkourhaaste aloitettu!" +general.3217="Pelaajajäljitin (Oikeaklikkaa)" +general.3218="Tapahtui virhe, pyydämme sinua ottamaan yhteyttä ylläpitoon (%%server%%)" +general.3219="Kanava: %%channel%%" +general.3220="Klikkaa vaihtaaksesi tätä kanavaa!" +general.3221="Tätä housing-kanavaa ladataan vielä!" +general.3222="Valikon vierittäminen epäonnistui, päivitä valikko sen sijaan!" +general.3223="Sivu (%%current%%/%%total%%)" +general.3224="Klikkaa vierittääksesi!" +general.3225="Vieritä oikealle" +general.3226="Vieritä vasemmalle" +general.3227="Eniten vieraita" +general.3228="Sosiaalinen" +general.3229="Viikoittaiset keksit" +general.3230="Suositeltu" +general.3231="Vieraile uudelleen" +general.3232="Uudet talot" +general.3233="Ylläpito+YT" +general.3234="Roolipeli (RP)" +general.3235="Rakennus" +general.3236="Juttelu" +general.3237="Peli" +general.3238="Kilpailu" +general.3239="Tapahtuma" +general.3240="Oma kieli" +general.3241="Tunniste \"%%tag%%\"" +general.3242="Näytä talot, joihin omistaja on asettanut tunnisteen \"%%tag%%\"." +general.3243="Näytä talot paikalla olevien vierailijoiden määrän mukaan" +general.3244="Näytä partysi jäsenten, kavereidesi sekä guild-tovereidesi talot" +general.3245="Näytä kavereidesi talot" +general.3246="Näytä guildisi jäsenten talot" +general.3247="Näytä kuluneen viikon aikana eniten keksejä saaneet talot" +general.3248="Näytä viimeksi vierailtujen talojen kaltaisia taloja" +general.3249="Näytä äskettäin vieraillut talot" +general.3250="Näytä äskettäin Player Housingiin liittyneiden pelaajien uudet talot" +general.3251="Näytä henkilökunnan ja youtubettajien talot" +general.3252="Näytä MVP++-pelaajien omistamia taloja\n\nOsta MVP++ osoitteessa store.hypixel.net!" +general.3253="Näytä satunnainen valikoima taloja" +general.3254="Näytä talot, joiden omistaja käyttää samaa kieltä kuin sinä.\n\nValitse kielesi \"Profiilini\"-valikosta missä tahansa lobbyssa." +general.3255="Näytä talot, joiden omistajat puhuvat kieltä %%lang%%" +general.3256="Tapahtui virhe kommunikoitaessa housing-backendin kanssa!" +general.3257="Kieli: %%lang%%" +general.3258="Ei taloja!" +general.3259="Ei löydetty taloja tällä kanavalla :(" +general.3260="Jokaisella Hypixel-pelaajalla on talo, jonka he voivat rakentaa vastaamaan omia unelmiaan." +general.3261="Nollaa KAIKKI kanavat" +general.3262="Tämä nollaa kaikki valitsemasi housing-kanavat niiden oletusarvoihin!" +general.3263="Klikkaa nollataksesi!" +general.3264="Kanavan valinta" +general.3265="Lisää kielikanavia..." +general.3266="Hypixelissä on kanavat jokaiselle kielelle." +general.3267="Klikkaa tarkastellaksesi niitä!" +general.3268="Klikkaa käyttääksesi tätä kanavaa!" +general.3269="Kielikohtaiset kanavat" +general.3270="Kieli: %%lang%%" +general.3271="Nollaa housing-kanavien valinta!" +general.3272="Tämä on oletuskanava!" +general.3273="Pysy ajan tasalla Hypixelin uutisista + saa ilmainen %%reward%% seuraamalla meitä!" +general.3274="Klikkaa seurataksesi:" +general.3275="Voit lunastaa nämä palkinnot koska tahansa Lähettimieheltä" +general.3276="Olet jo lunastanut tämän palkinnon!" +general.3277="Klikkaa lunastaaksesi palkinnon!" +general.3278="Pit" +general.3279="Tiimin ylpeys" +general.3280="Kukka" +general.3281="Verinen" +general.3282="Kakka" +general.3283="DJ" +general.3284="Tulinen tuuli" +general.3285="Väriliitu" +general.3286="Et ole avannut tätä saavutusta vielä!" +general.3287="Daredevil" +general.3288="Näytä maailmalle mitä kuuluu ja kuka käskee ratsastamalla tällä roihuavalla luuttomalla ratsulla." +general.3289="Tämän valitseminen asettaa asetuksen %%category%% oletukseksi." +general.3290="Häkki" +general.3291="Temple" +general.3292="Noidan mökki" +general.3293="Purjevene" +general.3294="Sieni" +general.3295="UFO" +general.3296="Juustohampurilainen" +general.3297="Häkit" +general.3298="Rantapallo" +general.3299="Mehiläinen" +general.3300="Sillanrakentaja" +general.3301="Timanttinen Steve" +general.3302="Paukkuserpentiini" +general.3303="Endermite" +general.3304="Konfetti" +general.3305="Sokeritoukka" +general.3306="Vaatii: %%rank%%" +general.3307="Kartan palautekysely" +general.3308="Klikkaa tästä vastataksesi \"" +general.3309="\"." +general.3310="Voit tehdä tämän vain lobbyissa!" +general.3311="Tarjous antaa palautetta kartasta on vanhentunut." +general.3312="Virhe: Tuntematon pelimuoto %%gameType%%!" +general.3313="Pelasit äskettäin kartassa %%mapname%%, ja haluaisimme kuulla mielipiteesi siitä." +general.3314="[Anna palautetta]" +general.3315="Kiitos palautteestasi!" +general.3316="Oliko kartassa helppo suunnistaa?" +general.3317="Mitä mieltä olit kartan koosta?" +general.3318="Kuinka arvostelisit tämän kartan pelinopeuden?" +general.3319="Mitä mieltä olit kartan ulkonäöstä?" +general.3320="Minkä arvosanan antaisit kartalle yleisesti?" +general.3321="Miten arvioisit kartan aloitustasapainoa?" +general.3322="Olivatko smaragdigeneraattorit helppoja löytää?" +general.3323="Olivatko smaragdigeneraattorit helppoja saavuttaa?" +general.3324="Olivatko timanttisaaret mielestäsi sijoiteltu tasapuolisesti?" +general.3325="Miten arvioisit tämän kartan tasapainoa yleisesti?" +general.3326="Kuinka kaukana keskisaari oli aloitussaareltasi?" +general.3327="Oliko aloitussaarellasi helppo suunnistaa?" +general.3328="Oliko keskisaarella helppo suunnistaa?" +general.3329="Olivatko kartan ainutlaatuiset elementit hauskoja?" +general.3330="Oliko kartassa tarpeeksi piilopaikkoja?" +general.3331="Olitko tyytyväinen siihen, kuinka paljon kultaa löysit tästä kartasta?" +general.3332="Erittäin suuri" +general.3333="Jokseenkin iso" +general.3334="Juuri sopiva" +general.3335="Jokseenkin pieni" +general.3336="Hyvin pieni" +general.3337="Erittäin nopea" +general.3338="Jokseenkin nopea" +general.3339="Jokseenkin hidas" +general.3340="Erittäin hidas" +general.3341="Erinomainen" +general.3342="Hyvä" +general.3343="Huono" +general.3344="Erittäin huono" +general.3345="Hyökkäyspainotteinen" +general.3346="Tasapainotettu" +general.3347="Puolustuspainotteinen" +general.3348="Liian yksinkertainen" +general.3349="Liian sekava" +general.3350="Epätasapainoinen" +general.3351="Erittäin epätasapainoinen" +general.3352="Liian kaukana" +general.3353="Liian lähellä" +general.3354="Erittäin hauska" +general.3355="Hauska" +general.3356="Keskiverto" +general.3357="Ei niin hauskoja" +general.3358="Ei yhtään hauskoja" +general.3359="Liian monta" +general.3360="Ei tarpeeksi" +general.3361="Liian paljon" +general.3362="PÄÄSIÄISERIKOINEN!" +general.3363="Vastasit jo tähän kysymykseen." +general.3364="Avataan Battle Passissa: %%season%%!" +general.3365="Suodatetut kosmeettiset esineet" +general.3366="Muut kosmeettiset esineet" +general.3367="(%%number%%)" +general.3368="Muut kosmeettiset esineet" +general.3369="Esineet ovat myynnissä!" +general.3370="Tapahtuma on KÄYNNISSÄ!" +general.3371="Esineet eivät ole myynnissä" +general.3372="Esineet aina myynnissä!" +general.3373="Jotkin erikoisesineet voi avata vain erityisillä tavoilla. Tutustu niihin täällä!" +general.3374="Klikkaa tarkastellaksesi kosmeettisia esineitä!" +general.3375="Valittuna nyt: %%option%%" +general.3376="Klikkaa ottaaksesi käyttöön!" +general.3377="Klikkaa poistaaksesi käytöstä!" +general.3378="Yksityisten pelien asetukset" +general.3379="Sinun täytyy odottaa 5s käyttöjen välillä!" +general.3380="Otit hohto-ominaisuuden käyttöösi! (Näkyy pelaajille, joilla on käytössään versio 1.9 tai uudempi)" +general.3381="Otit hehkun pois käytöstä!" +general.3382="Antaa pelihahmollesi rankkisi värin mukaiset ääriviivat." +general.3383="Huomio: Hohto-ominaisuus näkyy vain pelaajille, jotka pelaavat Minecraftin versiolla 1.9 tai uudemmalla!" +general.3384="Klikkaa poistaaksesi käytöstä!" +general.3385="Klikkaa ottaaksesi käyttöön!" +general.3386="Avataan minkä tahansa kauden Battle Passissa!" +general.3387="Hehku" +general.3388="Sinun tulee avata saavutus '%%achievement%%' käyttääksesi tätä kosmeettista esinettä!" +general.3389="Tehostelista" +general.3390="Tämä tehtävä avataan ostaessasi Battle Passin!" +general.3391="Olet jo löytänyt tämän lohikäärmeen munan!" +general.3392="Olet löytänyt salaisen lohikäärmeen munan!" +general.3393="Klikkaa hypätäksesi alkuun." +general.3394="Suorita tehtäviä ansaitaksesi experienceä Battle Passiin!" +general.3395="Tehtävät ovat tällä hetkellä poistettu käytöstä!" +general.3396="Kehitä Battle Passiasi pelaamalla pelejä ja suorittamalla tehtäviä." +general.3397="Ansaitse yli 100 palkintoa pelaamalla ja suorittamalla tehtäviä." +general.3398="Voit ostaa Battle Passin milloin tahansa kauden aikana!" +general.3399="Mikä on Battle Pass?" +general.3400="Tehtävät" +general.3401="Klikkaa hypätäksesi loppuun." +general.3402="Alkaa %%time%%!" +general.3403="Viikon %%week%% tehtävät" +general.3404="Avautuu %%time%%!" +general.3405="Suoritettu:" +general.3406="Ilmainen viikoittainen tehtävä" +general.3407="Ilmainen päivittäinen tehtävä" +general.3408="Ilmainen tehtävä" +general.3409="Viikoittainen tehtävä" +general.3410="Päivittäinen tehtävä" +general.3411="Tehtävä" +general.3412="Suoritettu" +general.3413="Suoritetut päivittäiset tehtävät poistetaan automaattisesti seuraavana päivänä." +general.3414="Avataan ostamalla Battle Pass!" +general.3415="+%%amount%% Battle Pass EXP" +general.3416="Klikkaa korvataksesi!" +general.3417="Olet jo korvannut päivittäisen tehtävän tänään!" +general.3418="Kausi 1" +general.3419="Kausi 2" +general.3420="Kausi 3" +general.3421="Kausi 4" +general.3422="Taso" +general.3423="Battle Pass -tavaraluettelo" +general.3424="Jotkin ansaitut palkinnot sijoitetaan Battle Pass -tavaraluetteloon." +general.3425="Näitä palkintoja voi lunastaa koska tahansa." +general.3426="Klikkaa näyttääksesi tehtävät!" +general.3427="Päivittäiset tehtävät" +general.3428="Tavaraluettelo" +general.3429="ANSAITTU!" +general.3430="Ilmainen Battle Pass" +general.3431="Maksullinen Battle Pass" +general.3432="Taso: %%tier%%" +general.3433="Korkein taso saavutettu" +general.3434="EXP: %%exp%%/%%max%%" +general.3435="%%boost%%% Henkilökohtainen EXP Boost" +general.3436="%%boost%%% Partyn EXP Boost" +general.3437="Päättyy %%time%%!" +general.3438="Battle Pass -taso %%start%% - %%end%%" +general.3439="Lupaus täytetty" +general.3440="[Coop tai sinä] Avaa viimeinen Talismaanipussipäivitys" +general.3441="Muuttaa partikkelien laatua." +general.3442="Auto-Tip" +general.3443="Tarjoa palautekyselyjä kartoista" +general.3444="Aseta karttojen palautekyselyt käyttöön tai pois käytöstä" +general.3445="%%percent%% pelin %%game%% pelaajista on avannut tämän!" +general.3446="Näitä palkintoja voi lunastaa koska tahansa tapahtumakauden aikana." +general.3447="LUNASTAMATTOMIA PALKINTOJA!" +general.3448="Maksullinen Battle Pass" +general.3449="Vaatii maksullisen Battle Passin!" +general.3450="Sinut potkittin guildista syystä: '%%reason%%'" +general.3451="%%player%% poisti sinut guildista. Syy: '%%reason%%'." +general.3452="1v1-vastustajaa etsimässä" +general.3453="Tiimiä etsimässä" +general.3454="Juttuseuraa etsimässä" +general.3455="Chillailemassa" +general.3456="Guildia etsimässä" +general.3457="Älä häiritse" +general.3458="AFK" +general.3459="Voittoja keräilemässä" +general.3460="Tappoja keräilemässä" +general.3461="Suoritetut tehtävät" +general.3462="Ensimmäisen kerran liittynyt" +general.3463="Kauden 1 taso" +general.3464="Bed Wars - Taso" +general.3465="Bed Wars - Viimeistelyt" +general.3466="Bed Wars - Tyhjyystapot" +general.3467="Bed Wars - Sänkyjä rikottu" +general.3468="Bed Wars - Voittoputki" +general.3469="Bed Wars - Tapot" +general.3470="Bed Wars - Voitot" +general.3471="Bed Wars - Kolikot" +general.3472="SkyWars - Taso" +general.3473="SkyWars - Palikoita asetettu" +general.3474="SkyWars - Palikoita rikottu" +general.3475="SkyWars - Nuoliosumat" +general.3476="SkyWars - Nuolia ammuttu" +general.3477="SkyWars - Lähitaistelutapot" +general.3478="SkyWars - Munia heitetty" +general.3479="SkyWars - Helmiä heitetty" +general.3480="SkyWars - Olentotapot" +general.3481="SkyWars - Poletit" +general.3482="SkyWars - Tapot" +general.3483="SkyWars - Voitot" +general.3484="SkyWars - Kolikot" +general.3485="Blitz - Tapot" +general.3486="Blitz - Voitot" +general.3487="Blitz - Kolikot" +general.3488="Duels - Paras voittoputki" +general.3489="Duels - Nuoliosumat" +general.3490="Duels - Nuolia ammuttu" +general.3491="Duels - Lähitaisteluosumat" +general.3492="Duels - Lähitaisteluhyökkäykset" +general.3493="Duels - Voitot" +general.3494="Duels - Tapot" +general.3495="Duels - Kolikot" +general.3496="Build Battle - Pisteet" +general.3497="Build Battle - Voitot" +general.3498="Build Battle - Kolikot" +general.3499="Murder Mystery - Kultaa kerätty" +general.3500="Murder Mystery - Puukkotapot" +general.3501="Murder Mystery - Tapot" +general.3502="Murder Mystery - Voitot" +general.3503="Murder Mystery - Kolikot" +general.3504="UHC - Päitä syöty" +general.3505="UHC - Pisteet" +general.3506="UHC - Tapot" +general.3507="UHC - Voitot" +general.3508="UHC - Kolikot" +general.3509="Smash Heroes - Taso" +general.3510="Smash Heroes - Tapot" +general.3511="Smash Heroes - Voitot" +general.3512="Smash Heroes - Kolikot" +general.3513="Football - Voitot" +general.3514="Hole in the Wall - Voitot" +general.3515="Bounty Hunters - Voitot" +general.3516="Pixel Painters - Voitot" +general.3517="Dragon Wars - Voitot" +general.3518="Ender Spleef - Voitot" +general.3519="Galaxy Wars - Voitot" +general.3520="Throw Out - Voitot" +general.3521="Farm Hunt - Voitot" +general.3522="Party Games - Voitot" +general.3523="Hide and Seek - Voitot" +general.3524="Hypixel Says - Voitot" +general.3525="Mini Walls - Voitot" +general.3526="Blocking Dead - Voitot" +general.3527="Zombies - Tapot" +general.3528="TNT Games - Voitot" +general.3529="TNT Games - Kolikot" +general.3530="Wizards - Voitot" +general.3531="Speed UHC - Voitot" +general.3532="Speed UHC - Tapot" +general.3533="Speed UHC - Kolikot" +general.3534="Mega Walls - Voitot" +general.3535="Mega Walls - Tapot" +general.3536="Mega Walls - Viimeistelyt" +general.3537="Mega Walls - Kolikot" +general.3538="Cops and Crims - Pommeja viritetty" +general.3539="Cops and Crims - Pommeja purettu" +general.3540="Cops and Crims - Laukauksia ammuttu" +general.3541="Cops and Crims - Pääosumatapot" +general.3542="Cops and Crims - Voitot" +general.3543="Cops and Crims - Tapot" +general.3544="Cops and Crims - Kolikot" +general.3545="Warlords - Voitot" +general.3546="Warlords - Tapot" +general.3547="Warlords - Kolikot" +general.3548="Quakecraft - Laukauksia ammuttu" +general.3549="Quakecraft - Voitot" +general.3550="Quakecraft - Tapot" +general.3551="Quakecraft - Kolikot" +general.3552="The Walls - Voitot" +general.3553="The Walls - Tapot" +general.3554="The Walls - Kolikot" +general.3555="Paintball - Laukauksia ammuttu" +general.3556="Paintball - Voitot" +general.3557="Paintball - Tapot" +general.3558="Paintball - Kolikot" +general.3559="VampireZ - Voitot" +general.3560="VampireZ - Tapot ihmisistä" +general.3561="VampireZ - Tapot vampyyreista" +general.3562="VampireZ - Kolikot" +general.3563="Arena Brawl - Voitot" +general.3564="Arena Brawl - Tapot" +general.3565="Arena Brawl - Kolikot" +general.3566="Turbo Kart Racers - Voitot" +general.3567="Turbo Kart Racers - Kolikot" +general.3568="Nollaa status" +general.3569="Statuksesi on nollattu." +general.3570="Vaihda näkyvyys itselläsi" +general.3571="Statuksesi saattaa näkyä itsellesi hieman jäljessä viiveen vuoksi. Muille pelaajille se kuitenkin näkyy aivan normaalisti." +general.3572="Tämä ominaisuus on juuri nyt poissa käytöstä!" +general.3573="%%game%% -statukset" +general.3574="Yleiset statukset" +general.3575="Yleiset tilastostatukset" +general.3576="Esikatselu:" +general.3577="Valittu!" +general.3578="Aseta statukseksesi %%status%%" +general.3579="Avataan kauden %%season%% Battle Passissa" +general.3580="Sinulla ei ole yhtään Network Boosteria saatavilla! Voit ostaa niitä osoitteessa http://store.hypixel.net/" +general.3581="\n%%purchaser%% aktivoi +%%multiplier%%X kolikot tähän peliin! Ansaitse XP ja kolikoita " +general.3582="\n%%purchaser%% ja yksi toinen pelaaja aktivoivat +%%multiplier%%X kolikot tähän peliin! Ansaitse XP ja kolikoita " +general.3583="\n%%purchaser%% ja %%count%% muuta aktivoivat +%%multiplier%%X kolikot tähän peliin! Ansaitse XP ja kolikoita " +general.3584="KLIKKAA" +general.3585="%%prefix%%Pelaaja poistettiin pelistäsi sääntöjen palvelimen sääntöjen rikkomisen vuoksi. Kiitos ilmoituksesta!" +general.3586="Halloween-opas" +general.3587="Halloween" +general.3588="Joulu" +general.3589="Pääsiäinen" +general.3590="Klikkaa tästä liittyäksesi %%game%% -peliin!" +general.3591="KLIKKAA TÄSTÄ" +general.3592="Innostu ja saa kaikki muutkin innostumaan! Se on niin lähellä! (vai niin kaukana?)" +general.3593="Vuoteen %%year%%" +general.3594="%%magic%%; %%minutes%% minuuttia %%magic%%;" +general.3595="%%magic%%; %%hours%% tuntia %%magic%%;" +general.3596="%%magic%%; %%days%% päivää %%magic%%;" +general.3597="Joulukalenteripalkinto" +general.3598="Ensimmäisen päivän voi lunastaa milloin vain!" +general.3599="Palkinto lunastettu!" +general.3600="Hups! Palkinto ohitettu!" +general.3601="Palkinto on yhä arvoitus!" +general.3602="Lunastit joulukuun %%day_ordinal%% päivän Adventtikalenterin palkinnon!" +general.3603="Hyvää joulua ja onnellista uutta vuotta!" +general.3604="Voit lunastaa vain tämän päivän palkinnon!" +general.3605="Jouluinen" +general.3606="Siivekäs" +general.3607="Lumipallosade" +general.3608="Kierre" +general.3609="Hautakivi" +general.3610="Bubbling Cauldron" +general.3611="Taikajuomapullo" +general.3612="Yllätyslumipallo" +general.3613="Nuku hyvin" +general.3614="Snowball Spammer" +general.3615="Snowman Rampage" +general.3616="Hirveä lumimies" +general.3617="On pelon ja kauhun aika! Tämä voitontanssi vapauttaa tappamiesi pelaajien kurjat sielut juhlimaan voittoasi." +general.3618="Lahjaräjähdys" +general.3619="Saa vihollisesi purkautumaan lahjapaketiksi!" +general.3620="Joulukuusi" +general.3621="Joulukuusi ilmestyy maahan tappaessasi vihollisen." +general.3622="Nuotio" +general.3623="Kummitus" +general.3624="Piparkakku-ukko" +general.3625="Grinch" +general.3626="Pelle" +general.3627="Reki" +general.3628="Luuranko näyttää peukkua" +general.3629="Robin" +general.3630="Pingviini" +general.3631="Hautakivi" +general.3632="Maissikarkki" +general.3633="Karkkikori" +general.3634="Soittokello" +general.3635="Sukka" +general.3636="Poro" +general.3637="Herra Lahjaukko" +general.3638="Terveellinen herkku" +general.3639="Laita makeat sivuun ja nauti sen sijaan näistä punaisista, säihkyvistä ja terveellisistä herkuista!" +general.3640="Petterin nenä" +general.3641="Miten edes sait tämän?" +general.3642="Erityinen Petterin nenä -puukko" +general.3643="ERITYISET JOULUTEHTÄVÄT" +general.3644="ERITYISET JOULUTEHTÄVÄT" +general.3645="ERITYISET JOULUTEHTÄVÄT" +general.3646="ILMAISIA PALKINTOJA!!" +general.3647="ILMAISIA PALKINTOJA!!" +general.3648="ILMAISIA PALKINTOJA!!" +general.3649="Erityinen Karkkitankohattu" +general.3650="Erityinen Joulupukin puku" +general.3651="Adventtikalenteripalkinto" +general.3652="Anna %s lahjaa Bed Warsissa" +general.3653="PÄIVITYS 0.7.5!" +general.3654="Present" +general.3655="Avataan Holiday Bundlessa!" +general.3656="Kiinalainen uusivuosi" +general.3657="Vipeltävät jalat" +general.3658="Lohikäärmeen karjaisu" +general.3659="Säihke" +general.3660="Hiiri" +general.3661="Kuu" +general.3662="Kotkot-pino" +general.3663="Tähtitaivas" +general.3664="Juustoinen" +general.3665="Lyhty" +general.3666="Rotta-asu" +general.3667="Rotat 2020" +general.3668="Avaa kauppavalikko" +general.3669="Klikkaa tästä avataksesi SkyWars-kaupan" +general.3670="◼ Erikoistehtävä" +general.3671="◼ Teemakartat" +general.3672="Haluatko nähdä sen? " +general.3673="[KYLLÄ]" +general.3674="Sataa possuja" +general.3675="Taivaalta sataa sikoja." +general.3676="Koiranpentujuhla" +general.3677="Luo susilauma." +general.3678="Leijuvat lyhdyt" +general.3679="Leijuvat lyhdyt valaisevat yötaivasta." +general.3680="Kiinalainen lohikäärme" +general.3681="Luo kiinalainen lohikäärme." +general.3682="Kaksoislohikäärme" +general.3683="Juusto" +general.3684="Rotta" +general.3685="Luna" +general.3686="Ulina" +general.3687="Henki" +general.3688="Vihollisen eläinsielu vapautuu tappaessasi hänet." +general.3689="Tulihenkäys" +general.3690="Syökset tulta tappaessasi vihollisen." +general.3691="Kunnioitettava" +general.3692="Possun rauha" +general.3693="Kauniita unia" +general.3694="Pahissika" +general.3695="Sian vuosi" +general.3696="Maapallopossu" +general.3697="Viisauden koirat" +general.3698="Koiran vuosi" +general.3699="Rauhallinen" +general.3700="%%prefix%% Vaatii tapahtumakauden %%event%% tehtävän suorittamisen!" +general.3701="Olet jo suorittanut tämän tehtävän tällä kaudella!" +general.3702="Olet lunastanut tämän palkinnon, mutta sinulla on %%amount%% palkintomerkki!\n\nVoit käyttää merkkejä lunastaaksesi palkinnon nyt, tai voit palata takaisin %%time%% kuluttua!" +general.3703="Olet lunastanut tämän palkinnon, mutta sinulla on %%amount%% palkintomerkkiä!\n\nVoit käyttää merkkejä lunastaaksesi palkinnon nyt, tai voit palata takaisin %%time%% kuluttua!" +general.3704="Parvi" +general.3705="Sataa munia" +general.3706="Kuoriutuvat munat" +general.3707="Pupun GG" +general.3708="Pääsiäiskori" +general.3709="Munajahti" +general.3710="Munayllätys" +general.3711="Kultainen muna" +general.3712="Kaniasu" +general.3713="Väärät munat" +general.3714="Vikinä" +general.3715="Pupupuku" +general.3716="Pupu puvussa" +general.3717="Munaisa" +general.3718="Bzzz" +general.3719="Pupumies" +general.3720="Leveä hymy" +general.3721="Tipu" +general.3722="Juhlat" +general.3723="Hyvin menee" +general.3724="Munaräjähdys" +general.3725="Ladybug" +general.3726="Piikikäs" +general.3727="Maalattu muna" +general.3728="Creeperin muna" +general.3729="Easter Simulator" +general.3730="∙ Easter Simulator" +general.3731="VIHJE" +general.3732="Olet jo avannut kaiken!" +general.3733="Näytämme nyt sinulle muutamia pelejä, joiden uskomme olevan hyviä aloittelijoille! Tämä avaa kaikki pelimme ja ominaisuutemme, ja niitä onkin paljon. Tämä tapahtuu pian automaattisesti, kun uskomme sinun olevan valmis, tai voit tehdä sen heti itse." +general.3734="Avaa kaikki" +general.3735="Avasit kaikki pelit onnistuneesti!" +general.3736="Lobbyn asetukset" +general.3737="Lobbyn asetukset" +general.3738="Ylläpidon/YouTubettajan asetukset" +general.3739="Ylläpidon/YouTubettajien asetukset" +general.3740="Nykyinen: %%option%%" +general.3741="Tämä generoi sinulle satunnaisen nimen." +general.3742="Tämä antaa sinun syöttää mukautetun nimen." +general.3743="Edellinen nimi: %%name%%" +general.3744="Vaihda salanimeäsi." +general.3745="Klikkaa vaihtaaksesi!" +general.3746="Salanimi" +general.3747="Vaihda naamioitumisesi aikana näkyvää rankkiasi." +general.3748="Salarank" +general.3749="Tämä käyttää tavallista skiniäsi." +general.3750="Tämä valitsee sinulle Steve- tai Alex-skinin." +general.3751="Tämä valitsee sinulle satunnaisen skinin." +general.3752="Tämä käyttää edellisen salanimesi hahmoa." +general.3753="Vaihda naamioitumisesi aikana näkyvää hahmoasi." +general.3754="Salahahmo" +general.3755="TOP" +general.3756="INFO" +general.3757="Tarkastele Hypixel Storea pelin sisältä!" +general.3758="Hypixel Gold: %%amount%%" +general.3759="Osta %s esinettä Bed Warsissa" +general.3760="%%player%% löi kaukaa ylläpitäjän %%staff%% korkealle taivaisiin!" +general.3761="Haluatko saada ilmoituksia, kun sinut mainitaan chatissa? Vaihda tilaa tästä." +general.3762="SALANIMI (vain peleissä)" +general.3763="Yksityisen pelin asetukset(Oikeaklikkaa)" +general.3764="Pelikohtainen" +general.3765="Kaikki lehmät" +general.3766="Niin ihania lehmiä." +general.3767="Elinvoimatehostus" +general.3768="Paranna kaikkien pelaajien terveyttä" +general.3769="Tavallinen elinvoima" +general.3770="Kaksinkertainen elinvoima" +general.3771="Kolminkertainen elinvoima" +general.3772="Vähäinen painovoima" +general.3773="Varaudu vähäiseen painovoimaan... joka auttaa loikkaamaan pitkälle." +general.3774="Yksi osuma, yksi tappo" +general.3775="Valitse esineet, joilla tappaa vihollisen välittömästi." +general.3776="Ei nopeutta" +general.3777="Nopeus I" +general.3778="Nopeus II" +general.3779="Nopeus III" +general.3780="LUOKKA" +general.3781="HUOMIO: Saadaksesi parhaan kokemuksen tästä kielestä suosittelemme asettamaan kieliasetuksen Pakota unicode-fontti päälle." +general.3782="Kuupöly" +general.3783="Kummitukset" +general.3784="Veggy SpringLazor™" +general.3785="Kauhu kalvakoon vihollistesi sydämiä Hirveän lumimiehen liittyessä puolellesi!" +general.3786="Sataa pääsiäismunia" +general.3787="Sataa pääsiäismunia!" +general.3788="Kuoriutuvia munia sataa taivaalta!" +general.3789="Valevampyyri" +general.3790="GG WPumpkin" +general.3791="Täydellinen miekanheitto" +general.3792="Öinen ajojahti" +general.3793="Luuranko sanoo Hei" +general.3794="Kynttilät" +general.3795="Lohikäärmeenpää" +general.3796="Kaninkorvat" +general.3797="Tulppaanit" +general.3798="Wither" +general.3799="Kiinalainen raketti" +general.3800="Maapallo" +general.3801="Klikkaa avataksesi!" +general.3802="Kana-apokalypsi" +general.3803="Tonneittain kanoja, paljon munia, tämä on maailmanloppu - paitsi jos tykkäät kanasta." +general.3804="Lumimyrsky" +general.3805="Et voi tehdä tuota kun olet valikossa!" +general.3806="Lumimyrsky" +general.3807="Ei saatavilla tällä hetkellä!" +general.3808="Joulukuusi" +general.3809="Varovainen joulupukki" +general.3810="Lumisota" +general.3811="Karkkikuningas" +general.3812="Hirviöjuhla" +general.3813="%%count%% pelaajaa yhteensä" +general.3814="➤ %%name%% -peli alkaa 15 sekunnin kuluttua! %%click%% liittyäksesi!" +general.3815="Avautuu tasolla %%level%%" +general.3816="Kala" +general.3817="Aarre" +general.3818="Romu" +general.3819="Hiljattain tekemäsi ilmoitus on tarkistettu ja käsitelty. Kiitos! :)" +general.3820="Kiitos ilmoituksesta, tämä auttaa parantamaan järjestelmämme ja yhteisöämme! :)" +general.3821="Kiitos ilmoituksesta, tämä auttaa parantamaan järjestelmäämme ja yhteisöämme!" +general.3822="Kurpitsaräjähdys" +general.3823="Pirstoutunut" +general.3824="HUUrjaa" +general.3825="Löytyipäs" +general.3826="Valkosipuli" +general.3827="Valvoja" +general.3828="Witch Please" +general.3829="Kurpitsalyhty" +general.3830="Karkki" +general.3831="%%player%% on jo kutsuttu Dueliin! Odota, että hän hyväksyy kutsun!" +general.3832="Klikkaa kutsuaksesi pelaaja %%player%% peliin %%name%%!" +general.3833="Frankenstein" +general.3834="Vihollinen" +general.3835="Tasapainotus" +general.3836="Kirves" +general.3837="Sivallus" +general.3838="Hakku" +general.3839="Aseet" +general.3840="Neliö" +general.3841="Ympyrä" +general.3842="Vieraile verkkosivuillamme valitaksesi yhden kolmesta Palkintokortista, joista voit saada kolikoita, dustia, experienceä, kosmeettisia esineitä + paljon muuta!" +general.3843="Pelisi on tehostettu %%purchaser%% ansiosta.\n+%%amount%%X kolikot Network Booster! Ansaitse kokemusta ja kolikoita" +general.3844="\nPeliäsi boostattiin pelaajan %%purchaser%% ja yhden muun +%%amount%%X kolikoiden Network Boosterilla! Ansaitse XP ja kolikoita" +general.3845="\nPeliäsi boostattiin pelaajan %%purchaser%% ja %%count%% muun +%%amount%%X kolikoiden Network Boosterilla! Ansaitse XP ja kolikoita" +general.3846="Harvinaisuus" +general.3847="Seuraava järjestys: %%next%%" +general.3848="Vasenklikkaa pyörittääksesi!" +general.3849="Järjestys: %%option%%" +general.3850="Järjestys: %%method%%" +general.3851="Löydät hatut Keräilyesinevalikosta työkalupalkistasi." +general.3852="Löydät vempaimet Keräilyesinevalikosta työkalupalkistasi." +general.3853="Yhteensä" +general.3854="lahja" +general.3855="lahjaa" +general.3856="Lumihiutale" +general.3857="Fireplace" +general.3858="Vihainen kalkkuna" +general.3859="Yllätyspentu" +general.3860="Joulupukki liukastuu" +general.3861="Hämähäkkilumipallo" +general.3862="Hopealanka" +general.3863="Lumituisku" +general.3864="Paketoitu" +general.3865="Juhlinta" +general.3866="Mistelinoksa" +general.3867="Snowglobe" +general.3868="Maat" +general.3869="Hyvää uutta vuotta!" +general.3870="Hyvää uutta vuotta!" +general.3871="Kaupungit" +general.3872="2019 Adventtikalenteri" +general.3873="2020 Adventtikalenteri" +general.3874="%%year%% Adventtikalenteri: %%amount%%" +general.3875="%%year%% Adventtikalenteri: %%amount%%" +general.3876="Saatavilla rankille %%rank%%:" +general.3877="Saatavilla Rank Giftingistä:" +general.3878="%%player%% kelkkaili lobbyyn!" +general.3879="%%seconds%% sekuntia kunnes on vuosi %%year%% kaupungissa" +general.3880="Avataan lunastamalla %%count%% Ranks Gifted -palkinto!" +general.3881="%%puncher%% löi pelaajan %%punched%% korkealle taivaisiin!" +general.3882="%%puncher%% löi ystävänsä, pelaajan %%punched%% korkealle taivaisiin!" +general.3883="Tämä avataan Rank Gifting -palkinnoissa!" +general.3884="Lyöntiviesti" +general.3885="Valitse viesti %%name%% näytettäväksi, kun lyöt ylläpitäjää tai ystävää." +general.3886="Oikeaklikkaa esikatsellaksesi!" +general.3887="Sinulla ei ole oikeuksia lobbylyönteihin!" +general.3888="Esikatselu: " +general.3889="Klikkaa tästä palataksesi Lyöntiviestivalikkoon!" +general.3890="Lyöntiviestiksesi asetettiin %%message%%" +general.3891="Muokkaa viestiä, joka näytetään kun käytät lyöntikykyäsi!" +general.3892="Lobbylyönnit ovat käytössä vain MVP+-pelaajille ja niille, joilla on Lyö ystäviä -esine Tournament Hallista." +general.3893="Lyöntiviestit" +general.3894="Lyöntiviestit" +general.3895="Valittuna nyt: %%message%%" +general.3896="EI MITÄÄN" +general.3897="Nollaa lyöntiviesti" +general.3898="Lyöntiviestisi on nollattu." +general.3899="Pelaajat voivat myös avata mahdollisuuden lyödä ystäviään lobbyissa Tournament Hallista saatavana palkintona aina aktiivisten turnausten aikaan." +general.3900="Pelaajien lyöminen" +general.3901="Tämä asetus on lukittu rankillasi!" +general.3902="Tämä asetus on lukittu!" +general.3903="Vaatii %%count%% Ranks Gifted -palkinnon!" +general.3904="Muokkaa ulkonäköä" +general.3905="Muokkaa ulkonäköä" +general.3906="%%puncher%% löi rakkaudella pelaajan %%punched%% korkealle taivaisiin!" +general.3907="%%puncher%% löi rakkaudella ystävänsä, pelaajan %%punched%% korkealle taivaisiin!" +general.3908="Vaatii MVP+-rankin tai Lyö ystäviä -esineen Tournament Hallista. Löydät Lyöntiviestit profiilistasi." +general.3909="Avataan vuoden %%year%% Adventtikalenterista" +general.3910="%%prefix%%%%color%%%%from%%%%color%% antoi %%days%% päivää rankkia MVP++ %%color%%lahjaksi pelaajalle %%target%%%%color%%!%%suffix%%" +general.3911="%%prefix%%%%color%%%%from%%%%color%% antoi rankin %%rank%%%%color%% lahjaksi pelaajalle %%target%%%%color%%!%%suffix%%" +general.3912="%%color%%Hän on antanut tähän mennessä %%gifted%%%%color%% rankkia!" +general.3913="." +general.3914="." +general.3915="." +general.3916="." +general.3917="Toisen päivän voi lunastaa milloin vain!" +general.3918="%%puncher%% tökkäsi pelaajan %%punched%% korkealle taivaisiin!" +general.3919="%%puncher%% tökkäsi ystävänsä, pelaajan %%punched%% korkealle taivaisiin!" +general.3920="%%puncher%% iski upeasti pelaajan %%punched%% korkealle taivaisiin!" +general.3921="%%puncher%% iski upeasti ystävänsä, pelaajan %%punched%% korkealle taivaisiin!" +general.3922="Rakkauslyöntiviesti" +general.3923="Tökkäyslyöntiviesti" +general.3924="Lumipallolyöntiviesti" +general.3925="Upea lyöntiviesti" +general.3926="Tuntematon ystävä" +general.3927="Ei tänään! ... eikä huomennakaan." +general.3928="Ai hei siellä." +general.3929="Kaikki kerätään!" +general.3930="%%puncher%% heitti lumipallolla pelaajan %%punched%% korkealle taivaisiin!" +general.3931="%%puncher%% heitti lumipallolla ystävänsä, pelaajan %%punched%% korkealle taivaisiin!" +general.3932="Tämä peli on nauhoitettu. Klikkaa tästä nähdäksesi uusinnan!" +general.3933="Klikkaa katsoaksesi tai käytä komentoa /replay tarkastellaksesi kaikkia viimeisimpiä pelejäsi." +general.3934="Tämä peli on nauhoitettu. Osta %%rank%% voidaksesi katsoa uusintoja." +general.3935="Klikkaa avataksesi kaupan osoitteessa https://store.hypixel.net" +general.3936="\nSyötä salasana\nyläpuolelle\n" +general.3937="Olet AFK. Liiku poistuaksesi AFK-tilasta." +general.3938="%%percent%% pelaajista on avannut tämän!" +general.3939="Käytä satunnaista %%cosmetic%%!" +general.3940="Klooni" +general.3941="Vaaleansininen villa" +general.3942="Et voi lyödä pelaajia, jotka suorittavat parkouria!" +general.3943="%%player%% saapui lobbyyn!" +general.3944="Kieltäydy lahjoista automaattisesti" +general.3945="Kun käytössä, kaikki lahjapyynnöt hylätään automaattisesti." +general.3946="Lobbyn tumma teema" +general.3947="Vaihtaa lobbyn vuorokauden aikaa päivän ja yön välillä." +general.3948="Online-tila" +general.3949="Tämän ollessa poissa käytöstä, PublicAPI ei voi käyttää online-tilaasi tai pelaamiasi pelejä ulkoisissa työkaluissa." +general.recent_games="Viimeaikaiset pelit" +general.3951="Tämän ollessa on poissa käytöstä, PublicAPI ei voi käyttää online-tilaasi tai pelaamiasi pelejä ulkoisissa työkaluissa." +general.3952="API-asetukset" +general.3953="5 tuntia!" +general.3954="Olet asettanut esineen pois päältä!" +general.3955="Olet asettanut esineen päälle!" +general.3956="Päivittäinen" +general.3957="Kurpitsalyhty" +general.3958="+%%amount%% Pit-kultaa" +general.3959="Tapa 25 pelaajaa" +general.3960="Vapauta parvi!" +general.3961="Satenkaarilahja" +general.3962="Avautuu tasolla %%level%%" +general.3963="Avataan Halloween Bundlessa!" +general.3964="Metsästäjä" +general.3965="Oppipoika" +general.3966="Tapot" +general.3967="Murhaajatapot" +general.3968="Murhaajavoitot" +general.3969="Capture the Wool -voitot" +general.3970="Hide and Seek: Piiloutujavoitot" +general.3971="Hide and Seek: Etsijävoitot" +general.3972="Zombies: Voitot" +general.3973="Zombies: Paras kierros" +general.3974="Avustukset" +general.3975="Voittoputki" +general.3976="Viimeisin ilmiantosi tutkittiin ja käsiteltiin. Kiitos! :)" +general.3977="%%player%% on päättänyt hyväksyä lahjasi %%item%%!" +general.3978="%%player%% on päättänyt kieltäytyä lahjastasi. Anteeksi!" +general.3979="Sinulta ei veloitettu yhtään gold." +general.3980="%%player%% ei hyväksynyt lahjaasi ajoissa, joten se vanhentui!" +general.3981="Nyrkkeily" +general.3982="Vanhentuneet saavutukset: %%count%%" +general.3983="Vanhentuneiden saavutusten pisteet: %%count%%" +general.3984="Vanhentuneet saavutukset" +general.3985="Näitä saavutuksia ei voi enää ansaita, sillä niitä vastaavat tapahtumat ja pelit eivät enää ole saatavilla." +general.3986="Pisteet näistä saavutuksista lasketaan yhä mukaan saavutuspalkintoihin, mutteivät sisälly tulostaulukoihin." +general.3987="Pisteet: %%count%%" +general.3988="Avattu: %%count%%" +general.3989="Järjestä oletusasettelun mukaan." +general.3990="Kurpitsat purskahtavat tappamasi pelaajan ruumiista" +general.3991="Murskaa vihollisesi puruiksi!" +general.3992="Koulu on peruttu! Ota kuppi kuumaa kaakaota! Lumi on tukkinut kaikki tiet!" +general.3993="Saatavilla kaupassa:" +general.3994="Kulta" +general.3995="Timantti" +general.3996="Et ole avannut tätä saavutusta vielä!" +general.3997="Olet jo aloittanut tehtävän %%name%%!" +general.3998="Peli alkaa %%time%% sekunnin kuluttua!" +general.3999="Rotan vuosi" +general.4000="Kartanvalinnat" +general.4001="Sinulla ei ole yhtään Network Boosteria saatavilla! Voit ostaa niitä osoitteessa\nhttps://store.hypixel.net/" +general.4002="Rauta" +general.4003="Mestari" +general.4004="Legenda" +general.4005="Hole in the Wall" +general.4006="Selaa avaamiasi pelin %%gamename%% kosmeettisia esineitä tai osta niitä suoraan kolikoilla." +general.4007="Ratsasta ghastilla helvetin netherin läpi" +general.4008="Pelaajat: " +general.4009="Klikkaa saadaksesi käännöksen!" +general.4010="Nettisivuiltamme saatavat päivittäiset palkinnot sisältävät esimerkiksi %%coins%%, %%exp%%, %%souls%%, uniikkeja kosmeettisia esineitä ja paljon muuta!" +general.4011="Lelukeppi" +general.4012="Vieraile pelaajan talossa" +general.4013="Avataan Rank Gifting -palkintona!" +general.4014="Raketti" +general.4015="Tulkoon nahka" +general.4016="Härkäasu" +general.4017="Käpertynyt härkä" +general.4018="Vihainen lehmä" +general.4019="Härän vuosi" +general.4020="Surullinen muu" +general.4021="Sammunut lyhty" +general.4022="Lehmäraketti" +general.4023="Naudanlihaa kaikkialla" +general.4024="Kuuhun siis" +general.4025="Härän hyökkäys" +general.4026="Pyhä karja" +general.4027="Härkä" +general.4028="Olet viimeistellyt salanimesi asettamisen!" +general.4029="Kun menet peliin, sinun nimimerkkisi on %%nick%%. Nimimerkkisi ei näy lobbyissa." +general.4030="GG" +general.4031="Kantava voima" +general.4032="Nahkalakki" +general.4033="Nahkatakki" +general.4034="Nahkahousut" +general.4035="Roiskahtava myrkyllinen taikajuoma" +general.4036="Roiskahtava nopeuden taikajuoma" +general.4037="Roiskahtava parantumisen taikajuoma" +general.4038="Roiskahtava nopeuden taikajuoma II" +general.4039="Insinööri" +general.4040="Maanviljelijä" +general.4041="Ritari" +general.4042="Vahvuuden taikajuoma" +general.4043="Roiskahtava vahingoittamisen taikajuoma" +general.4044="Roiskahtava heikkouden taikajuoma" +general.4045="Vesimieltymys" +general.4046="Hengitys" +general.4047="Roiskahtava kestävyyden taikajuoma" +general.4048="Rengaspanssarin saappaat" +general.4049="Magnolia" +general.4050="Ne ovat täällä vain hetken, mutta kyllä ne ovat kauniita!" +general.4051="Sadepäivän ilo" +general.4052="Kukapa ei pitäisi pienestä sadekuurosta?" +general.4053="Vau, kokonainen sateenkaari!" +general.4054="Sateinen" +general.4055="Kanaratsastaja" +general.4056="Söpö pupu" +general.4057="Muna-ase" +general.4058="Munaosuma" +general.4059="Muna-aika" +general.4060="Puput korissa" +general.4061="Pääsiäiskello" +general.4062="Hypixel-veteraanin status" +general.4063="Uusi Hypixel-pelaaja" +general.4064="%%color%%%%years%% vuoden Hypixel-veteraani" +general.4065="Avataan Hypixelin syntymäpäivätehtävästä" +general.4066="Pelaaja poistettiin pelistäsi.\nKäytä komentoa /report auttaaksesi palvelintamme!" +general.4067="Pelaaja poistettiin lobbystasi.\nKäytä komentoa /report auttaaksesi palvelintamme!" +general.4068="%%color%%1 vuoden Hypixel-veteraani" +general.4069="Poistettiin arvonimi %%name%%!" +general.4070="Arvonimen poistamisessa ilmeni ongelma: %%message%%" +general.4071="Guild backend ei ole juuri nyt tavoitettavissa. Yritä myöhemmin uudelleen." +general.4072="Arvonimen luomisessa ilmeni ongelma. Yritä hetken kuluttua uudelleen." +general.4073="Arvonimen poistamisessa ilmeni ongelma. Yritä hetken kuluttua uudelleen." +general.4074="Oletusarvonimen asettamisessa ilmeni ongelma. Yritä hetken kuluttua uudelleen." +general.4075="Arvonimen uudelleennimeämisessä ilmeni ongelma. Yritä hetken kuluttua uudelleen." +general.4076="Arvonimen oikeuksien muokkaamisessa ilmeni ongelma. Yritä hetken kuluttua uudelleen." +general.4077="Arvonimen tunnisteen muokkaamisessa ilmeni ongelma. Yritä hetken kuluttua uudelleen." +general.4078="Arvonimen tunnisteen muokkaamisessa ilmeni ongelma: %%message%%" +general.4079="Hidasta vähän, ei noin nopeasti." +general.4080="Käsitellään pyyntöäsi..." +general.4081="%%name%% on nyt oletusarvonimi!" +general.4082="Oletusarvonimen asettamisessa ilmeni ongelma: %%message%%" +general.4083="Arvonimen %%oldRankName%% uusi nimitys on nyt %%newRankName%%!" +general.4084="Arvonimen nimityksen asettamisessa ilmeni ongelma: %%message%%" +general.4085="Annettiin oikeus %%permission%% arvonimelle %%rankName%%!" +general.4086="Poistettiin oikeus %%permission%% arvonimeltä %%rankName%%!" +general.4087="Arvonimen oikeuksien muokkaamisessa ilmeni ongelma: %%message%%" +general.4088="Tunniste poistettu onnistuneesti!" +general.4089="Tunniste vaihdettu onnistuneesti: %%tag%%!" +general.4090="Vihollisen tappaminen saa aikaan veriräjähdyksen." +general.4091="Tappamasi vihollinen lentää kuin leppäkeihäs." +general.4092="Vihollisesi pää lennähtää korkealle ilmaan tappaessasi hänet." +general.4093="Tappamasi vihollinen räjähtää kuin Piñata." +general.4094="TNT räjähtää kadottaen tappamasi vihollisen." +general.4095="Kokemus" +general.4096="Kuinka kauan pelaaja on ollut guildissa" +general.4097="Muokkaa seuraavia visuaalisia ominaisuuksia pelaajallasi!" +general.4098="∙ MVP+-rankin väri" +general.4099="∙ Lyöntiviestit" +general.4100="∙ Hehku" +general.4101="∙ Status" +general.4102="Ei näytettäviä saavutuksia!" +general.4103="Nykyisillä asetuksillasi ei ole nähtävissä yhtään saavutusta." +general.4104="Kausittaiset saavutukset: %%gameType%%" +general.4105="Näytä pelin %%gameType%% kausittaiset haastesaavutukset." +general.4106="Näitä saavutuksia ei lasketa mukaan pelin saavutusten suoritusprosenttiin." +general.4107="Kausittaiset haastesaavutukset" +general.4108="+%%amount%% %%multiplier%%x Henkilökohtainen kolikkobooster (%%length%%)" +general.4109="Kieli puuttuu! Saatavilla olevat kielet: %%values%%" +general.4110="Virheellinen kieli '%%text%%'! Saatavilla olevat kielet: %%values%%" +general.4111="Juhli esittelemällä voitontanssiasi muille pelaajille aina kun voitat!" +general.4112="Valikoima erilaisia efektejä, joista valitsemasi aktivoituu aina tappaessasi vihollisen!" +general.4113="Klikkaa työstääksesi %%cost%% mysteeripölyllä!" +general.4114="Joulutehtävä-eksklusiivinen" +general.4115="Syöttämäsi salanimi on merkattu sopimattomaksi ja sen käyttö on estetty! Lisätietoja saat osoitteesta https://hypixel.net/rules." +general.4116="Tämä salanimi on sopimaton!" +general.4117="Sinulla ei ole vaadittua rankkia tämän käyttämiseksi!" +general.4118="AVATTU!" +general.4119="Tätä kosmeettista esinettä ei tarvitse valita, se on jo aktiivinen!" +general.4120="PAIKALLA:" +general.4121="Pelaajia ei löytynyt, pahoittelut!" +general.4122="Näkymättömyyden taikajuoma" +general.4123="Nopeuden taikajuoma" +general.4124="Tätä kosmeettista esinettä ei tarvitse valita!" +general.4125="Kurpitsaraketti" +general.4126="Taikajuomasade" +general.4127="Karkki vai kepponen" +general.4128="Infection" +general.4129="Kurpitsapelto" +general.4130="Tämä esine ei ole juuri nyt saatavilla!" +general.4131="%%puncher%% säikäytti pelaajan %%punched%% korkealle taivaisiin!" +general.4132="%%puncher%% säikäytti ystävänsä, pelaajan %%punched%% korkealle taivaisiin!" +general.4133="Avataan Päälobbyn Noidan padassa!" +general.4134="Avataan Halloween-päälobbyn Noidan padassa!" +general.4135="%%color%%Saatavilla rankille %%rank%% %%color%%tapahtuman %%festival%% aikana!" +general.4136="Pöö!" +general.4137="Karkki vai kepponen!" +general.4138="Legendaarinen Kalastaja" +general.4139="Avataan Päälobbyn Kalastuspalkintona" +general.4140="Päälobbyn Erikoiskaloja napattu" +general.4141="Päälobbyn Aarteita löydetty" +general.4142="Kunnianarvoisa Aave" +general.4143="Kurpitzoita" +general.4144="Karmiva Luurankoinen" +general.4145="Karkit" +general.4146="Otettiin lumipartikkelit käyttöön! Voit asettaa ne pois päältä koska tahansa komennolla /letitsnow!" +general.4147="Jokin meni vikaan annettaessa pakkausta, ilmoitathan tästä osoitteessa http://hypixel.net/bugs!" +general.4148="Poistettiin lumipartikkelit käytöstä! Voit ottaa ne käyttöön koska tahansa komennolla /letitsnow!" +general.4149="%%amount%%x %%item%% KAKSOISKAPPALE" +general.4150="%%amount%%x %%item%%" +general.4151="%%player%% löysi esineen %%item%% %%name%%ista!" +general.4152="%%player%% löysi esineen %%item%% %%name%%ista!" +general.4153="SINUA ONNISTI!\nSaat TUPLA-EXP tässä pelissä!" +general.4154="Tämä on Guildin tasopalkinto. Koska guildisi on tasolla %%level%%, sinulla on %%chance%%% todennäköisyys saada TUPLA-EXP." +general.4155="Lumienkeli" +general.4156="Menora" +general.4157="Lumi-Jerry" +general.4158="Karkkitankoampuja" +general.4159="Lumiukonrakennus" +general.4160="Joulumusiikkia" +general.4161="Jouluinen" +general.4162="Dreidel" +general.4163="Orjanlaakeri" +general.4164="Wreath" +general.4165="Kultalahja" +general.4166="Punavihreä lahja" +general.4167="Kuktavalkoinen lahja" +general.4168="Pähkinänsärkijä" +general.4169="Hanukka" +general.4170="Joulupukin hattu" +general.4171="Hypixel Store ei ole saatavilla täällä! Yritä lobbyssa!" +general.4172="HYVÄÄ JOULUA JA ONNELLISTA UUTTA VUOTTA TOIVOO HYPIXEL" +general.4173="Karmiva lyöntiviesti" +general.4174="Kalastuslyöntiviesti" +general.4175="%%puncher%% kalasti pelaajan %%punched%% korkealle taivaisiin!" +general.4176="%%puncher%% kalasti ystävänsä, pelaajan %%punched%% korkealle taivaisiin!" +general.4177="Avataan Kalastuksen kausittaispalkintona!" +general.4178="Avataan Päälobbyn kalastuksen kausittaispalkintona!" +general.4179="Ylläpito ja parhaat kaverit voivat lähettää sinulle viestejä." +general.4180="Ylläpito ja parhaat kaverit voivat lähettää sinulle party-kutsuja." +general.4181="Ylläpito ja parhaat kaverit voivat lähettää sinulle guild-kutsuja." +general.4182="Ylläpito ja parhaat kaverit voivat lähettää sinulle Duel-kutsuja." +general.4183="Asetukset:" +general.4184="Asetukset & Näkyvyys" +general.4185="Sallii sinun muokata ja hallita henkilökohtaisia asetuksiasi." +general.4186="Yhteisöasetukset" +general.4187="Peliasetukset" +general.4188="Tiikeri" +general.4189="Roar" +general.4190="Kultainen tiikeri" +general.4191="Kirkas tiikeri" +general.4192="Hyvä onni" +general.4193="Leijonatanssija" +general.4194="Makeita unia" +general.4195="Tiikerin vuosi" +general.4196="Tähtäys, ja osuma" +general.4197="Haluatko pelata pelejä?" +general.4198=" - Klikkaa NPC-hahmoja spawn-alueen edessä." +general.4199="Klikkaa tästä teleportataksesi spawn-alueelle." +general.4200=" - Käytä kompassiasi avataksesi pelivalikon." +general.4201="Klikkaa tästä avataksesi pelivalikon." +general.4202=" - Käytä komentoja, kuten $ tai $." +general.4203="Klikkaa tästä mennäksesi Bed Wars -lobbyyn." +general.4204="Klikkaa tästä pelataksesi SkyBlockia." +general.4205="Kieleksesi vaihdettiin automaattisesti %%language%%." +general.4206="Klikkaa tästä vaihtaaksesi takaisin kieleen %%language%%." +general.4207="Klikkaa vaihtaaksesi kielesi." +general.4208="Nolla" +general.4209="Yksi" +general.4210="Kaksi" +general.4211="Kolme" +general.4212="Neljä" +general.4213="Viisi" +general.4214="Kuusi" +general.4215="Seitsemän" +general.4216="Kahdeksan" +general.4217="Yhdeksän" +general.4218="%%playing%% pelaamassa" +general.4219="Koodinmurtaja-lyöntiviesti" +general.4220="%%puncher%% %%magic%%H mursi pelaajan %%punched%% koodin %%magic%%H korkealle taivaisiin!" +general.4221="%%puncher%% %%magic%%H mursi ystävänsä, pelaajan %%punched%% koodin %%magic%%H korkealle taivaisiin!" +general.4222="Pääsiäissaavutus" +general.4223="Kesäsaavutus" +general.4224="Halloweensaavutus" +general.4225="Joulusaavutus" +general.4226="Lahjoita rank" +general.4227="Lahjoita rank pelaajalle %%player%%." +general.4228="Klikkaa antaaksesi lahjan!" +general.4229="Et voi lahjoittaa rankkeja tälle pelaajalle!" +general.4230="Tämä pelaaja ei ole lobbyssasi!" +general.4231="Luodaan ainutlaatuista satunnaista nimeä. Odota hetki..." +general.4232="Käsitellään pyyntöä. Odota hetki..." +general.4233="Käytä komentoa /rankcolor vaihtaaksesi väriä ja nähdäksesi kaikki vaihtoehdot." +general.4234="%%player%% hyppäsi lobbyyn!" +general.4235="Avaa loputon kartanvalinta ostamalla MVP+ osoitteesta https://store.hypixel.net" +general.4236="%s+%s%s mysteeripölyä" +general.4237="Ottaaksesi viirin käyttöön, mene Keräilyesineet > Viirit" +general.4238="#%%number%%" +general.4239="+Kyky vaihtaa nimen edessä olevan '+'-merkin väriä rankilla %%rank%%" +general.4240="Sinulla ei ole tarvittavaa rankkia tätä bonusta varten! Osta rankkeja osoitteessa https://store.hypixel.net" +general.4241="Kysely saatavilla!" +general.4242="Klikkaa tästä tai käytä komentoa /resource avataksesi resurssipakettikirjan." +general.4243="Tätä ei voi kumota." +general.4244="Voit ostaa VIP-rankin kaupasta osoitteesta https://store.hypixel.net" +general.4245="Löydät kaupan osoitteesta https://store.hypixel.net" +general.4246="%%player%% kelkkaili lobbyyn!" +general.4247="Kuuma peruna -vempain" +general.4248="Vuosipäivän trampoliinivempain" +general.4249="Hypixel-klikkausefekti" +general.4250="Et voi lähettää giftejä itsellesi!" +general.4251="ok" +general.4252="Hei, on väärä aika vuodesta!" +general.4253="Yleiset tilastot" +general.4254="Vaihdettiin etuliitteesi väriksi %%color%%!" +general.4255="Saatavilla vain pääsiäisenä ja erikoistapahtumien aikaan" +general.4256="Pelaat palvelimella MC.HYPIXEL.NET" +general.4257="Rankkeja, Boostereita & PALJON MUUTA! STORE.HYPIXEL.NET" +general.4258="Äärimmäinen" +general.4259="Tilin tila" +general.4260="Tarkista rangaistushistoriasi ja katso, mikä on tilanteesi." +general.4261="Tilin tila" +general.4262="Replayta hyödyntävä järjestelmä, joka auttaa Hypixelin ylläpitoa huijareiden jäljittämisessä.\n\nKatso pelaajien ilmiantamia huijareita määrittääksesi, ovatko ilmiannot perusteltuja!" +general.4263="Guildin arvonimi" +general.4264="SP" +general.4265="Ylläpitäjien ([GM] ja [ADMIN]) lyöminen on kaikille MVP%%color%%+-pelaajille saatavilla oleva ominaisuus." +general.4266="Pelaa toinen satunnainen peli (Oikeaklikkaa)" +general.4267="Oikeaklikkaa pelataksesi toisen satunnaisen pelin!" +general.4268="Oikeaklikkaa NPC-hahmoja" +general.4269="liittyäksesi peleihin ja aloittaaksesi pelaamisen." +general.4270="Voit käyttää komentoa /friend add" +general.4271="lisätäksesi pelaajan kaveriksesi." +general.4272="Käytä komentoa /party invite" +general.4273="pelataksesi muiden pelaajien kanssa!" +general.4274="Vieraile verkkosivuillamme!" +general.4275="www.hypixel.net - uutisia, keskustelua ja muuta!" +general.4276="Siinä se!" +general.4277="Pidä hauskaa palvelimella!" +general.4278="Saavutusopas" +general.4279="Paikalla" +general.4280="Poissa" +general.4281="Kiireinen" +general.4282="Näkymätön" +general.4283="Näkymätön-tilassa" +general.4284="Aktivoi henkilökohtaisia boostereita sekä koko palvelimen laajuisia network boostereita saadaksesi ylimääräisiä kolikoita." +general.4285="Antaa ylimääräisen kolikkokertoimen kaikkiin peleihin joksikin aikaa." +general.4286="Antaa KAIKILLE ylimääräisen kolikkokertoimen tiettyyn peliin tai kaikkiin peleihin!" +general.4287="Pupuja, jotka juoksevat ympäriinsä ja räjähtävät!" +general.4288="Juhli upealla ilotulituksella!" +general.4289="Rakenna ympärillesi lumiukkoja, jotka räjähtävät heti synnyttyään!" +general.4290="AKTIVOI BOOSTER" +general.4291="Voit aktivoida pelin %%game%% Network Boosterisi kahdella tavalla:" +general.4292="ASETA BOOSTER JONOON" +general.4293="Klikkaa saadaksesi lisätietoa boosterin asettamisesta jonoon." +general.4294="LISÄÄ BOOSTER KASAAN" +general.4295="Klikkaa saadaksesi lisätietoa boosterin asettamisesta kasaan." +general.4296="Aktivoituasi boosterin saat kolikoita ja Hypixel-experienceä, kun muut pelaajat kiittävät sinua." +general.4297="Asettamalla boosterin jonoon annat kaikille pelaajille +2X kolikot peliin %%game%%." +general.4298="Arvioitu odotusaika: " +general.4299="Klikkaa asettaaksesi boosterin jonoon." +general.4300="Voit myös " +general.4301="Lisää booster kasaan >" +general.4302="Lisää boosterisi kasaan aktivoidaksesi sen nopeammin! Lisää 0.1X nykyiseen kertoimeen, voi olla enintään +3X (10 kasattua boosteria)." +general.4303="Klikkaa lisätäksesi boosterin kasaan." +general.4304="Aseta booster jonoon >" +general.4305="Arvonimessä voi olla enintään 16 merkkiä!" +general.4306="Tuo sana/lause on jo suodattimessasi!" +general.4307="Et voi lisätä suodattimeen sanaa/lausetta, joka on yli 32 merkkiä pitkä!" +general.4308="Sinulla ei ole tuota sanaa/lausetta suodattimessasi!" +general.4309="POISSA" +general.4310="KIIREINEN" +general.4311="NÄKYMÄTÖN-TILASSA" +general.4312="Kesto: %%duration%%" +general.4313="Pelimuoto: %%value%%" +general.4314="Kartta: %%value%%" +general.4315="Palvelin: %%value%%" +general.4316="Pelaajia: %%value%%" +general.4317="Alkoi %%time%% sitten" +general.4318="Peli käynnissä" +general.4319="Klikkaa katsoaksesi replayn!" +general.4320="Replay vanhentui!" +general.4321="Replay vaatii korkeamman rankin!" +general.4322="Yritetään ladata replayta..." +general.4323="Tätä replayta ei voi katsoa juuri nyt! Yritä hetken kuluttua uudelleen!" +general.4324="Tätä ei voi tehdä juuri nyt! Yritä hetken kuluttua uudelleen." +general.4325="Lähetetään sinut taloon %%house%%" +general.4326="Talo: %%house%%" +general.4327="Klikkaa liittyäksesi!" +general.4328="TASAPELI!" +general.4329="PELI VOITETTU!" +general.4330="PELI HÄVITTY!" +general.4331="%%player1%% VS %%player2%%" +general.4332="VS" +general.4333="Ei kukaan" +general.4334="(Tuntematon peli)" +general.4335="Päivittäinen %%mode%% -voittoputki: " +general.4336="Kokonaisvoittoputki: " +general.4337="(Party-peli)" +general.4338="(Duel-komento)" +general.4339="(Yksityinen peli)" +general.4340="(Tavallinen peli)" +general.4341="(Turnaus)" +general.4342="(Ranked)" +general.4343="(Championship)" +general.4344="Hoops" +general.4345="Muokkaa tavaraluettelosi asettelua %%key%%." +general.4346="Muokkaa asettelua - %%key%%" +general.4347="Työkalupalkki" +general.4348="Tallenna asettelu" +general.4349="Tallenna tavaraluettelosi asettelu %%key%%." +general.4350="Klikkaa tallentaaksesi!" +general.4351="Tallensit tavaraluettelosi asettelun %%key%%!" +general.4352="Nollaa asettelu" +general.4353="Nollaa tavaraluettelosi asettelu %%key%%." +general.4354="Nollasit tavaraluettelosi asettelun %%key%%!" +general.4355="LEGENDAARINEN" +general.4356="Olemme lisänneet mahdollisuuden sinulle auttaa meitä kääntämään Hypixel vieläkin useammille eri kielille!" +general.4357="+%%amount%% villaa" +general.4358="+%%amount%% Wool Wars Experienceä" +general.4359="%%game%% -tehtävät" +general.4360="Avataan Event-kaupasta!" +general.4361="Olet nyt %%color%%Event-levelillä %%accentColor%%%%level%%!" +general.4362="Ansaitsit %%silver%% Event-silveriä!" +general.4363="Shokkiaalto" +general.4364="Myrskyinen" +general.4365="Lämpöaallonluoja" +general.4366="Tämän mystisiä voimia kantavan tikun huhutaan aikoinaan kuuluneen itse Heliokselle." +general.4367="Pelin kosmeettinen esine" +general.4368="Wool Warsin kosmeettinen esine" +general.4369="Bed Warsin kosmeettinen esine" +general.4370="Murder Mysteryn kosmeettinen esine" +general.4371="Duelsin kosmeettinen esine" +general.4372="SkyWarsin kosmeettinen esine" +general.4373="Lobby-lyöntiviesti" +general.4374="Lobby-status" +general.4375="Lobbyn kosmeettinen esine" +general.4376="Lisätty: %%color%%%%festival%% %%year%%" +general.4377="Hinta: %%cost%% Event-silveriä" +general.4378="Ostettu!" +general.4379="Ei tarpeeksi Silveriä!" +general.4380="Klikkaa ostaaksesi!" +general.4381="Event-kauppa" +general.4382="Ostit esineen %%cosmetic%%!" +general.4383="Sinulla ei ole tarpeeksi Silveriä ostaaksesi tuota!" +general.4384="Nouse tasoissa tapahtumien aikana pelaamalla pelejä ja suorittamalla tehtäviä." +general.4385="Kesäinen näkymä -este" +general.4386="Lämpöaalto-tappoilmoitukset" +general.4387="Poltettu-sängyntuhoamisefekti" +general.4388="Aurinkovarjo-saarikoriste" +general.4389="Lainelauta-saarikoriste" +general.4390="Aalto-saarikoriste" +general.4391="Jäätelöhäkki" +general.4392="Hiekkalinnahäkki" +general.4393="Frisbee-puukko" +general.4394="Liekeissä-aura" +general.4395="Rentoutunut- kosmeettinen arvonimi" +general.4396="Kesän Event-level -status" +general.4397="%%accentColor%%Event-level %%color%%%%level%% %%levelBar%% %%accentColor%%%%percent%%" +general.4398="MAX" +general.4399="Käynnissä nyt: %%festival%%" +general.4400="%%festival%% %%year%%" +general.4401="Event-silver: %%silver%%" +general.4402="Klikkaa näyttääksesi kaupan!" +general.4403="Event-kauppa" +general.4404="Ei tapahtumaa käynnissä!" +general.4405="OLETUS" +general.4406="Etu rankista %%prefix%%" +general.4407="%%color%%%%multiplier%%x EXP-tehostus" +general.4408="%%silver%% Silveriä tasosta" +general.4409="%%color%%Tason edistyminen" +general.4410="Klikkaa avataksesi Hypixel Storen!" +general.4411="Tietoja rank-edusta" +general.4412="%%color%%%%highlight%%%%multiplier%%%%highlight%%x EXP-tehostus" +general.4413="%%highlight%%%%silver%% %%highlight%%Silveriä tasosta" +general.4414=" %%underline%%KLIKKAA AVATAKSESI" +general.4415="HYPIXEL" +general.4416="STORE" +general.4417="Voit ostaa rankkeja kaupastamme!" +general.4418="Tuetut pelit:" +general.4419="Käytä tätä lyöntiviestiä MVP+-rankilla tai Lyö ystäviä -perkin kanssa lyödessäsi ylläpidon jäseniä ilmaan!" +general.4420="Leveile Event-levelilläsi kaikille lobbyssa tällä statuksella!" +general.4421="Näytä kaikille miten tuhoat vihollisen sängyn Bed Warsissa tällä sängyntuhoamisefektillä." +general.4422="Tee Bed Wars -saarestasi suorastaan upea tällä saarikoristeella!" +general.4423="Ainutlaatuisia partikkeleita, jotka näkyvät liikkuessasi Duelsissa!" +general.4424="Esittele kunniatasoasi tällä arvonimellä Duelsissa." +general.4425="Esittele tyyliäsi murhaajana tällä frisbeellä, joka vaihtaa väriä jokaisessa pelissä!" +general.4426="Liity peliin tyylillä tällä SkyWars-häkillä!" +general.4427="Tutustu tähän lobbyn kosmeettiseen esineeseen Keräilyesineet-valikossa!" +general.4428="Avaa tämä este Wool Warsiin ja esittele sitä ennen kierroksen alkua!" +general.4429="Avaa tämä tappoilmoituspaketti Wool Warsiin käyttääksesi sitä tappaessasi pelaajia!" +general.4430="%%puncher%% laukaisi pelaajan %%punched%% suoraan aurinkoon!" +general.4431="Aurinkoinen lyöntiviesti" +general.4432="Osta tämä kosmeettinen esine Event-kaupasta tapahtumien aikana!" +general.4433="+%%amount%% Event Experienceä" +general.4434="Avaa tämä tappoefekti käyttääksesi sitä useissa eri peleissä!" +general.4435="Avaa tämä ammusjälki käyttääksesi sitä useissa eri peleissä!" +general.4436="Avaa tämä voitontanssi käyttääksesi sitä useissa eri peleissä!" +general.4437="Pelaajien vähimmäismäärä ei täyttynyt. Ole hyvä ja yritä liittyä peliin uudelleen myöhemmin." +general.4438="Et voi katsoa tämän pelaajan tilastoja." +general.4439="Tätä komentoa ei tueta täällä." +general.4440="%%days%%d" +general.4441="%%hours%%h" +general.4442="%%minutes%%min" +general.4443="<10min" +general.4444="SUOSITELTU!" +general.4445="Klikkaa tästä asettaksesi salanimen satunnaisella skinillä peittääksesi identiteettisi paremmin." +general.4446="EI SUOSITELTU!" +general.4447="Klikkaa tästä asettaaksesi salanimen omalla skinilläsi. Tämä antaa muiden pelaajien selvittää todellisen identiteettisi." +general.4448="Johtuen Minecraft-skinien toiminnasta oman skinisi käyttäminen saattaa antaa muiden pelaajien selvittää todellisen identiteettisi." +general.4449="Suosittelemme valitsemaan satunnaisen skinin." +general.4450="Käytät nyt oman Minecraft-hahmosi skiniä myös käyttäessäsi salanimeä! Johtuen Minecraft-skinien toiminnasta oman skinisi käyttäminen saattaa antaa muiden pelaajien selvittää todellisen identiteettisi." +general.4451=" %%underline%%➤ Suosittelemme valitsemaan satunnaisen skinin." +general.4452="SUOSITELTU!\nKlikkaa tästä asettaaksesi salanimen satunnaisella skinillä peittääksesi identiteettisi paremmin." +general.4453="Pixel Party: Paras kierros" +general.4454="Pixel Party: Voitot" +general.4455="Pixel Party - Voitot" +general.4456="Pixel Party - Paras kierros" +general.4457="Pixel Party - Suoritetut kierrokset" +general.4458="Vaaleanharmaa" +general.4459="Palkintoja voi lunastaa enintään sekunnin välein!" +general.4460="%s+%s%s%s Hypixel-experienceä" +general.4461="Lähetä shokkiaalto vastustajasi ruumiin läpi." +general.4462="Aiemmin seuraamasi pelaaja ei ole enää elossa." +general.4463="∙ Useita Arcade-pelejä" +general.4464="Vaadittu rank: %%rank%%" +general.4465="Sinulla ei ole vaadittua rankkia!" +general.4466="SkyBlockin kosmeettinen esine" +general.4467="Mustan kissan ulkonäkö: Paranormauli" +general.4468="Ampiaisen ulkonäkö: Zombi" +general.4469="Rotan ulkonäkö: Piiplonen" +general.4470="Halloweenin Event-level -status" +general.4471="Demoni-saarikoriste" +general.4472="Zombikäsi-saarikoriste" +general.4473="Suklaalevy-saarikoriste" +general.4474="Kurpitsalyhtyhäkki" +general.4475="Kallohäkki" +general.4476="Maissikarkkiasu" +general.4477="Vuokkokalalemmikki" +general.4478="Happosadekaapu" +general.4479="Luusiivet-kaapu" +general.4480="Liekehtivä heittokoukkuvempain" +general.4481="Kurpitsapommittaja-voitontanssi" +general.4482="Kurpitsapallo-ammusjälki" +general.4483="Karkkikori-ammusjälki" +general.4484="Tuonpuoleinen-tappoefekti" +general.4485="Kurpitsalyhdyt-tappoefekti" +general.4486="Event-kauppa on tällä hetkellä poissa käytöstä, palaa pian takaisin!" +general.4487="Päättyy pian!" +general.4488="Päättyy %%days%% päivän kuluttua!" +general.4489="Esittele tyyliäsi tällä siistillä asulla Build Battlessa!" +general.4490="Lunasta %%color%%%%item%% SkyBlockin Jerryn toimituksista!" +general.4491="TAVALLINEN" +general.4492="EPÄTAVALLINEN" +general.4493="HARVINAINEN" +general.4494="EEPPINEN" +general.4495="LEGENDAARINEN" +general.4496="MYYTTINEN" +general.4497="Anna SkyBlock-lemmikillesi uusi tapahtumateemainen ulkonäkö!" +general.4498="Saatat joutua vaihtamaan lobbya saadaksesi silverisi." +general.4499="Jokin on vialla, käynnissä ei ole yhtään tapahtumaa!" +general.4500="Päivittäinen EXP: %%color%%%%daily%%/%%accentColor%%%%cap%%" +general.4501="Kuka tahansa voi lähettää sinulle kaveripyyntöjä." +general.4502="Nollaa mukautetut paikat" +general.4503="Nollaa KAIKKI mukautetut paikat." +general.4504="Nollattiin mukautetut paikkasi!" +general.4505="Mukautettu paikka" +general.4506="Tämä paikka voidaan vaihtaa suosikkipelisi tai pelimuotosi pikakuvakkeeksi!" +general.4507="Voit muuttaa tätä paikkaa milloin tahansa oikeaklikkaamalla." +general.4508="+Kyky vaihtaa nimen edessä olevan '+'-merkin väriä rankilla %%rank%%" +general.4509="Prototype-peli" +general.4510="Selviydy yhä vaikeammista kartoista laskeutumalla veteen ja ole ensimmäinen maalissa!" +general.4511="SAAVUTETTU" +general.4512="Lähitaisteluosumia" +general.4513="Lähitaisteluhyökkäyksiä" +general.4514="Nuoliosumat" +general.4515="Jousilaukaukset" +general.4516="Vahinkoa tehty" +general.4517="Elinvoimaa palautettu" +general.4518="Gun Game -voitot" +general.4519="Gun Game -tapot" +general.4520="Chaos-voitot" +general.4521="Pelejä pelattu" +general.4522="Kuolemat" +general.4523="Tulispiraali" +general.4524="Avataan Summer Bundlessa!" +general.4525="Pelin %%game%% kuvakkeet" +general.4526="Seiso oikealla värillä tai putoa kuolemaasi!" +general.4527="Valitse saatavilla olevien pelien luettelosta kartta, jossa haluat pelata." +general.4528="Ansaitse event-silveriä noustessasi event-tasoissa. Silverillä voi ostaa tapahtuma-aiheisia kosmeettisia esineitä!" +general.4529="Tämä saavutus on vanhentunut eikä sitä voi enää saada." +general.4530="Taisteluseuranta poissa käytöstä!" +general.4531="Taisteluseuranta käytössä!" +general.4532="Avataan asetuksia..." +general.4533="Käsitellään, yritä hetken kuluttua uudelleen!" +general.4534="Kiire kiire kiire kiire kiire..." +general.4535="Odota hetki, en voi tehdä kaikkea kerralla!" +general.4536="Tämä huolestuttaa minua..." +general.4537="Yritä kovemmin." +general.4538="Edistyminen: %%random%%" +general.4539="Kokeile tätä %%random%% kertaa lisää, se saattaa toimia!" +general.4540="Hei maailma!" +general.4541="Onko siellä ketään?" +general.4542="Olet onnistuneesti hakkeroinut pääpalvelintietokoneen algoritmien avulla!" +general.4543="%%game%% ei tue tätä toimintoa vielä!" +general.4544="Peli on jo alkanut!" +general.4545="Jokainen pelaaja kuolee yhdestä osumasta!" +general.4546="Vauhtia, vauhtia!" +general.4547="Paranna kaikkien pelaajien elinvoimaa!" +general.4548="Tätä kieltä valmistellaan paraikaa!" +general.4549="Näytä viimeksi pelaamasi pelit." +general.4550="Hypixel Replay-järjestelmällä pelaajat voivat katsoa lähiaikoina pelaamiaan pelejä." +general.4551="Replay-nauhoituksia tuetaan seuraavissa peleissä:" +general.4552="Hypixel Replay" +general.4553="Näytä vain replayt" +general.4554="Näytä kaikki" +general.4555="Määritä, näytetäänkö kaikki viimeaikaiset pelisi vai vain ne, joissa on replay." +general.4556="Hei.. sinä! Älä tee noin >:(" +general.4557="SINULLE ANNETTIIN VEGGY SPRINGLAZOR™ !!!" +general.4558="Erinomainen" +general.4559="Legendaarinen viiri: Hypixel-miekka" +general.4560="Legendaarinen viiri: Portaali" +general.4561="Lähettimies" +general.4562="Kartan valinta on poissa käytöstä turnauksen aikana!" +general.4563="Guildin tasopalkinto" +general.4564="Nykyinen putki: %%streak%%" +general.4565="Kysely" +general.4566="Ei kyselyä saatavilla juuri nyt!" +general.4567="Olet jo vastannut tähän kyselyyn!" +general.4568="Ei kyselyä saatavilla juuri nyt! Yritä myöhemmin uudelleen!" +general.4569="Olet jo vastannut tähän kyselyyn!" +general.4570="Ei kyselyä saatavilla juuri nyt! Yritä myöhemmin uudelleen!" +general.4571="Olet jo vastannut tähän kyselyyn!" +general.4572="Anna palautetta ja vastaa tähän kyselyyn!" +general.4573="Vastaa tähän kyselyyn ja ansaitse 5000 XP sekä 3000 Arcade-kolikkoa!" +general.4574="Vastaa tähän kyselyyn ja ansaitse 5000 XP!" +general.4575="Vastaa tähän kyselyyn ja ansaitse mahtavia palkintoja!" +general.4576="Kysely" +general.4577="Klikkaa vastataksesi tähän kyselyyn!" +general.4578="Saatavilla olevat pelit" +general.4579="Shamaanin ulkonäkö: Kevätsankari" +general.4580="Luurangon ulkonäkö: Jazz-kädet" +general.4581="Luurangon ulkonäkö: Avaruuspanssari" +general.4582="Luurangon ulkonäkö: Kepponen" +general.4583="Luurangon ulkonäkö: Kauhunen" +general.4584="Luurangon ulkonäkö: Red Ted" +general.4585="Zombin ulkonäkö: Toon" +general.4586="Zombin ulkonäkö: Jumbo" +general.4587="Zombin ulkonäkö: Taco" +general.4588="Zombin ulkonäkö: Haukotus" +general.4589="Zombin ulkonäkö: Gorilla" +general.4590="Creeperin ulkonäkö: Johnny" +general.4591="Creeperin ulkonäkö: Pommijätkä" +general.4592="Creeperin ulkonäkö: Tuho" +general.4593="Creeperin ulkonäkö: Kreeft" +general.4594="Creeperin ulkonäkö: Sirkka" +general.4595="Endermanin ulkonäkö: Dash" +general.4596="Endermanin ulkonäkö: Etsijä" +general.4597="Endermanin ulkonäkö: Pelaaja" +general.4598="Endermanin ulkonäkö: Varjo" +general.4599="Endermanin ulkonäkö: Hoops" +general.4600="Herobrinen ulkonäkö: Ukkonen" +general.4601="Herobrinen ulkonäkö: Larry" +general.4602="Herobrinen ulkonäkö: Aurinkoinen" +general.4603="Herobrinen ulkonäkö: Nyrkkeilijä" +general.4604="Herobrinen ulkonäkö: Odin" +general.4605="Hämähäkin ulkonäkö: Surma" +general.4606="Hämähäkin ulkonäkö: Vinny" +general.4607="Hämähäkin ulkonäkö: Lepatus" +general.4608="Hämähäkin ulkonäkö: Sammakko" +general.4609="Hämähäkin ulkonäkö: Häive" +general.4610="Kalmarin ulkonäkö: Vartija" +general.4611="Kalmarin ulkonäkö: Tohtori Liiske" +general.4612="Kalmarin ulkonäkö: K'Tulu" +general.4613="Kalmarin ulkonäkö: Valitus" +general.4614="Kalmarin ulkonäkö: Merisoturi" +general.4615="Pelon herran ulkonäkö: Tuomiopoika" +general.4616="Pelon herran ulkonäkö: Crowe" +general.4617="Pelon herran ulkonäkö: Rynnäköitsijä" +general.4618="Pelon herran ulkonäkö: Leivän herra" +general.4619="Pelon herran ulkonäkö: Itse hellyys" +general.4620="Shamaanin ulkonäkö: Toteemi" +general.4621="Shamaanin ulkonäkö: Koiruli" +general.4622="Shamaanin ulkonäkö: Diskokarhu Brian" +general.4623="Shamaanin ulkonäkö: Susi" +general.4624="Shamaanin ulkonäkö: Nikolaus" +general.4625="Mystikon ulkonäkö: Drufus" +general.4626="Mystikon ulkonäkö: Steele" +general.4627="Mystikon ulkonäkö: Chester" +general.4628="Mystikon ulkonäkö: Byron-poika" +general.4629="Shamaanin ulkonäkö: Keisari" +general.4630="Golemin ulkonäkö: Peikko" +general.4631="Golemin ulkonäkö: Bryce" +general.4632="Golemin ulkonäkö: Flint" +general.4633="Golemin ulkonäkö: Victor" +general.4634="Golemin ulkonäkö: Harmaa" +general.4635="Roihun ulkonäkö: Mango" +general.4636="Roihun ulkonäkö: Proto" +general.4637="Roihun ulkonäkö: Paahde" +general.4638="Roihun ulkonäkö: Chaze" +general.4639="Roihun ulkonäkö: Ghaze" +general.4640="Sikamiehen ulkonäkö: Supersika" +general.4641="Sikamiehen ulkonäkö: Kuningassika" +general.4642="Sikamiehen ulkonäkö: Kai" +general.4643="Sikamiehen ulkonäkö: Picasso" +general.4644="Sikamiehen ulkonäkö: Lainsuojaton" +general.4645="Merirosvon ulkonäkö: Kapteeni Luiseva" +general.4646="Merirosvon ulkonäkö: Jameson" +general.4647="Merirosvon ulkonäkö: Guy" +general.4648="Merirosvon ulkonäkö: Papukaija-Frank" +general.4649="Merirosvon ulkonäkö: Fjodor" +general.4650="Metsästäjän ulkonäkö: Terä" +general.4651="Metsästäjän ulkonäkö: Tucson" +general.4652="Metsästäjän ulkonäkö: Hippikuu" +general.4653="Metsästäjän ulkonäkö: Lammas" +general.4654="Metsästäjän ulkonäkö: Kakunmetsästäjä" +general.4655="Metsästäjän ulkonäkö: Luolamies Kuba" +general.4656="Feeniksin ulkonäkö: Seilori Sid" +general.4657="Feeniksin ulkonäkö: Pöllö" +general.4658="Feeniksin ulkonäkö: Kekäle" +general.4659="Feeniksin ulkonäkö: Hapsu" +general.4660="Feeniksin ulkonäkö: Haukka X" +general.4661="Ihmissuden ulkonäkö: Rousku" +general.4662="Ihmissuden ulkonäkö: Sini" +general.4663="Ihmissuden ulkonäkö: Pölyttäjä" +general.4664="Ihmissuden ulkonäkö: Jake" +general.4665="Ihmissuden ulkonäkö: Cruze" +general.4666="Myyrän ulkonäkö: Truck" +general.4667="Myyrän ulkonäkö: Kaivosmies Tyler" +general.4668="Myyrän ulkonäkö: Jolly" +general.4669="Myyrän ulkonäkö: Tiili" +general.4670="Myyrän ulkonäkö: Graen" +general.4671="Lehmän ulkonäkö: Lehmäasu" +general.4672="Lehmän ulkonäkö: Rautalehmä" +general.4673="Lehmän ulkonäkö: Luumuu" +general.4674="Lehmän ulkonäkö: Sienihullutus" +general.4675="Lehmän ulkonäkö: Vakava härkä" +general.4676="Lumiukon ulkonäkö: Gus" +general.4677="Lumiukon ulkonäkö: Frozen" +general.4678="Lumiukon ulkonäkö: Hirveä lumimies" +general.4679="Lumiukon ulkonäkö: Jääötökkä" +general.4680="Lumiukon ulkonäkö: Dobu" +general.4681="Automatonin ulkonäkö: Atomi" +general.4682="Automatonin ulkonäkö: Fenderi" +general.4683="Automatonin ulkonäkö: Tyhjiö" +general.4684="Automatonin ulkonäkö: Epäonnistunut koe" +general.4685="Automatonin ulkonäkö: Kampi" +general.4686="Salamurhaajan ulkonäkö: Hitguy" +general.4687="Salamurhaajan ulkonäkö: Torny" +general.4688="Salamurhaajan ulkonäkö: Connor" +general.4689="Salamurhaajan ulkonäkö: Blu" +general.4690="Salamurhaajan ulkonäkö: Okamoto" +general.4691="Luopion ulkonäkö: Peruskallio" +general.4692="Luopion ulkonäkö: Petturi" +general.4693="Luopion ulkonäkö: Ara" +general.4694="Luopion ulkonäkö: Huppu" +general.4695="Luopion ulkonäkö: Morde" +general.4696="Hain ulkonäkö: Shelly" +general.4697="Hain ulkonäkö: Aarre" +general.4698="Hain ulkonäkö: Ahmatti" +general.4699="Hain ulkonäkö: Wata" +general.4700="Hain ulkonäkö: Bblurgbl" +general.4701="Herobrinen ulkonäkö: Pukkibrine" +general.4702="Osta event-experienceä" +general.4703="Oletko jäämässä jälkeen? Osta event-experienceä noustaksesi tasoissa nopeammin!" +general.4704="Level: %%color%%%%level%%/%%accentColor%%%%maxLevel%%" +general.4705="Ostamalla rankin saat takautuvasti kaiken silverin, jonka olisit ansainnut kyseisellä rankilla." +general.4706="%%player%% otti käyttöön yksityisten pelien modifikaattorit!" +general.4707=" - %%name%%: %%value%%" +general.4708=" - %%name%%" +general.4709="Sielut" +general.4710="Sisällöntuottajan rank - %%rank %%prefix%%" +general.4711="Ylläpitäjän rank - %%rank %%prefix%%" +general.4712="ADMINISTRAATTORI" +general.4713="Administraattorit (eli Adminit) ovat ylläpitäjiä, jotka huolehtivat Hypixelin toiminnasta." +general.4714="Voit auttaa heitä ilmoittamalla virheistä foorumeilla! %%url%%" +general.4715="GAME MASTER" +general.4716="Game Masterit (eli GM:t) ovat ylläpitäjiä, jotka valvovat ja moderoivat Hypixeliä." +general.4717="Voit auttaa heitä käytämällä ilmoitusjärjestelmää! %%command%%" +general.4718="YOUTUBETTAJA" +general.4719="YouTubettajat ovat striimaajia ja videontekijöitä, jotka luovat Hypixeliin liittyvää sisältöä." +general.4720="Saat lisätietoa heistä ja YOUTUBE-rankin vaatimuksista osoitteessa %%url%%" +general.4721="Lisätietoa saat osoitteesta %%url%%" +general.4722="Tuntematon!" +general.4723="Näytä statukset pelille %%game%%" +general.4724="Easter Simulator - Voitot" +general.4725="Easter Simulator - Munia löydetty" +general.4726="Scuba Simulator - Voitot" +general.4727="Scuba Simulator - Esineitä löydetty" +general.4728="Scuba Simulator - Pisteitä yhteensä" +general.4729="Halloween Simulator - Voitot" +general.4730="Halloween Simulator - Karkkeja löydetty" +general.4731="Grinch Simulator - Voitot" +general.4732="Grinch Simulator - Lahjoja varastettu" +general.4733="Suurin osa sopimattomiksi luokitelluista viesteistä suodatetaan" +general.4734="Näet viestejä, joiden sisältö katsotaan sopimattomaksi" +general.4735="Päällä" +general.4736="Tuo pelaaja ei ole enää elossa, pahoittelut!" +general.4737="Kategoriat" +general.4738="Pelinsisäinen kartan valinta" +general.4739="Vaihtaa sitä, avaako \"Pelaa uudestaan?\" -paperi karttavalinnan pelin lopuksi sellaisissa peleissä, jotka sitä tukevat. Tämän ollessa poissa käytöstä se lähettää sinut automaattisesti satunnaiseen karttaan." +general.4740="Vaihda online-tilaasi." +general.4741="SMP-kutsujen yksityisyysasetukset" +general.4742="Muuta sitä, kuka voi lähettää sinulle SMP-kutsuja" +general.4743="Tämän ollessa poissa käytöstä ulkoiset työkalut eivät näe paikalla-tilaasi tai sijaintiasi palvelimella Public APIn kautta." +general.4744="Tämän ollessa poissa käytöstä ulkoiset työkalut eivät näe viimeksi pelaamiasi pelejä Public APIn kautta." +general.4745="Voittoputket" +general.4746="Tämän ollessa poissa käytöstä ulkoiset työkalut eivät näe tietoja voittoputkistasi niitä tukevissa peleissä." +general.4747="Build Battlen kosmeettinen esine" +general.4748="Kurpitsapallo" +general.4749="Kurpitsapommittaja" +general.4750="Tuonpuoleinen" +general.4751="Kurpitsalyhdyt" +general.4752="Paras aikasi: %%time%%" +general.4753="Ei koskaan nollaudu." +general.4754="Joulunajan Event-level -status" +general.4755="Talvipyörre" +general.4756="Jäänpommittaja" +general.4757="Pyörähtelevät lumihiutaleet" +general.4758="Särkyvä jää -sängyntuhoamisefekti" +general.4759="Ritisevä jää" +general.4760="Lahjasade" +general.4761="Pingviinihäkki" +general.4762="Lumiukkohäkki" +general.4763="Vihreä koristehäkki" +general.4764="Punainen koristehäkki" +general.4765="Savupiippu-saarikoriste" +general.4766="Piparkakkutalo-saarikoriste" +general.4767="Joulusukka-saarikoriste" +general.4768="Iso lahja -saarikoriste" +general.4769="Vanukas-saarikoriste" +general.4770="Mukava-tausta" +general.4771="Jäätyneet lohikäärmesiivet -kaapu" +general.4772="Komeettakaapu" +general.4773="Kelkkavempain" +general.4774="Paranna jouluisia rakennuksiasi Build Battle -taustojen avulla!" +general.4775="SINÄ" +general.4776="Joulu" +general.4777="Guildistasi ei löytynyt tietoja." +general.4778="Sinusta ei löytynyt tietoja." +general.4779="Ladataan..." +general.4780="Klikkaa vaihtaaksesi asetuksia!" +general.4781="Vain %%filter%%" +general.4782="Ladataan tulostaulukkoa..." +general.4783="Tästä tulostaulukosta\nei löytynyt tietoja." +general.4784="Ladataan tietojasi..." +general.4785="Hyväksy muutokset" +general.4786="Klikkaa hyväksyäksesi muutokset!" +general.4787="Hylkää muutokset" +general.4788="Sulje valikko hyväksymättä muutoksia!" +general.4789="Tasattu tekstin tasaus toimii oikein vain Minecraftin Vanilla-fonttikoolla." +general.4790="Tämä asetus tallennetaan kaikkiin lobbyihin." +general.4791="Tulostaulukkojen tiedot on tallennettu välimuistiin, eivätkä ne päivity välittömästi." +general.4792="Valitse %%name%%!" +general.4793="%%underline%%Tulostaulukon asetukset" +general.4794="Hylkäsit tulostaulukoiden asetusten muutokset." +general.4795="Hyväksyit tulostaulukoiden asetusten muutokset!" +general.4796="Asetuksesi säilyivät muuttumattomina." +general.4797="Palvelimen tulostaulukot ovat\nväliaikaisesti poissa käytöstä." +general.4798="Parhaiden kavereiden tulostaulukot\novat väliaikaisesti poissa käytöstä." +general.4799="Kaverilistasi on tyhjä.\nKirjoita /f lisätäksesi\npelaajan kavereihisi." +general.4800="Parhaiden kavereiden\nlistasi on tyhjä.\nKirjoita /f best merkitäksesi\nkaverisi parhaaksi kaveriksesi." +general.4801="Tämä ominaisuus toimii vain, jos\nsinulla on enintään %%limit%% parasta kaveria." +general.4802="Kavereiden tulostaulukot ovat\nväliaikaisesti poissa käytöstä." +general.4803="Tämä ominaisuus toimii vain, jos\nsinulla on enintään %%limit%% kaveria." +general.4804="Guildin tulostaulukot ovat\nväliaikaisesti poissa käytöstä." +general.4805="Et ole guildissa." +general.4806="Tämä ominaisuus toimii vain, jos\nguildissasi on enintään %%limit%%\njäsentä." +general.4807="Keskitetty" +general.4808="Tasattu" +general.4809="Aikaväli" +general.4810="Tekstin tasaus" +general.4811="Parhaat kaverit" +general.4812="Guildin jäsenet" +general.4813="Näkymä" +general.4814="Pelaajat" +general.4815="Pelimuoto" +general.4816="Top 10" +general.4817="Pelaajat ympärilläsi" +general.4818="Vastaanotat viestejä siitä, kun kaikki kaverisi tulevat paikalle tai poistuvat." +general.4819="Vastaanotat viestejä siitä, kun parhaat kaverisi tulevat paikalle tai poistuvat." +general.4820="Et vastaanota viestejä siitä, kun kaverisi tulevat paikalle tai poistuvat." +general.4821="Parhaat" +general.4822="Tämä asetus tallennetaan koko palvelimelle." +general.4823="Vasen-/oikeaklikkaa vaihtaaksesi!" +general.4824="Esimerkki: \"Network Boosterisi peliin TNT Games lisättiin jonoon. Se aktivoidaan noin 1 tunnin 12 minuutin kuluttua.\"" +general.4825="Saatavilla vain lobbyissa!" +general.4826="Eniten ansaitut" +general.4827="Vähiten ansaitut" +general.4828="Järjestää saavutukset suoritusprosentin mukaan pienimmästä suurimpaan." +general.4829="Järjestää saavutukset suoritusprosentin mukaan suurimmasta pienimpään." +general.4830="Tapot murhaajana" +general.4831="Viimeistelytapot" +general.4832="Suola" +general.4833="Insane" +general.4834="Nykyinen" +general.4835="Spleef-voitot" +general.4836="Kaikki: Defusal" +general.4837="Kaikki: Deathmatch" +general.4838="Deathmatch-voitot" +general.4839="Teams-voitot" +general.4840="DOM-voitot" +general.4841="EXP" +general.4842="Jänismeteoriitit" +general.4843="Oikeaklikkaa sauvalla luodaksesi valtavia kurpitsoja, jotka tuhoavat kartan." +general.4844="Luo susilauma." +general.4845="Avataan suorittamalla tapahtumakauden %%event%% tehtävä!" +general.4846="Tule myrskyksi ratsastamalla Talvipyörteellä!" +general.4847="Ammu valtava Kurpitsalaser joka tuhoaa kaiken tieltään! Varo, ase potkaisee." +general.4848="Jäniksiä putoaa taivaalta ja räjähtää ympärilläsi!" +general.4849="On aika tehdä lumimyrsky" +general.4850="Jouluilotulitteet" +general.4851="Lyhtyspiraali" +general.4852="Terälehtipuhuri" +general.4853="Aikaan jäädytetty" +general.4854="Nouseva lohikäärme" +general.4855="Kevätnauhat" +general.4856="Tulinen lohikäärme nousee taisteluidesi tuhkista." +general.4857="Jäädytä uhrisi aikaan." +general.4858="Katso, kun uhriesi sielut menevat tuonpuoleiseen." +general.4859="Saa terälehdet kieppumaan tuulessa vihollisesi ympärillä!" +general.4860="Vihollisen tappaminen ampuu lehmän kuun yli." +general.4861="Luo upea esitys taivaalle kieppuen nousevista lyhdyistä." +general.4862="Murskaa jäätä vihollistesi päälle." +general.4863="Saa lahjoja jokaisesta taposta!" +general.4864="Lähetä uhrisi pyörteenä ilmaan." +general.4865="Laukaisee jouluisia ilotulitteita taivaalle!" +general.4866="Laukaise kurpitsoja taivaalle siitä, mihin uhrisi kaatui!" +general.4867="Tappamasi vihollisen sielu erkaantuu hänen kehostaan ja jää lentelemään ympäriinsä!" +general.4868="Liharäjähdys!" +general.4869="Hardcore-selviytymispelejä, joissa on keskiössä vanilla PvP, työstäminen, perkit, kitit ja paljon muuta." +general.4870="Kaveri-ilmoitukset" +general.4871="Kaverit voivat lähettää sinulle SMP-kutsuja." +general.4872="Kukaan ei voi lähettää sinulle SMP-kutsuja." +general.4873="Kuka tahansa voi lähettää sinulle SMP-kutsuja." +general.4874="Klikkaa tästä liittyäksesi %%game%% -peliin!" +general.4875="Avataan Tournament Hallissa!" +general.4876="➤ Käytä satunnaista skiniä." +general.4877="➤ Haluan yhä käyttää omaa skiniäni." +general.4878="Tapahtui virhe komentoa suoritettaessa :(" +general.4879="Ei tietoja." +general.4880="%%days%% päivän kuluttua" +general.4881="Sinulla ei ole vielä tietoja." +general.4882="Sinulla ei ole vielä tietoja." +general.4883="Vuosipäivän ritarivempain" +general.4884="Taimihäkki" +general.4885="Lehmä-saarikoriste" +general.4886="Sadepilvi-saarikoriste" +general.4887="Verso-saarikoriste" +general.4888="Kehitä tappojesi tyyliä tällä TNT Games -kuolemaefektillä!" +general.4889="Tuplahyppää tyylillä tällä TNT Games- tuplahyppyefektillä!" +general.4890="Blitzin kosmeettinen esine" +general.4891="Avaa tämä partikkeliaura erottuaksesi joukosta Blitzissä!" +general.4892="Kehitä tappojesi tyyliä tällä Blitz-viimeistelyefektillä!" +general.4893="Ärsytä vihollisiasi tyylillä tällä Blitz-pilkalla!" +general.4894="Avaa tämä voitontanssi käyttääksesi sitä Blitzissä!" +general.4895="Quaken kosmeettinen esine" +general.4896="Tapa pelaajia tyylillä tällä Quakecraft-säteellä!" +general.4897="Mega Wallsin kosmeettinen esine" +general.4898="Avaa tämä tappoilmoituspaketti käyttääksesi sitä Mega Wallsissa!" +general.4899="Munat-tuplahyppyefekti" +general.4900="Munahdus-kuolemaefekti" +general.4901="Jänislahja" +general.4902="Pääsiäissäde" +general.4903="Loikkivat puput -voitontanssi" +general.4904="Tappajapupupilkka" +general.4905="Värikäs kanasade -voitontanssi" +general.4906="Pupu-tappoilmoitukset" +general.4907="Lohikäärmeen muna -aura" +general.4908="Pääsiäisen Event-level -status" +general.4909="Avataan Tournament Hallissa!" +general.4910="Bingointoilija" +general.4911="Bingointoilija" +general.4912="10 vuotta Hypixeliä" +general.4913="Hyvää 10. vuosipäivää!" +general.4914="Avataan 10:nnen vuosipäivätapahtuman aikana" +general.4915="Event-level %%festival%% %%year%%" +general.4916="Avattavissa eventin %%festival%% %%year%% aikana" +general.4917="Tavalliset tekstistatukset." +general.4918="Statukset, jotka näyttävät yleisiä palvelintilastoja." +general.4919="Statukset, jotka näyttävät tilastoja pelille %%game%%." +general.4920="Erityisin keinoin saadut statukset." +general.4921="Statukset eri kausitapahtumien aikana." +general.4922="∙ Kaikki Classic Games -pelit (paitsi Arena Brawl)" +general.4923="∙ Mega Walls" +general.4924="➤ %%name%% -peli alkaa 30 sekunnin kuluttua! %%click%% liittyäksesi!" +general.4925="Tämä vaatimaton \"Sticks R Us\" -liikkeessä myytävä keppi on oikeasti taikasauva. Se muuten räjäyttää myös asioita." +general.4926="Pupulyhty" +general.4927="Kanat" +general.4928="Onnenjänis" +general.4929="Jänisjuhla" +general.4930="Jäniksen vuosi" +general.4931="Rotan vuosi" +general.4932="BBQ" +general.4933="Röh" +general.4934="Riemuvoitto" +general.4935="#1" +general.4936="Söpö haamu" +general.4937="Söpö kurpitsa" +general.4938="Munakori" +general.4939="Sängyn rikkominen luo paljon pieniä porsaita." +general.4940="Guildin johtaja: %%name%%" +general.4941="Guildin jäseniä: %%count%%" +general.4942="Guildin taso: %%level%%" +general.4943="Guildin kuvaus: \n%%description%%" +general.4944="Pelit:\n%%games%%" +general.4945="Klikkaa pyytääksesi lupaa liittyä!" +general.4946="Olet jo tässä guildissa!" +general.4947="Pyytääksesi liittymistä, sinun on ensin erottava nykyisestä guildistasi!" +general.4948="Klikkaa muuttaaksesi!" +general.4949="Järjestä tulokset" +general.4950="Eniten guildin jäseniä ensin." +general.4951="Vähiten guildin jäseniä ensin." +general.4952="Korkein guildin taso ensin." +general.4953="Pienin guildin taso ensin." +general.4954="Järjestä ilman ilmeistä järjestystä." +general.4955="Tulikehä" +general.4956="Löydä tuli sisältäsi ja lähetä se eteenpäin." +general.4957="Liekkirenkaat" +general.4958="Vesipatsas-sängyntuhoamisefekti" +general.4959="Viljelyvälinepuukko" +general.4960="2023 Kesän Event-level -status" +general.4961="Hypixelin ritari-tunnus -bundle" +general.4962="Hypixelin ritari (punainen) " +general.4963="Hypixelin ritari (sininen)" +general.4964="Salaman isku -tappoääni" +general.4965="Hyökyaaltovempain" +general.4966="Summer Furniture Bundle #1" +general.4967="Flamingokelluke" +general.4968="Rantavahtituoli" +general.4969="Kalastajan kylmälaukku" +general.4970="Kasvihuoneen istutushylly" +general.4971="Hieno rantatuoli" +general.4972="Kesä-kallopakkaus" +general.4973="Trooppiset hiekkarannat -tausta" +general.4974="Aurinkoinen ranta -teema" +general.4975="Ananashäkki" +general.4976="Pirtelöhäkki" +general.4977="Rapu-saarikoriste" +general.4978="Hiekkalinna-saarikoriste" +general.4979="Vesimeloni-saarikoriste" +general.4980="Esittele tyyliäsi murhaajana tällä puukolla!" +general.4981="Laajenna talojesi ympäristöä tämän uskomattoman teeman avulla!" +general.4982="Osta tämä bundle avataksesi useita eri kosmeettisia esineitä!" +general.4983="Sisältää:" +general.4984="Eliminoi vastustajasi tyylillä vaihtamalla, minkä äänen he kuulevat!" +general.4985="Koristele ja lisää yksityiskohtia taloosi tällä kallovalikoimalla!" +general.4986="Järjestää harvinaisuuden mukaan" +general.4987="Kategoria" +general.4988="Järjestetty kosmeettisen esineen pelin tyypin mukaan" +general.4989="EXP yhteensä: %%color%%%%amount%%/%%accentColor%%%%maxAmount%% (%%percent%%)" +general.4990="Hinta: %%silver%% event-silveriä" +general.4991="Tuntematon vuosi" +general.4992="Lisää hieman hohtoa aloitusalueeseesi Duels-pelimuodossa tunnuksen avulla!" +general.4993="Sivu %%number%%" +general.4994="Hinta: %%cost%% event-silveriä" +general.4995="%%cost%% event-silveriä %%discount%%% alennusta!" +general.4996="Turnauksen sijoitus" +general.4997="Kummituskartanoteema" +general.4998="Vampyyripuku" +general.4999="Naamiaisasu" +general.5000="Magma Boss -puku" +general.5001="Päättömän hevosmiehen puku" +general.5002="Yksinäinen majakka -teema" +general.5003="Katedraaliteema" +general.5004="Kurpitsa-asu" +general.5005="Luurankosamurain puku" +general.5006="Halloweenin 2023 Event-level -status" +general.5007="Halloweenin 2022 Event-level -status" +general.5008="Silmämuna-saarikoriste" +general.5009="Karmiva Hypixel -saarikoriste" +general.5010="Karkkikorihäkki" +general.5011="Kummituslinnakehäkki" +general.5012="Endermiten ulkonakö: Dynamiitti" +general.5013="Sankarin asu" +general.5014="Lepakkotyypin kypärä" +general.5015="Halloween Spray/Kill Note paketti #1" +general.5016="Pelottava peli ohi" +general.5017="Hirviö sängyn alla" +general.5018="Kuokkavieras" +general.5019="Kurpitsamaatila" +general.5020="Musta kissa -symboli" +general.5021="Patasymboli" +general.5022="Hautasymboli" +general.5023="Henkiin herätetty maalaus" +general.5024="Luurankotuoli" +general.5025="Kurpitsa karkki moniste" +general.5026="Matkija-arkku" +#general.5027="" # No translation available +general.5028="Luurangon jäännökset" +general.5029="Kirotut liekit" +general.5030="Ulvova tuuli" +general.5031="Hautausmaavempain" +general.5032="Verilepakot" +general.5033="Hämähäkin silkki" +general.5034="pyörremyrsky" +general.5035="Draculan lento" +general.5036="Nappaa tämä upea tarjous vuoden nurmikon asusteesta!" +general.5037="Avaa tämä suihke/tappolappu esitelläksesi sitä eri peleissä!" +general.5038="%%spray%% Spray/Kill Note" +general.5039="Vaihda haarniskasi ulkonäköä tällä esine skinillä!" +general.5040="Käytössä esineessä: %%item%%" +general.5041="Vahvista ostos" +general.5042="Vaihtele vuosittaisten tapahtumateemaisten kosmeettisten esineiden välillä." +general.5043="Näytetään vuosi: %%year%%" +general.5044="Eeppinen lemmikki: Lohi" +general.5045="Legendaarinen lemmikki: Luurankohevosen varsa" +general.5046="Karmiva bingointoilija" +general.5047="Legendaarinen Blaze-kaapu" +general.5048="Osallistu erilaisiin bingokortteihin osana %%festival%% -tapahtumaa! Täytä tavoitteet serverillä ansaitaksesi palkintoja!" +general.5049="Klikkaa nähdäksesi kortit!" +general.5050="%%festival%%bingo" +general.5051="Bingo on tällä hetkellä poissa käytöstä, yritäthän myöhemmin uudelleen!" +general.5052="Bingokortti: %%card%%" +general.5053="Täydennä tavoitteita koko verkossa bingotyylillä ansaitaksesi palkintoja!" +general.5054="%%color%%%%progress%%% suoritettu" +general.5055="Klikkaa nähdäksesi kortin!" +general.5056="%%gameType%% -tehtävä" +general.5057="%%color%%%%festival%%-tehtävä" +general.5058="Vaikeustaso: %%color%%%%difficulty%%" +general.5059="Olet suorittanut tämän tehtävän!" +general.5060="Et ole suorittanut tätä tehtävää vielä!" +general.5061="%%magic%%H Suoritit tehtävän \"%%objective%%\" %%color%%%%card%%Bingokortilta! %%magic%%H" +general.5062="Avattu" +general.5063="Lukittu" +general.5064="Suorita kaikki tehtävät tässä sarjassa saadaksesi seuraavat palkinnot!" +general.5065="Lunastettu!" +general.5066="Klikkaa lunastaaksesi!" +general.5067="%%sequence%% palkinto" +general.5068="Sinun on suoritettava kaikki tehtävät tässä sarjassa avataksesi tämän palkinnon!" +general.5069="Ensimmäisen vaakarivin" +general.5070="Toisen vaakarivin" +general.5071="Kolmannen vaakarivin" +general.5072="Neljännen vaakarivin" +general.5073="Viidennen vaakarivin" +general.5074="Ensimmäisen pystyrivin" +general.5075="Toisen pystyrivin" +general.5076="Kolmannen pystyrivin" +general.5077="Neljännen pystyrivin" +general.5078="Viidennen pystyrivin" +general.5079="Ensimmäisen vinorivin" +general.5080="Toisen vinorivin" +general.5081="Suorita kaikki tehtävät tästä kortista saadaksesi seuraavat palkinnot!" +general.5082="Blackout-palkinto" +general.5083="Sinun on suoritettava kaikki tehtävät tästä kortista saadaksesi tämän palkinnon!" +general.5084="+%%amount%% kolikkoa kaikkiin minipeleihin" +general.5085="+%%amount%% Classic Games -tokenia" +general.5086="Bingoa ei näytä olevan olemassa, ole hyvä ja ilmoita tästä https://hypixel.net/bugs!" +general.5087="Avataan %%event%%bingon aikana" +general.5088="Karmiva bingointoilija" +general.5089="Oikeaklikkaa katsellaksesi esineitä!" +general.5090="Pixel Party" +general.5091="Capture the Wool" +general.5092="Halloween Simulator" +general.5093="Tuo kaikki vastustajen villat tukikohtaasi, mutta varmista samalla että omaa villaasi puolustetaan hyvin!" +general.5094="Capture The Wool" +general.5095="Capture the Wool" +general.5096="Dropper" +general.5097="Halloween Simulator" +general.5098="Pixel Party" +general.5099="Kuurupiilo" +general.5100="Mysteeripölyä saa satunnaisesti pelien pelaamisesta." +general.5101="Avaa ilmaisia palkintoja joka päivä läpi joulun." +general.5102="%%day%%. joulukuuta" +general.5103="TNT Gamesin kosmeettinen esine" +general.5104="Jääpuikko" +general.5105="Holiday Spray/Kill Note Bundle #1" +general.5106="Joulun 2023 Event-level -status" +general.5107="Snowball Spirit Lemmikin ulkoasu" +general.5108="Spirit lemmikki" +general.5109="Pohjantähti ulkoasu" +general.5110="Reput" +general.5111="Muuta reppusi ulkoasua tällä Item ulkoasulla!" +general.5112="Musta lahja ulkoasu" +general.5113="Sininen lahja ulkoasu" +general.5114="Vihreä lahja ulkoasu" +general.5115="Violetti lahja ulkoasu" +general.5116="Kultainen lahja ulkoasu" +general.5117="Valkoinen lahja ulkoasu" +general.5118="Huurteinen seinän väri" +general.5119="Lumijuhlahousut" +general.5120="Männynkäpy-saarikoriste" +general.5121="Luminen mökki -saarikoriste" +general.5122="Mukana toimitettu lumiukkokauppiaan ulkoasu" +general.5123="Huurteinen aseen nimi-Paketti" +general.5124="Firnvale teema" +general.5125="Bear Furniture Bundle" +general.5126="Bear Bench" +general.5127="Bear Bookshelf" +general.5128="Bear Chair" +general.5129="Bear Side Table" +general.5130="Bear Bed" +general.5131="Lumihiutale-viimeistely" +general.5132="Lumiukko-viimeistely" +general.5133="Piparkakku-Jerry" +general.5134="Kauden tervehdys" +general.5135="Jouluyö, juhlayö" +general.5136="Ruma Bed Wars -villapaita" +general.5137="Lumihattu" +general.5138="Pohjan tähti ilmapallo" +general.5139="Kaakaohäkki" +general.5140="Pyrypallohäkki" +general.5141="Jäähdytetty kaksoishyppy Efekti" +general.5142="Paksu jää hattu" +general.5143="Arcade Gamesin kosmeettinen esine" +general.5144="Housingin kosmeettinen esine" +general.5145="Pelimuoto: %%mode%%" +general.5146="Varmista, että näytät parhaalta, kun kaikki räjähtää!" +general.5147="Pue itsesi tuhotaksesi vihollisesi Quakecraftissa" +general.5148="Näytä kuvake tai hymiö viimeistelytappojesi yläpuolella!" +general.5149="Piristä seiniäsi uudella värillä Hole in the Wall -pelissä!" +general.5150="Juhli tyylikkäästi omilla bilepöksyilläsi Pixel Partyssa!" +general.5151="Miten muuten saaresi voisi leijua? Käytä ikiomaa ilmapalloasi!" +general.5152="Surmaa vihollisesi tyylillä käyttämällä mukautettuja aseiden nimiä!" +general.5153="Vaihda kauppiaasi Bed Warsissa kauppias ulkoasuilla" +general.5154="%%cardColor%%%%card%%: %%percentColor%%%%percent%%% suoritettu" +general.5155="Eeppinen lemmikki: Valkoinen jänis (pieni)" +general.5156="Legendaarinen klikkausefekti: Lumi" +general.5157="Legendaarinen lemmikki: Pakkaantunut jää" +general.5158="HELPPO" +general.5159="KESKIVAIKEA" +general.5160="VAIKEA" +general.5161="Mysteeripölytoimitus" +general.5162="Kuukauden ilmainen %%amount%% mysteeripölyä %%month%%lta on saapunut!" +general.5163="Ansaitsit %%amount%% mysteeripölyä!" +general.5164="Olet saavuttanut mysteeripölyrajoituksen!" +general.5165="+%%amount%% event-experienceä (päivittäinen maksimimäärä)" +general.5166="HYPIXELIN %%game%% -turnaus on käynnissä!" +general.5167="Kilpaile, nouse sijoituksissa ja ansaitse ilmaisia palkintoja!" +general.5168="Ansaitse tribuutteja pelaamalla!" +general.5169="Klikkaa TÄSTÄ mennäksesi Tournament Halliin!" +general.5170="Klikkaa liittyäksesi tournament halliin!" +general.5171="HYPIXEL järjestää %%game%% -turnauksen!" +general.5172="Osallistuaksesi, vieraile hallissa %%day%%%%ordinal%% %%month%%ta" +general.5173="Klikkaa TÄSTÄ lukeaksesi ilmoituksen!" +general.5174="Klikkaa näyttääksesi!" +general.5175="Turnauksen yhteenveto" +general.5176="%%type%% – sarja %%bracket%%" +general.5177="MVP: %%player%% %%points%% pisteellä" +general.5178="Ansaitsit (näytä hiirellä!): %%points%%" +general.5179="Ansaitsit: %%points%%" +general.5180="%%underline%%Erittely" +general.5181="%%what%% (x%%occur%%): %%points%% pistettä" +general.5182="Pisteet yhteensä: %%total%% Sijoitus: #%%pos%%" +general.5183="Pisteitä yhteensä: %%total%%" +general.5184="Sarja: %%progress%%" +general.5185="Et ansainnut yhtään tribuuttia tässä pelissä, koska saavutit tribuuttien enimmäismäärän (%%max%%) tähän turnaukseen" +general.5186="Nouse sijoituksissa saadaksesi ylimääräisiä tribuutteja" +general.5187="Et ansainnut yhtään tribuuttia tässä pelissä" +general.5188="Ansaitse tribuutteja voittamalla ja käytä niitä sitten ainutlaatuisiin palkintoihin Tournament Hallissa" +general.5189="Ansaitsit myös: + %%earned_this_game%% tribuuttia" +general.5190="Käytä tribuutteja ainutlaatuisiin palkintoihin!" +general.5191="%%mode%% -TURNAUS" +general.5192="Tämä on sarjan %%bracket%% peli" +general.5193="Pisteet: %%positive%%" +general.5194="%%hours%% h %%mins%% min jäljellä turnauksessa!" +general.5195="Alle tunti jäljellä" +general.5196="Ansaitse pisteitä noustaksesi Turnauksen sijoituksissa!" +general.5197="Vieraile Tournament Hallissa saadaksesi lisää tietoa" +general.5198="Pistettä sarjassa pysymiseksi: %%earned%%/%%required%%" +general.5199="%%before%% säilytetty! (alin sarja)" +general.5200="Olet alimmassa sarjassa,\ntästä ei voi mennä alemmas. :(" +general.5201="%%before%% säilytetty! (paras sarja!)" +general.5202="Olet korkeimmassa sarjassa! Onnittelut!" +general.5203="%%before%% säilytetty!" +general.5204="Sarjalasku! %%before%% ➜ %%after%%" +general.5205="SARJANOUSU! %%before%% ➜ %%after%%" +general.5206="Sarjasi määrittää pelistä\nansaitsemiesi pisteiden määrän." +general.5207="%%points%% turnauspiste" +general.5208="%%points%% turnauspistettä" +general.5209="+%%amount%% tribuuttia (%%reason%%)" +general.5210="Käytä tribuutteja Tournament Hallissa\nsaadaksesi ainutlaatuisia Hypixelin palkintoja!\n\nVoit ansaita jopa %%max%% tribuuttia turnausta kohden.\nOlet ansainnut tähän mennessä %%earned%%!" +general.5211="Nollautuu alle tunnin kuluttua." +general.5212="Nollautuu kuukauden ja 1 vuorokauden kuluttua." +general.5213="Nollautuu kuukauden ja %%days%% vuorokauden kuluttua." +general.5214="Nollautuu %%months%% kuukauden ja 1 vuorokauden kuluttua." +general.5215="Nollautuu %%months%% kuukauden ja %%days%% vuorokauden kuluttua." +general.5216="Nollautuu kuukauden kuluttua." +general.5217="Nollautuu %%months%% kuukauden kuluttua." +general.5218="Nollautuu vuorokauden ja 1 tunnin kuluttua." +general.5219="Nollautuu vuorokauden ja %%hours%% tunnin kuluttua." +general.5220="Nollautuu %%days%% vuorokauden ja 1 tunnin kuluttua." +general.5221="Nollautuu %%days%% vuorokauden ja %%hours%% tunnin kuluttua." +general.5222="Nollautuu vuorokauden kuluttua." +general.5223="Nollautuu %%days%% vuorokauden kuluttua." +general.5224="Nollautuu tunnin kuluttua." +general.5225="Nollautuu %%hours%% tunnin kuluttua." +general.5226="Nollautuu alle tunnin kuluttua" +general.5227="%%fortune%% säteili Jalomielisyyttä, joten sait experience-pussin!" +general.5228="%%fortune%% ja %%fortune1%% säteilivät Jalomielisyyttä, joten sait 2 experience-pussia!" +general.5229="%%amount%% pelaajaa säteili Jalomielisyyttä, joten sait valtavan experience-pussin!" +general.5230="%%amount%% säteili Jalomielisyyttä, joten sait %%amount%% experience-pussia!" +general.5231="+%%amount%% %%game%% %%currencyType%%" +general.5232="Käytä pelin %%game%% %%currencyType%% kolikoita %%game%% -lobbyssa avataksesi päivityksiä ja kosmeettisia esineitä. Arcade-%%currencyType%% voi myös vaihtaa muiden tyyppien %%currencyType%% Arcade-lobbyssa." +general.5233="Käytä %%game%%-%%currencyType%% %%game%% -lobbyssa" +general.5234="Käytä %%game%%-%%currencyType%% %%game%% -lobbyssa avataksesi päivityksiä ja kosmeettisia esineitä" +general.5235="Bunny Bench" +general.5236="Egg Painting Station" +general.5237="Little Chick Tea Table" +general.5238="Little Chick Dresser" +general.5239="Little Chick Bed" +general.5240="Sinulla ei ole varaa tähän!" +general.5241="Osta käyttämällä %%currency%%" +general.5242="Event-silver" +general.5243="Jokin meni vikaan, ilmoitathan tästä!" +general.5244="Tapahtumatuotteiden ostaminen pelikaupoista on tällä hetkellä poissa käytöstä, pahoittelut!" +general.5245="Ei saatavilla juuri nyt!" +general.5246="Tapahtuma: %%color%%%%festival%%" +general.5247="Hinta: %%cost%% / %%silver%% event-silveriä" +general.5248="Kaikki ostettu!" +general.5249="Klikkaa katsellaksesi esineitä!" +general.5250="Tutustu erilaisiin samankaltaisiin kosmetiikkatuotteisiin, joista voit valita!" +general.5251="Valitse, mihin peleihin haluat ostaa tämän kosmeettisen esineen!" +general.5252="Saatavilla olevat pelit:" +general.5253="Avaa tämä kuolemanhuuto käyttääksesi sitä %%gameType%% -peleissä." +general.5254="Avaa tämä kuolinkirkaisu esitelläksesi sitä eri peleissä!" +general.5255="%%deathCry%% -kuolinkirkaisu" +general.5256="Avaa tämä joukko tappoilmoituksia esitelläksesi niitä %%gameType%% -peleissä." +general.5257="Avaa tämä joukko tappoilmoituksia esitelläksesi niitä eri peleissä!" +general.5258="%%killMessages%% -tappoilmoitukset" +general.5259="Avaa tämä tappolappu esitelläksesi sitä %%gameType%% -peleissä." +general.5260="Avaa tämä suihke esitelläksesi sitä %%gameType%% -peleissä." +general.5261="Avaa tämä suihke esitelläksesi sitä eri peleissä!" +general.5262="%%killNote%% -tappolappu" +general.5263="%%killEffect%% -tappoefekti" +general.5264="%%projectileTrail%% -ammusjälki" +general.5265="%%victoryDance%% -voitontanssi" +general.5266="Aloita animaatio omalla animoidulla hatullasi!" +general.5267="Esittele liikkeitäsi ikiomilla eleilläsi." +general.5268="Käytä viimeinen puheenvuorosi näiden viimeisten sanojen avulla!" +general.5269="Juurtunut" +general.5270="Mehiläisten sieppaus" +general.5271="➤ %%name%% -peli odottaa pelaajia! %%click%% liittyäksesi!" +general.5272="%%currency%%: %%color%%%%amount%%" +general.5273="Sinun on oltava vähintään %%rank%% käyttääksesi tätä!" +general.5274="Satunnainen suosikki" +#general.5275="" # No translation available +#general.5276="" # No translation available +general.5277="Energiansaanti" +general.5278="Mahdollistaa energiansaannin lisäämisen tai vähentämisen" +general.5279="0,5x energia" +general.5280="0,75x energia" +general.5281="1x energia" +general.5282="1,5x energia" +general.5283="2x energia" +general.5284="Pelin kesto" +general.5285="Mahdollistaa pelin keston pidentämisen tai lyhentämisen" +general.5286="15 minuuttia" +general.5287="30 minuuttia" +general.5288="45 minuuttia" +general.5289="1 tunti" +general.5290="2 tuntia" +general.5291="Elinvoima" +general.5292="Mahdollistaa elinvoiman lisäämisen tai vähentämisen" +general.5293="0,5x elinvoima" +general.5294="0,75x elinvoima" +general.5295="1x elinvoima" +general.5296="1,5x elinvoima" +general.5297="2x elinvoima" +#general.5298="" # No translation available +#general.5299="" # No translation available +general.5300="Pysyvä hyppytehostus" +general.5301="Pysyvän hyppytehostuksen aktivointi" +general.5302="Pysyvä kylläisyys" +general.5303="Pysyvän kylläisyyden aktivointi" +general.5304="Ikuinen nopeus" +general.5305="Pysyvän nopeuden aktivointi" +general.5306="Pysyvä vahvuus" +general.5307="Pysyvän vahvuuden aktivointi" +general.5308="Valmisteluaika" +general.5309="Mahdollistaa valmisteluajan pidentämisen tai lyhentämisen" +general.5310="Ei valmisteluaikaa" +general.5311="1 minuutti" +general.5312="5 minuuttia" +general.5313="7 minuuttia ja 35 sekuntia" +general.5314="20 minuuttia" +general.5315="Vuorokaudenaika" +general.5316="Mahdollistaa vuorokaudenajan muokkauksen" +general.5317="Aamu" +general.5318="Iltapäivä" +general.5319="Ilta" +general.5320="Yö" +general.5321="Keskiyö" +general.5322="Witherin elinvoima" +general.5323="Mahdollistaa Witherin elinvoiman lisäämisen tai vähentämisen" +general.5324="Ei Withereitä" +general.5325="100 EP" +general.5326="500 EP" +general.5327="1000 EP" +general.5328="1500 EP" +general.5329="Witherin raivon kesto" +#general.5330="" # No translation available +general.5331="Witherit eivät raivostu" +general.5332="10 minuuttia" +general.5333="Tähtisadetikku" +general.5334="Flamingo" +general.5335="Wool Wars - Voitot" +general.5336="Wool Wars - Tapot" +general.5337="Wool Wars - Kuolemat" +general.5338="Wool Wars - Avustukset" +general.5339="Wool Wars - Villaa asetettu" +general.5340="Wool Wars - Palikoita rikottu" +general.5341="Capture the Wool - Tapot" +general.5342="Capture the Wool - Villaa varastettu" +general.5343="Sheep Wars - Voitot" +general.5344="Sheep Wars - Tapot" +general.5345="Lampaita heitetty" +general.5346="Et voi lisätä enempää avainsanoja." +general.5347="Virheellinen komento! Käytä: /block add " +general.5348="Et voi estää itseäsi." +general.5349="Olet jo estänyt tämän pelaajan! /block remove poistaaksesi eston!" +general.5350="Olet saavuttanut estettyjen pelaajien enimmäismäärän! (%%limit%% pelaajaa)" +general.5351="Tapahtui virhe yrittäessä estää tuota pelaajaa!" +general.5352="Et voi estää tätä pelaajaa!" +general.5353="Estettiin pelaaja %%player%%." +general.5354="Estä pelaaja." +general.5355="Hallinnoi estolistaasti." +general.5356="Et voi käyttää tätä vielä! Ole hyvä ja yritä myöhemmin uudelleen." +general.5357="Tuntematon muuttuja '%%arg%%'!" +#general.5358="" # No translation available +#general.5359="" # No translation available +#general.5360="" # No translation available +general.5361="Sivunumeron tulee olla positiivinen!" +general.5362="En tiedä kuinka käsitellä sivunumeroa %%number%%!" +#general.5363="" # No translation available +general.5364="------ Ei estettyjä pelaajia ------" +#general.5365="" # No translation available +general.5366="sivu" +general.5367="Luettele estetyt pelaajat." +general.5368="Poista esto kaikilta pelaajilta." +general.5369="Mitään ei tapahtunut." +general.5370="Olet poistamassa eston KAIKILTA estämiltäsi pelaajilta. Oletko varma, että haluat tehdä tämän?" +general.5371="PERUUTA" +general.5372="Klikkaa peruuttaaksesi ja pitääksesi pelaajan estettynä." +general.5373="TYHJENNÄ ESTETTYJEN PELAAJIEN LISTA" +general.5374="Klikkaa tyhjentääksesi estettyjen pelaajien listasi." +general.5375="Odotathan ennen kuin teet tuon uudestaan." +#general.5376="" # No translation available +general.5377="Et ole estänyt yhtäkään pelaajaa." +#general.5378="" # No translation available +general.5379="Poistettiin kaikki estetyt pelaajat." +general.5380="Virheellinen käyttö! Käyttö: /block remove " +general.5381="Pelaajaa ei löytynyt!" +general.5382="Odottamaton virhe tapahtui yrittäessä poistaa estoa." +general.5383="Et ole estänyt tätä pelajaa." +#general.5384="" # No translation available +#general.5385="" # No translation available +#general.5386="" # No translation available +general.5387="Poista esto pelaajalta." +#general.5388="" # No translation available +#general.5389="" # No translation available +general.5390="Estä pelaaja" +general.5391="Klikkaa lisätäksesi pelaaja %%player%% estettyjen listallesi." +#general.5392="" # No translation available +#general.5393="" # No translation available +#general.5394="" # No translation available +#general.5395="" # No translation available +#general.5396="" # No translation available +#general.5397="" # No translation available +#general.5398="" # No translation available +#general.5399="" # No translation available +#general.5400="" # No translation available +#general.5401="" # No translation available +#general.5402="" # No translation available +#general.5403="" # No translation available +#general.5404="" # No translation available +#general.5405="" # No translation available +#general.5406="" # No translation available +#general.5407="" # No translation available +#general.5408="" # No translation available +#general.5409="" # No translation available +#general.5410="" # No translation available +#general.5411="" # No translation available +#general.5412="" # No translation available +#general.5413="" # No translation available +#general.5414="" # No translation available +#general.5415="" # No translation available +general.5416="KÄYTÖSSÄ" +general.5417="POISSA KÄYTÖSTÄ" +general.5418="Kuka tahansa" +#general.5419="" # No translation available +general.5420="EI AKTIIVINEN" +general.5421="KÄYTÖSSÄ" +general.5422="Vaihtoehdot:" +general.5423="Julkisen chatin kirosanasuodatin" +#general.5424="" # No translation available +#general.5425="" # No translation available +#general.5426="" # No translation available +general.5427="Guildin Kirosanasuodatin" +#general.5428="" # No translation available +#general.5429="" # No translation available +#general.5430="" # No translation available +#general.5431="" # No translation available +#general.5432="" # No translation available +general.5433="Muuta, kuka voi lähettää sinulle yksityisviestiä." +#general.5434="" # No translation available +#general.5435="" # No translation available +#general.5436="" # No translation available +general.5437=" Ruoka: %%food%%%" +#general.5438="" # No translation available +#general.5439="" # No translation available +#general.5440="" # No translation available +#general.5441="" # No translation available +#general.5442="" # No translation available +#general.5443="" # No translation available +#general.5444="" # No translation available +#general.5445="" # No translation available +#general.5446="" # No translation available +general.5447="Bingo" +#general.5448="" # No translation available +#general.5449="" # No translation available +#general.5450="" # No translation available +#general.5451="" # No translation available +#general.5452="" # No translation available +#general.5453="" # No translation available +#general.5454="" # No translation available +#general.5455="" # No translation available +#general.5456="" # No translation available +#general.5457="" # No translation available +#general.5458="" # No translation available +#general.5459="" # No translation available +#general.5460="" # No translation available +#general.5461="" # No translation available +#general.5462="" # No translation available +#general.5463="" # No translation available +#general.5464="" # No translation available +#general.5465="" # No translation available +#general.5466="" # No translation available +#general.5467="" # No translation available +#general.5468="" # No translation available +#general.5469="" # No translation available +#general.5470="" # No translation available +#general.5471="" # No translation available +#general.5472="" # No translation available +#general.5473="" # No translation available +#general.5474="" # No translation available +general.5475="Vaikeustaso: %%difficulty%%" +general.5476="Harvinaisuus: %%rarity%%" +#general.5477="" # No translation available +#general.5478="" # No translation available +#general.5479="" # No translation available +#general.5480="" # No translation available +#general.5481="" # No translation available +#general.5482="" # No translation available +#general.5483="" # No translation available +general.5484="Roihukaapu" +#general.5485="" # No translation available +general.5486="Lumi-klikkausefekti" +#general.5487="" # No translation available +#general.5488="" # No translation available +#general.5489="" # No translation available +general.5490="Höyhenpeitekaapu" +#general.5491="" # No translation available +#general.5492="" # No translation available +#general.5493="" # No translation available +#general.5494="" # No translation available +#general.5495="" # No translation available +#general.5496="" # No translation available +#general.5497="" # No translation available +#general.5498="" # No translation available +#general.5499="" # No translation available +#general.5500="" # No translation available +#general.5501="" # No translation available +#general.5502="" # No translation available +#general.5503="" # No translation available +#general.5504="" # No translation available +#general.5505="" # No translation available +#general.5506="" # No translation available +#general.5507="" # No translation available +#general.5508="" # No translation available +#general.5509="" # No translation available +#general.5510="" # No translation available +#general.5511="" # No translation available +#general.5512="" # No translation available +#general.5513="" # No translation available +#general.5514="" # No translation available +#general.5515="" # No translation available +#general.5516="" # No translation available +#general.5517="" # No translation available +#general.5518="" # No translation available +#general.5519="" # No translation available +general.5520="Foorumit" +#general.5521="" # No translation available +general.5522="Hiekkalinna" +general.5523="Kahen kilon siika" +#general.5524="" # No translation available +#general.5525="" # No translation available +#general.5526="" # No translation available +general.5527="Haku" +general.5528="Klikkaa etsiäksesi!" +#general.5529="" # No translation available +#general.5530="" # No translation available +general.5531="Aloitus Miekka" +#general.5532="" # No translation available +general.5533="Puun tyyli" +general.5534="Puun tyylit" +#general.5535="" # No translation available +general.5536="Kultainen miekka" +#general.5537="" # No translation available +#general.5538="" # No translation available +general.5539="Tammilankut" +general.5540="Kuusilankut" +general.5541="Koivulankut" +general.5542="Viidakkopuulankut" +general.5543="Akasialautoja" +general.5544="Tummat tammilaudat" +general.5545="Tammihalot" +general.5546="Kuusihalot" +general.5547="Koivuhalot" +general.5548="Viidakkopuuhalot" +general.5549="Akaasiahalot" +general.5550="Tummat tammihalot" +#general.5551="" # No translation available +#general.5552="" # No translation available +#general.5553="" # No translation available +#general.5554="" # No translation available +#general.5555="" # No translation available +#general.5556="" # No translation available +#general.5557="" # No translation available +#general.5558="" # No translation available +#general.5559="" # No translation available +#general.5560="" # No translation available +#general.5561="" # No translation available +#general.5562="" # No translation available +general.5563="Kummitustalo" +#general.5564="" # No translation available +#general.5565="" # No translation available +general.5566="Ouija" +#general.5567="" # No translation available \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/general_goliath.properties b/configuration/i18n/fi_FI/official/general_goliath.properties new file mode 100644 index 000000000..8b816fa02 --- /dev/null +++ b/configuration/i18n/fi_FI/official/general_goliath.properties @@ -0,0 +1,790 @@ +general_goliath.0="En löytänyt yhtään JULKISIA viestejä tältä pelaajalta viimeisen 10 minuutin ajalta!" +general_goliath.1="Chat-ilmiantosi on siirretty henkilökunnan tarkistettavaksi. Kiitos! :)" +general_goliath.2="Sinulla ei ole yhtään odottavia chat-ilmiantoja!" +general_goliath.3="Käytä: /chatreport (pelaajan nimi)" +general_goliath.4="En löytänyt ketään tällä nimellä. Tarkastathan oikeinkirjoituksen!" +general_goliath.5="Et voi ilmiantaa itseäsi!" +general_goliath.6="Ole hyvä, ja avaa uusi tukipyyntö todisteiden kanssa!" +general_goliath.7="Ole hyvä, ja kirjoita /chatreport confirm kirjataksesi pelaajan %%player_name%% viimeisimmät JULKISET viestit henkilökunnan tarkistukseen." +general_goliath.8="Ilmiantoja pelaajaa %%player_name%% vastaan on jo olemassa" +general_goliath.9="Pelaajasta %%player_name%% tehdyn ilmiannon prioriteetti on jo valmiiksi korkea!" +general_goliath.10="Korotettiin pelaajasta %%player_name%% tehdyn ilmiannon prioriteettia!" +general_goliath.11="CHAT-ILMIANTO" +general_goliath.12="VAROITUS" +general_goliath.13="Ole hyvä, ja pidä viestisi asianmukaisena ja noudata sääntöjämme. Mikäli jatkat sääntöjemme rikkomista, sinut voidaan hiljentää tai sinulle voidaan antaa antaa porttikielto. Lista säännöistämme löytyy sivulta https://hypixel.net/rules" +general_goliath.14="Ilmiantosi pelaajaa %%player_name%% vastaan on vastaanotettu! Kiitos avustasi!" +general_goliath.15="Kiitos ilmiannostasi. Ymmärrämme huolesi, mutta tällä hetkellä emme voi tehdä tämän suhteen mitään." +general_goliath.16="Tarvitsemme lisää todisteita pelaajaa %%player_name%% koskevaan ilmiantoosi! Ole hyvä, ja avaa ilmianto osoitteessa https://hypixel.net/report" +general_goliath.17="Henkilökunnan jäsen on korottanut pelaajasta %%player_name%% tekemäsi ilmiannon prioriteettia!" +general_goliath.18="Mystery %%plural%%" +general_goliath.19="Box" +general_goliath.20="Boxit" +general_goliath.21="%%amount%% mysteeripölyä" +general_goliath.22="Lunastit %%plural%% %%reward%%!" +general_goliath.23="palkinnon" +general_goliath.24="palkinnon" +general_goliath.25="Guild-komennot:" +general_goliath.26="Näyttää tämän ohjeviestin" +general_goliath.27="Guild-kutsu pelaajalta %%name%% on vanhentunut" +general_goliath.28="Guild-kutsu pelaajalle %%player%% on vanhentunut" +general_goliath.29="Guild-kutsut pelaajille %%players%% ovat vanhentuneet" +general_goliath.30="Liittymispyyntö guildiin %%name%% on vanhentunut" +general_goliath.31="Liittymispyynto pelaajalta %%player%% on vanhentunut" +general_goliath.32="Liittymispyynnöt pelaajilta %%players%% ovat vanhentuneet" +general_goliath.33="Emme löytäneet guildia vanhan ID:n mukaan!" +general_goliath.34="" +general_goliath.35="Tuo viesti on liian pitkä!" +general_goliath.36="Lähetät viestejä liian nopeasti! Hidasta vähän!" +general_goliath.37="Lähetät viestejä liian nopeasti! Sinun on odotettava %%time%% viestien välillä." +general_goliath.38="Et ole guildissa!" +general_goliath.39="Et ole guildissa joten sinut siirrettiin kanavalle %%channel%%!" +general_goliath.40="Guildisi chatti on mykistettynä %%time%%!" +general_goliath.41="Sinut on guild-hiljennetty vielä %%time%%!" +general_goliath.42="Et voi lähettää guild-chattiin viestejä kun sinulla on guild-chat poissa päältä! Käytä komentoa %%command%% laittaaksesi sen päälle!" +general_goliath.43="/g toggle" +general_goliath.44="Sihteeri" +general_goliath.45="Guild" +general_goliath.46="Klikkaa näyttääksesi pelaajan %%player%% profiili" +general_goliath.47="/guild accept " +general_goliath.48="Sinut kutsuttiin seuraaviin guildeihin kun et ollut paikalla: %%guilds%%" +general_goliath.49="Kutsusi guildiin \"%%guild%%\" hylättiin, koska tämä guild on täynnä!" +general_goliath.50="Liityit guildiin %%guild%%!" +general_goliath.51="GUILD-TEHTÄVÄ VALMIS!" +general_goliath.52="Guild on suorittanut tämän viikon tehtävän!" +general_goliath.53="GUILD-TEHTÄVÄN TASO %%tier%% VALMIS!" +general_goliath.54="Guild on suorittanut tason %%tier%% tämän viikon tehtävästä!" +general_goliath.55="+%%amount%% Guild Experienceä" +general_goliath.56="Sait %%multiplier%%x Guild Exp guildisi kirikertoimen vuoksi." +general_goliath.57="TASON NOUSU!" +general_goliath.58="Guild on noussut tasolle %%level%%!" +general_goliath.59="SAAVUTUS AVATTU" +general_goliath.60="Guild on ansainnut saavutuksen %%achievement%% %%tier%%!" +general_goliath.61="%%player%% antoi Guildin johtajuuden pelaajalle %%newPlayer%%" +general_goliath.62="Jokin meni vikaan yrittäessä vaihtaa guildin omistajaa! Ilmoitathan seuraavan: (Error: gtransfer-nodef)" +general_goliath.63="%%player%% lakkautti guildin." +general_goliath.64="Guildisi nimi saa olla enintään %%char%% merkkiä pitkä!" +general_goliath.65="Guildisi nimessä ei voi olla [TUNNISTEITA]!" +general_goliath.66="Guild nimellä %%guild%% on jo olemassa!" +general_goliath.67="Poista hiljennys pelaajalta tai koko guildilta" +general_goliath.68="" +general_goliath.69="Guildisi ei ole mykistettynä!" +general_goliath.70="%%sender%% on poistanut Guild-chatin mykistyksen!" +general_goliath.71="%%sender%% poisti hiljennyksen pelaajalta %%name%%" +general_goliath.72="Hiljennyksesi poistettiin!" +general_goliath.73="Tämä pelaaja ei ole hiljennetty!" +general_goliath.74="Et voi siirtää Guildin omistusta itsellesi!" +general_goliath.75="%%player%% ei voi olla Guildin johtaja sillä hän ei ole VIP+" +general_goliath.76="================== VAROITUS ==================\nTämä antaa Guildin omistuksen JOLLEKIN MUULLE. Tätä ei voi kumota.\nJos haluat varmasti jatkaa, tee /guild confirm seuraavan 10 sekunnin aikana." +general_goliath.77="Siirtää guildin omistuksen toiselle pelaajalle" +general_goliath.78="Piilotit guild-chatin!" +general_goliath.79="Asetit guild-chatin näkyviin!" +general_goliath.80="Piilota guild-chat itseltäsi" +general_goliath.81="Sinulla ei ole lupaa tähän." +general_goliath.82="Et ole saanut vielä yhtään Guildin tunnisteen väriä! Voit saada niitä ansaitsemalla Guild Experienceä ja näin nostamalla Guildin tasoa." +general_goliath.83="Virheellinen komento! Ohje: /guild tag HYP tai /guild tag reset" +general_goliath.84="Guildin [TUNNISTE] voi olla enintään %%length%% merkkiä pitkä!" +general_goliath.85="Guildin [TUNNISTEESSA] saa olla vain kirjaimia tai numeroita!" +general_goliath.86="Tuo [TUNNISTE[ sisältää kiellettyjä sanoja!" +general_goliath.87="%%player%% asetti guildin tunnisteeksi [%%tag%%]! Saatat joutua vaihtamaan lobbya päivittääksesi sen." +general_goliath.88="Asettaa guildin [TUNNISTEEN]" +general_goliath.89="Guildisi on oltava ainakin tasolla %%level%% asettaaksesi tunnisteen!" +general_goliath.90="%%player%% vaihtoi guild tunnisteen väriksi %%color%%! Saatat joutua vaihtamaan lobbya päivittääksesi sen." +general_goliath.91="Guildisi ei ole avannut vielä yhtään tunnisteen väriä!" +general_goliath.92="Voit asettaa Guildin tunnisteen väriksi minkä tahansa seuraavista:" +general_goliath.93="Klikkaa asettaaksesi Guildin tunnisteen väriksi %%color%%" +general_goliath.94="Klikkaa väriä valitaksesi sen." +general_goliath.95=" Guild > %%name%% poisti guild-chatin viiveen!" +general_goliath.96=" Guild > %%name%% asetti guild-chatin viiveen päälle. Voit puhua vain kymmenen sekunnin välein" +general_goliath.97="Aseta guild-chatin viive, joka vaatii jäseniä odottamaan 10 sekuntia viestien välissä" +general_goliath.98="Guildin kauppa ei ole enää saatavilla. Kaikki aikaisemmat edut ovat nyt kaikille ilmaisia." +general_goliath.99="Näytä Guildin kauppa" +general_goliath.100="Virheellinen arvo '%%value%%'! Arvon pitäisi olla \"true\" (kyllä) tai \"false\" (ei)" +general_goliath.101="%%player%% asetti vaihtoehdon %%option%% päälle." +general_goliath.102="%%player%% asetti vaihtoehdon %%option%% pois päältä." +general_goliath.103="%%player%% vaihtoi Guildin kuvaukseksi %%description%%" +general_goliath.104="Pahoittelut, en tunnistanut tuota peliä!" +general_goliath.105="%%player%% poisti pelin %%game%% guildisi peleistä." +general_goliath.106="%%player%% lisäsi pelin %%game%% guildin peliksi." +general_goliath.107="Vain Guildin johtaja voi käyttää tätä" +general_goliath.108="Asetukset:" +general_goliath.109=" " +general_goliath.110="Muuta guildin asetuksia" +general_goliath.111="Guildin listaaminen julkiseksi. Tämä antaa pelaajille mahdollisuuden liittyä kutsutta." +general_goliath.112="Muuta Guild-etsimessä näkyvää Guildin kuvausta." +general_goliath.113="Guildin näkyvyys" +general_goliath.114="Guildin pelit" +general_goliath.115="Aseta Guildin suosikkipelit. Antaa uusille pelaajille mahdollisuuden löytää guild, jonka jäsenet pelaavat heidän lempipelejään." +general_goliath.116="%%player%% vaihtoi guildin nimeksi %%name%%!" +general_goliath.117="Vaihtaa Guildin nimeä" +general_goliath.118="Guild-tehtävän edistyminen" +general_goliath.119="Tehtävän suorittamiseksi on Guildin jäsenten suoritettava haasteita missä tahansa pelissä." +general_goliath.120="Palkinto: %%amount%% Guild Experienceä jokaisesta tasosta" +general_goliath.121="Antaa tietoa tämänhetkisestä Guild-tehtävästä" +general_goliath.122="%%player%% ei ole guildisi jäsen!" +general_goliath.123="%%player%% on Guildin johtaja, joten häntä ei voi ylentää enempää!" +general_goliath.124="Et ole luonut yhtään arvonimeä! Luo arvonimiä komennolla %%command%%!" +general_goliath.125="Pelaajalla %%name%% on jo korkein luomasi arvonimi!" +general_goliath.126="Voit ylentää vain omaan arvonimeesi asti!" +general_goliath.127="Et voi ylentää itseäsi!" +general_goliath.128="%%player%% ylennettiin arvonimeltä %%oldRank%% arvonimelle %%rank%%" +general_goliath.129="Ylentää pelaajan seuraavalle arvonimelle" +general_goliath.130="Muokkaa arvonimen oikeuksia" +general_goliath.131="Guild Party" +general_goliath.132="Luo partyn paikalla olevista Guildisi jäsenistä" +general_goliath.133="Guildin online-tila asetettiin pois päältä!" +general_goliath.134="Guildin online-tila asetettiin päälle!" +general_goliath.135="Määritä näkyvätkö poissa olevat pelaajat guildin pelaajalistassa." +general_goliath.136="Guildin nimi: %%name%%" +general_goliath.137="Jäsenmäärä: %%total%%" +general_goliath.138="Paikalla olevat jäsenet: %%online%%" +general_goliath.139="Poissa olevat jäsenet: %%offline%%" +general_goliath.140="Näyttää paikalla olevat guildin jäsenet" +general_goliath.141="Sinulla ei ole pääsyä sihteerien chattiin!" +general_goliath.142="Lähetä viesti sihteerien chattiin" +general_goliath.143="Liittymis- ja poistumisviestit piilotetaan!" +general_goliath.144="Liittymis- ja poistumisviestit näytetään!" +general_goliath.145="Muuta guildin liittymis- ja poistumisviestien näkyvyyttä" +general_goliath.146="Hiljennä pelaaja tai koko guild" +general_goliath.147=" " +general_goliath.148="Väärä aikamuoto! Kokeile %%example%%" +general_goliath.149="7D, 1D, 6H, 1H" +general_goliath.150="Et voi asettaa hiljennystä alle minuutiksi" +general_goliath.151="Et voi asettaa hiljennystä yli kuukaudeksi" +general_goliath.152="%%sender%% on mykistänyt Guild-chatin ajaksi %%time%%" +general_goliath.153="Guildin chatti on mykistetty %%time%% ajan" +general_goliath.154="Et voi hiljentää guildin johtajaa!" +general_goliath.155="Et voi hiljentää itseäsi!" +general_goliath.156="Tämä pelaaaja on jo hiljennetty!" +general_goliath.157="%%name%% on guild-hiljentänyt sinut ajaksi %%time%%" +general_goliath.158="Guild tervetuloviestin komennot:" +general_goliath.159="Guildin tervetuloviesti" +general_goliath.160="Guildin tervetuloviestin esikatselu" +general_goliath.161="Muokkaa Guildin tervetuloviestiä" +general_goliath.162="Sinulla ei ole tervetuloviestiä! Käytä komentoa /guild motd add lisätäksesi sellaisen!" +general_goliath.163="Listaa tervetuloviestin rivit" +general_goliath.164="Rivinumeron on oltava suurempi kuin 0!" +general_goliath.165="Asetettu rivin #%%line%% tekstiksi '%%message%%'!" +general_goliath.166="Riviä #%%line%% ei ole olemassa! Kokeile komentoa /guild motd add" +general_goliath.167="Virheellinen rivinumero '%%line%%'!" +general_goliath.168="Lisää rivin tervetuloviestiin" +general_goliath.169="Guildin tervetuloviestissä saa olla vain %%lines%% riviä!" +general_goliath.170="Tarkastele miltä tervetuloviesti tulee näyttämään pelaajille" +general_goliath.171="Guildin tervetuloviestiä ei ole!" +general_goliath.172="Guildin tervetuloviesti tyhjennetty" +general_goliath.173="Tyhjentää tervetuloviestin" +general_goliath.174="Listaa guildisi jäsenet" +general_goliath.175="Asettaa tervetuloviestin rivin" +general_goliath.176="Asetettu rivin #%%line%% tekstiksi '%%message%%'!" +general_goliath.177="" +general_goliath.178="Avaa Guildin valikon" +general_goliath.179="%%player%% ei ole guildisi jäsen!" +general_goliath.180="Arvonimi: %%rank%%" +general_goliath.181="Liittyi: %%date%%" +general_goliath.182="Arvonimeä muutti viimeksi: %%by%%" +general_goliath.183="Arvonimeä muutettiin viimeksi: %%date%%" +general_goliath.184="Guild Exp -osallistuminen:" +general_goliath.185="Tänään: " +general_goliath.186="Olet Guildin johtaja! Et voi poistua ennen kuin käytät komentoa /guild disband tai /guild tranfer!" +general_goliath.187="Poistuit guildista." +general_goliath.188="%%player%% poistui guildista!" +general_goliath.189="Poistu nykyisestä guildistasi" +general_goliath.190="Et voi potkia itseäsi guildista!" +general_goliath.191="Poistaa pelaajan guildista" +general_goliath.192="Et voi poistaa pelaajaa %%player%% koska hän on %%rank%%!" +general_goliath.193="Et voi poistaa pelaajaa %%player%% koska hän on %%rank%%!" +general_goliath.194="Sinulla ei ole oikeuksia poistaa jäseniä guildista!" +general_goliath.195="%%player%%poisti sinut guildista. Syy: '%%reason%%'" +general_goliath.196="%%kicker%% poisti pelaajan %%player%% guildista!" +general_goliath.197="Pyydä lupaa liittyä tiettyyn guildiin" +general_goliath.198=" " +general_goliath.199="Emme löytäneet pelaajaa tai guildia jonka nimi on '%%search%%'!" +general_goliath.200="Pyysit lupaa liittyä guildiin %%name%%! Heillä on 5 minuuttia aikaa hyväksyä!" +general_goliath.201="Olet jo pyytänyt lupaa liittyä guildiin %%name%%! Odota että he hyväksyvät!" +general_goliath.202="Tällä Guildilla on liittymispyynnöt poissa päältä! Pyydä Guildin johtajalta, %%master%%, kutsua!" +general_goliath.203="%%inviter%% on pyytänyt lupaa liittyä Guildiin!\n" +general_goliath.204="Klikkaa tästä hyväksyäksesi tai kirjoita /guild accept %%acceptName%%!" +general_goliath.205="Klikkaa käyttääksesi komentoa\n/guild accept %%player%%" +general_goliath.206="Sinulla ei ole oikeuksia kutsua pelaajia!" +general_goliath.207="Et voi kutsua tätä pelaajaa guildiisi!" +general_goliath.208="%%player%% on jo guildisi jäsen!" +general_goliath.209="Guildisi on täynnä!" +general_goliath.210="%%player%% on jo toisessa guildissa!" +general_goliath.211="" +general_goliath.212="%%inviter%% kutsui sinut guildiinsa %%guild%%!" +general_goliath.213="Klikkaa tästä hyväksyäksesi tai kirjoita /guild accept %%master%%!" +general_goliath.214="Kutsuu pelaajan guildiin" +general_goliath.215="Kutsuit pelaajan %%player%% guildiisi. Hänellä on 5 minuuttia aikaa hyväksyä." +general_goliath.216="%%inviter%% kutsui sinut guildiinsa, jonka nimi on %%guild%%! Käytä komentoa /guild accept %%master%% hyväksyäksesi kutsun!" +general_goliath.217="Lähetit offline-kusun pelaajalle %%player%%! Kun hän liittyy Hypixeliin, hänellä tulee olemaan viisi minuuttia aikaa hyväksyä kutsu." +general_goliath.218="Luotu: %%date%%" +general_goliath.219="Jäsenet: %%members%%/%%max%%" +general_goliath.220="Kuvaus: %%description%%" +general_goliath.221="ei asetettu" +general_goliath.222="Tervetuloviestiä muokattiin viimeksi: tuntematon" +general_goliath.223="Tervetuloviestiä muokkasi viimeksi %%player%%, %%date%%" +general_goliath.224="Guild Exp: %%exp%%" +general_goliath.225="Guildin taso: %%level%% (%%percent%%%%%aqua%% tasolle %%plusOne%%)" +general_goliath.226="Näyttää informaatiota guildistasi" +general_goliath.227="Virheellinen komento, kokeile jotain seuraavista:\n/guild history\n/guild log (sivunumero)" +general_goliath.228="'%%input%%' ei ole hyväksyttävä sivunumero." +general_goliath.229="Mitään ei ole tapahtunut hiljattain." +general_goliath.230="Sivun on oltava väliltä 1-%%page%%." +general_goliath.231="24 tunnin Guild-historia (Sivu %%page%%/%%max%%)" +general_goliath.232="Katso tapahtumat viimeiseltä 24 tunnilta" +general_goliath.233="Guildillasi ei ole Discord-kutsua!" +general_goliath.234="Vaihtaaksesi linkkiä, käytä komentoa /guild discord (kutsulinkki) tai komentoa /guild discord reset jos haluat poistaa sen." +general_goliath.235="Tuo ei näytä olevan toimiva Discord kutsulinkki!" +general_goliath.236="%%player%% päivitti Guildin Discord-kutsulinkin." +general_goliath.237="Aseta tai tarkastele guildin Discord-linkkiä" +general_goliath.238="Lakkauttaa guildin" +general_goliath.239="%%player%% on Guildin johtaja, joten häntä ei voi ylentää enempää!" +general_goliath.240="Pelaajalla %%name%% on jo alin luomasi arvonimi!" +general_goliath.241="Voit alentaa vain omaan arvonimeesi asti!" +general_goliath.242="Et voi alentaa itseäsi!" +general_goliath.243="%%player%% alennettiin arvonimeltä %%oldRank%% arvonimelle %%rank%%" +general_goliath.244="Alentaa pelaajan edelliselle arvonimelle" +general_goliath.245="Sinun on oltava VIP+ luodaksesi guildin!\nVoit kuitenkin liittyä toisten guildeihin!" +general_goliath.246="Sinulla on oltava rankki jos haluat luoda guildin!\nVoit kuitenkin liittyä toisten guildeihin!" +general_goliath.247="Loit guildin nimellä %%guild%%!" +general_goliath.248="Luo guildin annetulla nimellä" +general_goliath.249="nimi" +general_goliath.250="Et käyttänyt vahvistuskomentoa, tai komento vanhentui!" +general_goliath.251="Sinun on oltava pelaaja käyttääksesi tätä komentoa!" +general_goliath.252="Sinun on oltava guildin jäsen käyttääksesi tätä komentoa!" +general_goliath.253="Sinun on oltava Guildin johtaja käyttääksesi tätä komentoa!" +general_goliath.254="Sinun Guild-arvonimelläsi ei ole oikeuksia käyttää tätä!" +general_goliath.255="Sinun on ostettava %%upgrade%% kaupasta! Kaupan saa auki kirjoittamalla: /guild shop!" +general_goliath.256="Olet jo guildissa!" +general_goliath.257="Tapahtui virhe käyttäessäsi tuota komentoa! Ilmoitathan tästä ylläpidolle!" +general_goliath.258="Sinulla ei ole oikeuksia littyä tuolle palvelimelle!" +general_goliath.259="Ei löydetty pelaajaa nimellä '%%name%%'" +general_goliath.260="Tuo pelaaja ei ole paikalla!" +general_goliath.261="%%player%% ei ole paikalla!" +general_goliath.262="Tuo pelaaja on lisännyt sinut hänen estettyjen pelaajien listalleen!" +general_goliath.263="Virheellinen komento! '/%%command%%" +general_goliath.264="Lähetä viesti guildin chat-kanavalle" +general_goliath.265="Virheellinen komento, kokeile jotain seuraavista:\n/guild log\n/guild log (sivunumero)\n/guild log (pelaajan nimi)\n/guild log (pelaajan nimi) (sivunumero)" +general_goliath.266="Ei näytettäviä tietoja." +general_goliath.267="Guild Log (Sivu %%page%%/%%max%%)" +general_goliath.268="Guild Log jäsenelle %%user%% (Sivu %%page%%/%%max%%)" +general_goliath.269="asetti pelaajalle %%player%% arvonimen %%rank%%" +general_goliath.270="loi guildin" +general_goliath.271="lakkautti guildin" +general_goliath.272="kutsui pelaajan %%player%%" +general_goliath.273="liittyi" +general_goliath.274="potki pelaajan %%player%% : \"%%details%%\"" +general_goliath.275="poistui" +general_goliath.276="asetti arvon \"%%details%%\" asetukselle %%target%%" +general_goliath.277="siirsi omistajuuden pelaajalle %%player%%" +general_goliath.278="mykisti guild-chatin ajaksi %%details%%" +general_goliath.279="poisti guild-chatin mykistyksen" +general_goliath.280="hiljensi pelaajan %%player%% ajaksi %%details%%" +general_goliath.281="poisti hiljennyksen pelaajalta %%name%%" +general_goliath.282="asetti chatin viiveeksi %%details%% " +general_goliath.283="loi arvonimen %%details%%" +general_goliath.284="poisti arvonimen %%details%%" +general_goliath.285="Katsele tarkastuslokia" +general_goliath.286="Guild on täynnä" +general_goliath.287="%%player%% ei ole kutsunut sinua guildiin, tai kutsu on vanhentunut!" +general_goliath.288="Tuo guild on täynnä!" +general_goliath.289="Liityit guildiin %%name%%!" +general_goliath.290="%%player%% liittyi guildiin!" +general_goliath.291="Hyväksyy guild-kutsun" +general_goliath.292="Tarkastele rankkisi oikeuksia" +general_goliath.293="Et näytä olevan tämän guildin jäsen!" +general_goliath.294="Sinun rankilläsi ei ole yhtään oikeuksia!" +general_goliath.295="Listaa guildin jäsenet jotka ovat ansainneet eniten experienceä" +general_goliath.296="Virheellinen numero!" +general_goliath.297="Numeron tulee olla positiivinen!" +general_goliath.298="Tapahtui virhe, yritä myöhemmin uudelleen!" +general_goliath.299="Kukaan ei ansainnut guild experienceä päivänä %%date%%." +general_goliath.300="Top Guild Experience" +general_goliath.301="%%days%% päivää sitten" +general_goliath.302="tänään" +general_goliath.303="Odotathan ennen kuin teet tuon uudestaan!" +general_goliath.304="vaihtoi arvonimen %%target%% nimeksi %%details%%" +general_goliath.305="potki pelaajan %%player%% : \"%%details%%\"" +general_goliath.306="potki pelaajan %%player%% ." +general_goliath.307="Emme löytäneet arvonimeä nimellä '%%name%%'!" +general_goliath.308="%%player%% siirrettiin arvonimeltä %%oldRank%% arvonimelle %%rank%%" +general_goliath.309="%%player%% siirrettiin arvonimeltä %%oldRank%% arvonimelle %%rank%%" +general_goliath.310="Hänellä on jo tämä arvonimi!" +general_goliath.311="Et voi ylentää ketään Guildin johtajaksi, käytä komentoa '/guild transfer'!" +general_goliath.312="%%player%% nollasi guildin tunnisteen! Saatat joutua vaihtamaan palvelinta päivittääksesi sen." +general_goliath.313="Ilmianna pelaaja" +general_goliath.314="Jokin taisi mennä vikaan, yritä uudelleen hetken kuluttua!" +general_goliath.315="Voit ilmiantaa huijareita käyttämällä komentoa\n/watchdogreport (pelaajan nimi) (huijauskeinot)" +general_goliath.316="Voit ilmiantaa chatin väärinkäytöstä komennolla\n/chatreport (pelaajan nimi)" +general_goliath.317="Näyttää informaatiota Guildin jäsenestä" +general_goliath.318="Asettaa pelaajan arvonimen" +general_goliath.319="Asettaa guildin tunnisteen värin" +general_goliath.320="%%prefix%%Pelaaja poistettiin lobbystasi palvelimen sääntöjen rikkomisen vuoksi." +general_goliath.321="%%name%% ei ole lähettänyt sinulle yksityisviestejä viimeisen kymmenen minuutin aikana!" +general_goliath.322="%%name%% ei ole lähettänyt guild-chat -viestejä viimeisen kymmenen minuutin aikana!" +general_goliath.323="%%name%% ei ole lähettänyt viestejä viimeisen kymmenen minuutin aikana!" +general_goliath.324="Voit ilmiantaa henkilön seuraavaksi. Suosittelemme kuitenkin, että poistuisit hänen guildistaan, jotta et näkisi tätä keskustelua enää.\n" +general_goliath.325="Haluatko lähteä tästä guildista?" +general_goliath.326="Voit ilmiantaa henkilön seuraavaksi. Ehdotamme myös, että lisäisit hänet estettyjen pelaajien listallesi, jotta et näkisi hänen viestejään enää.\n" +general_goliath.327="Haluatko lisätä tämän pelaajan estettyjen pelaajien listallesi?" +general_goliath.328="Voit ilmiantaa henkilön seuraavaksi. Suosittelemme kuitenkin, että lähtisit hänen guildistaan, jotta et näkisi hänen viestejä enää." +general_goliath.329="Haluatko poistaa tämän pelaajan kaverilistaltasi?" +general_goliath.330="Jos tunnet että viestit häiritsevät sinua, voit tehdä ilmiannon painamalla alla olevaa \"KYLLÄ\"-painiketta" +general_goliath.331=" KYLLÄ " +general_goliath.332=" EI " +general_goliath.333="Peruuta ilmianto" +general_goliath.334="Lähetä ilmianto" +general_goliath.335="Yksityisviesti-ilmianto" +general_goliath.336="Guild-chat -ilmianto" +general_goliath.337="Partychat-ilmianto" +general_goliath.338="Sopimaton nimi" +general_goliath.339="Build Battle" +general_goliath.340="Huijaaminen" +general_goliath.341="Yksityisviestit" +general_goliath.342="Guild-chat" +general_goliath.343="Guildin nimi/tunniste" +general_goliath.344="Housing" +general_goliath.345="Partychat" +general_goliath.346="Sopimaton lemmikin nimi" +general_goliath.347="Pixel Painters" +general_goliath.348="Sopimaton skin tai viitta" +general_goliath.349="Kiitos tästä %%type%% -ilmiannosta. Ymmärrämme huolesi ja tarkastamme sen niin pian kuin voimme." +general_goliath.350="Ilmianna %%name%%?" +general_goliath.351="Valitse syy:" +general_goliath.352="Klikkaa ilmiantaaksesi %%name%% syystä %%report%%" +general_goliath.353="Julkinen chat -ilmianto" +general_goliath.354="Suljit ilmiantosi!" +general_goliath.355="Virheellinen käyttäjänimi. Kirjoititko nimen oikein?" +general_goliath.356="Pelaajaa nimeltä '%%name%%' ei löydetty. Kirjoititko nimen oikein?" +general_goliath.357="Olet jo ilmiantanut pelaajan %%name%% vähän aikaa sitten!" +general_goliath.358="Tapahtui virhe tehdessä ilmiantoa, yritä myöhemmin uudelleen." +general_goliath.359="Sinulla ei ole yhtään vahvistettavia ilmiantoja!" +general_goliath.360="Syötä ilmiannettavan pelaajan nimi (/%%command%% %%usage%%)" +general_goliath.361="Pahoittelut, en ymmärrä tätä ilmiantotyyppiä." +general_goliath.362="Tuo pelaaja ei ole juuri nyt paikalla." +general_goliath.363="Olet avannut liian monta %%name%% ilmiantoa! Sinulla voi olla vain %%reports%% avattua %%name%% ilmiantoa!" +general_goliath.364="Ymmärrämme huolesi, tätä pelaajaa koskien on jo avattu ilmiantoja. " +general_goliath.365="Pahoittelut, tämä ilmiantotyyppi ei toimi kirjan kanssa. Käytä komentoa ja puhu kehittäjälle." +general_goliath.366="Jokin meni vikaan, yritä lähettää ilmiantosi uudelleen." +general_goliath.367="Käytä komentoa %%command%% lähettääksesi ilmiantosi ylläpidon käsiteltäväksi." +general_goliath.368="Guild > %%player%% poistui." +general_goliath.369="Guild > %%player%% liittyi." +general_goliath.370="Olet jo partyssa, poistu siitä hyväksyäksesi tämän kutsun!" +general_goliath.371="Partyyn liittyminen epäonnistui." +general_goliath.372="Komento: /party accept " +general_goliath.373="Olet jo partyssa! Poistu siitä liittyäksesi toiseen." +general_goliath.374="Tämä party hajotettiin." +general_goliath.375="Tämä party on täynnä!" +general_goliath.376="Olet jo tässä partyssa." +general_goliath.377="Et voi liittyä tuohon partyyn!" +general_goliath.378="Jokin meni vikaan hakiessa partyn tietoja!" +general_goliath.379="Sinulla ei ole kutsua tämän pelaajan partyyn." +general_goliath.380="Tämä kutsu ei enää kelpaa." +general_goliath.381="Pelaajan hakeminen tuolla nimellä epäonnistui, yritä myöhemmin uudelleen." +general_goliath.382="Hyväksy partykutsu pelaajalta" +general_goliath.383="Tämä voidaan suorittaa vain testnetissä/betanetissä!" +general_goliath.384="Kutsuttiin pelaaja %%players%% partyysi!" +general_goliath.385="Paikalla ei vaikuttaisi olevan ketään!" +general_goliath.386="Et voi kutsua pelaajia." +general_goliath.387="Kutsuu kaikki paikalla olevat pelaajat partyysi" +general_goliath.388="Sinun tulee olla partyssa käyttääksesi tätä komentoa!" +general_goliath.389="Et ole tämän partyn johtaja!" +general_goliath.390="Ei löydetty partya, jossa tuo pelaaja olisi!" +general_goliath.391="Et voi haastaa omaa partyasi!" +general_goliath.392="Olet jo haastanut tämän partyn! Odota heidän vastaustaan!" +general_goliath.393="Toisen partyn tietojen hakeminen epäonnistui!" +general_goliath.394="Partyn tietojen hakeminen epäonnistui!" +general_goliath.395="Haasta toinen party CvC-taisteluun" +general_goliath.396="Kaikkien pelaajien tulee olla paikalla pelataksenne Cops and Crims -taistelussa." +general_goliath.397="toisen partyn kaikki pelaajat eivät olleet paikalla" +general_goliath.398="Kaikkien pelaajien tulee olla Cops and Crims -lobbyssa pelin aloittamiseksi!" +general_goliath.399="toisen partyn kaikki pelaajat eivät olleet Cops and Crims -lobbyssa" +general_goliath.400="Partyssasi tulee olla täsmälleen 8 jäsentä, sinut mukaan lukien!" +general_goliath.401="toisessa partyssa ei ollut 8 pelaajaa" +general_goliath.402="Komento: /party chat " +general_goliath.403="Et ole partyssa juuri nyt." +general_goliath.404="Viestin lähettäminen epäonnistui, yritä uudelleen." +general_goliath.405="Lähetä chat-viesti koko partylle" +general_goliath.406="Tuota pelaajaa ei ole olemassa." +general_goliath.407="Komento: /party demote " +general_goliath.408="Et ole partyssa juuri nyt!" +general_goliath.409="Tämä pelaaja ei ole partyssasi!" +general_goliath.410="Et voi alentaa itseäsi!" +general_goliath.411="Et voi alentaa pelaajaa, joka ei ole moderaattori!" +general_goliath.412="%%name1%% alensi pelaajan %%name2%% Partyn jäseneksi" +general_goliath.413="Partyn päivittäminen epäonnistui!" +general_goliath.414="Pelaajan tietojen hakeminen epäonnistui!" +general_goliath.415="Partyn tietojen hakeminen epäonnistui!" +general_goliath.416="Alentaa pelaajan partyn moderaattorista jäseneksi" +general_goliath.417="Sinulla ei ole oikeuksia hajottaa tätä partya." +general_goliath.418="Partyn hakeminen epäonnistui, yritä uudelleen." +general_goliath.419="Hajottaa partyn" +general_goliath.420="Anna mulle nimi joka kaapata veliseni." +general_goliath.421="Tällä pelaajalla ei ole partya." +general_goliath.422="Olet jo partyssa, poistu siitä kaapataksesi toisen." +general_goliath.423="Tietokanta ei hyväksynyt kaappausta, ilmeisesti onni ei ollut sinun puolellasi." +general_goliath.424="Tietokanta ei hyväksynyt kaappausta, ilmeisesti onni ei ollut sinun puolellasi. (1)" +general_goliath.425="Kaappausyritys epäonnistui! Hylätään tehtävä." +general_goliath.426="Tietokanta ei hyväksynyt kaappausta, ilmeisesti onni ei ollut sinun puolellasi. (2)" +general_goliath.427="%%player%% kaappasi partyn!\nKumartakaa uutta johtajaanne" +general_goliath.428="Partyn hakeminen epäonnistui." +general_goliath.429="Partyn kaappaaminen epäonnistui :(" +general_goliath.430="Ota haltuusi toisen pelaajan party" +general_goliath.431="Voit kutsua enintään 10 pelaajaa kerrallaan!" +general_goliath.432="Partyn hakeminen epäonnistui, yritä uudelleen myöhemmin." +general_goliath.433="Et voi kutsua tätä pelaajaa partyysi!" +general_goliath.434="Ei löydetty pelaajaa tuolla nimellä!" +general_goliath.435="Et voi kutsua itseäsi partyyn!" +general_goliath.436="Et voi kutsua tätä pelaajaa, sillä hän ei ole paikalla." +general_goliath.437="%%player%% on jo partyssa." +general_goliath.438="%%player%% on jo kutsuttu partyyn." +general_goliath.439="Et voi kutsua tätä pelaajaa, sillä hän on estänyt sinut." +general_goliath.440="Pelaajan kutsuminen epäonnistui." +general_goliath.441="Virhe kutsuessa tätä pelaajaa." +general_goliath.442="Et voi kutsua tätä pelaajaa." +general_goliath.443="Kutsu toinen pelaaja partyysi" +general_goliath.444="Komento: /party kick " +general_goliath.445="Et ole partyssa juuri nyt!" +general_goliath.446="Et ole tämän partyn johtaja." +general_goliath.447="Et voi potkia itseäsi partysta!" +general_goliath.448="%%player%% poistettiin partysta" +general_goliath.449="%%other%% potki sinut partysta" +general_goliath.450="Pelaajan potkiminen partysta epäonnistui, yritä uudelleen." +general_goliath.451="Partyn hakeminen epäonnistui, ilmoitathan tästä ylläpidolle." +general_goliath.452="Poista pelaaja partystasi" +general_goliath.453="Ei poissa olevia pelaajia poistettavana." +general_goliath.454="Poissa olevien pelaajien poistaminen epäonnistui" +general_goliath.455="Sinulla ei ole oikeuksia käyttää tätä komentoa." +general_goliath.456="Partyn tietojen hakeminen epäonnistui." +general_goliath.457="Poista kaikki poissa olevat pelaajat partystasi" +general_goliath.458="%%player%% poistui partysta." +general_goliath.459="Poistuit partysta." +general_goliath.460="Partysta poistuminen epäonnistui, yritä yydelleen." +general_goliath.461="Et ole partyssa." +general_goliath.462="Partysi hakeminen epäonnistui" +general_goliath.463="Poistu nykyisestä partystasi" +general_goliath.464="Et ole partyssa juuri nyt." +general_goliath.465="Listaa partyssasi tällä hetkellä olevat pelaajat" +general_goliath.466="Partyn mykistäminen epäonnistui, yritä uudelleen." +general_goliath.467="Party on nyt mykistetty.\nVain Partyn moderaattorit, ylläpito ja johtaja voivat keskustella chatissa." +general_goliath.468="Party ei ole enää mykistetty." +general_goliath.469="Sinulla ei ole oikeuksia käyttää tätä komentoa!" +general_goliath.470="Mykistää partyn chatin, jolloin vain ylläpito sekä partyn moderaattorit ja johtaja voivat käyttää sitä" +general_goliath.471="Jäsenen tietojen päivittäminen epäonnistui!" +general_goliath.472="Sinun ei pitäisi olla täällä!" +general_goliath.473="Tämä äänestys on päättynyt." +general_goliath.474="Olet jo vastannut tähän äänestykseen!" +general_goliath.475="En ymmärrä tätä vastausta!" +general_goliath.476="Tuntematon vastaus!" +general_goliath.477="Ääni rekisteröity! Tulokset näytetään kohta." +general_goliath.478="Vastaa äänestykseen" +general_goliath.479="Sinulla ei ole oikeuksia käyttää tätä komentoa, sinun tulee olla %%mvp%% tai %%yt%%" +general_goliath.480="Äänestys on jo käynnissä!" +general_goliath.481="Jokainen vastaus voi olla enintään 20 merkin pituinen." +general_goliath.482="Jokin vastauksista on liian lyhyt! Vastauksen tulee olla vähintään yhden merkin pituinen!" +general_goliath.483="Vain partyn johtaja voi käyttää partyn äänestyskomentoa. Äänestys kestää 30 sekuntia. Tulokset näytetään äänestyksen päättyessä. Äänestyksessä voi olla maksimissaan neljä vastausvaihtoehtoa!\nVirheellinen komento! /party poll " +general_goliath.484=" - %%number%%. %%answer%%" +general_goliath.485="%%name%% loi äänestyksen! Vastaa klikkaamalla alapuolella olevia vaihtoehtoja" +general_goliath.486="Kysymys: %%question%%" +general_goliath.487="Äänestys päättyy %%seconds%% sekunnin kuluttua!" +general_goliath.488="Äänestys päättyi etuajassa, tässä ovat tulokset!" +general_goliath.489="%%answer%% - %%votes%% Ääntä (%%percentage%%%) [%%visualised%%]" +general_goliath.490="Luo äänestyksen, jossa partyn jäsenet voivat äänestää" +general_goliath.491="Sinulla ei ole oikeuksia käyttää tätä komentoa! Tarvitset %%yt%%-rankin tai %%superstar%%." +general_goliath.492="Asettaa yksityiset pelit päälle partyllesi" +general_goliath.493="Komento: /party promote " +general_goliath.494="Et voi ylentää itseäsi!" +general_goliath.495="%%name1%% ylensi pelaajan %%name2%% Partyn johtajaksi\n%%name1%% on nyt Partyn moderaattori" +general_goliath.496="%%name1%% ylensi pelaajan %%name2%% Partyn moderaattoriksi" +general_goliath.497="Ylentää toisen partyn jäsenen joko moderaattoriksi tai johtajaksi" +general_goliath.498="Partyn asetusten päivittäminen epäonnistui!" +general_goliath.499="%%player%% otti pois päältä asetuksen %%option%%" +general_goliath.500="Partyn tietojen hakeminen epäonnistui, yritä uudelleen." +general_goliath.501="Partyn asetukset\n/p setting allinvite - Antaa kaikille oikeuden kutsua pelaajia\n/p private - Asettaa yksityiset pelit päälle\n/p mute - Mykistää partyn chatin" +general_goliath.502="Muuttaa partyn asetuksia" +general_goliath.503="Salli kaikkien pelaajien lähettää partykutsuja" +general_goliath.504="Pelaa yksityisiä pelejä partysi kanssa" +general_goliath.505="Olet jo partyssa! Poistu liittyäksesi hiljaa." +general_goliath.506="Tuo pelaaja ei ole juuri nyt partyssa." +general_goliath.507="Tietojen hakeminen epäonnistui." +general_goliath.508="Partysta poistuminen epäonnistui" +general_goliath.509="Kaikki paikalla olevat guildin jäsenet ovat jo partyssasi!" +general_goliath.510="%%who%% siirsi partyn pelaajalle %%other%%" +general_goliath.511="Partyn siirtäminen epäonnistui." +general_goliath.512="Käyttäjän tietojen hakeminen epäonnistui." +general_goliath.513="Siirtää partyn toiselle pelaajalle" +general_goliath.514="Jokin meni vikaan hakiessa pelaajan tietoja!" +general_goliath.515="Et voi teleportata yli kymmenen pelaajan partya!" +general_goliath.516="Teleporttaa partyn jäsenet palvelimellesi" +general_goliath.517="Partysi luominen epäonnistui" +general_goliath.518="Partysi tietojen hakeminen epäonnistui." +general_goliath.519="Toisen pelaajan tietojen hakeminen epäonnistui" +general_goliath.520="%%sender%%yoinkkasi sinut partyyn" +general_goliath.521="%%who%% yoinkkasi pelaajan %%player%% partyyn" +general_goliath.522="Tämä komento on tällä hetkellä poissa käytöstä, ole hyvä ja yritä myöhemmin uudelleen!" +general_goliath.523="Sinulla ei ole oikeuksia käyttää tätä komentoa!" +general_goliath.524="Jokin meni vikaan käsiteltäessä komentoasi, ole hyvä ja yritä uudelleen myöhemmin." +general_goliath.525="Sinulla ei ole oikeuksia käyttää tätä komentoa! Tarvitset YouTube-rankin tai %%superstar%%." +general_goliath.526="Sinun tulee olla partyn johtaja käyttääksesi tätä komentoa." +general_goliath.527="Pelaajien enimmäismäärän tulee olla vähintään 2." +general_goliath.528="Loit julkisen partyn! Pelaajat voivat liittyä komennolla /party join %%name%%\nPartyn maksimikoko on %%count%% pelaajaa.\n" +general_goliath.529="Partyn luominen epäonnistui, ole hyvä ja yritä uudelleen myöhemmin" +general_goliath.530="Partyn avaaminen julkiseksi epäonnistui, yritä uudelleen." +general_goliath.531="Party on nyt julkinen! Pelaajat voivat liittyä komennolla /party join %%name%%\n\nPartyn maksimikoko on %%count%% pelaajaa." +general_goliath.532="Enimmäiskapasiteetin muuttaminen epäonnistui, yritä uudelleen." +general_goliath.533="Muutettiin partyn maksimikokoa!\n\nPartyn maksimikoko on %%count%% pelaajaa." +general_goliath.534="Sinun tulee olla partyssa käyttääksesi tätä komentoa!" +general_goliath.535="Party on jo yksityinen!" +general_goliath.536="Party ei ole enää julkinen" +general_goliath.537="Party tyhjennettiin!" +general_goliath.538="Partykutsu pelaajalta %%player%% vanhentui." +general_goliath.539="Partykutsu pelaajalle %%player%% vanhentui" +general_goliath.540="Party hajotettiin, koska partyn johtaja poistui palvelimelta." +general_goliath.541="%%name%% hajotti partyn!" +general_goliath.542="Partyn hajottaminen epäonnistui, ilmoitathan tästä ylläpidolle." +general_goliath.543="%%player%% on jo kutsuttu partyysi! Odota, että hän hyväksyy kutsun!" +general_goliath.544="%%player%% kutsui pelaajan %%them%% partyyn! Hänellä on 60 sekuntia aikaa hyväksyä." +general_goliath.545="%%player%% kutsui sinut partyynsa!\n" +general_goliath.546="%%player%% kutsui sinut pelaajan %%leader%% partyyn!\n" +general_goliath.547="Sinulla on 60 sekuntia aikaa hyväksyä. Klikkaa tästä liittyäksesi!" +general_goliath.548="Klikkaa käyttääksesi komentoa\n/party accept %%player%%" +general_goliath.549="Party siirrettiin pelaajalle %%other%% koska %%leader%% poistui" +general_goliath.550="%%player%% poistettiin partysta, koska hän poistui palvelimelta" +general_goliath.551="Partyn johtaja, %%player%% , poistui palvelimelta. Hänellä on 5 minuuttia aikaa palata ennen partyn hajoamista." +general_goliath.552="%%player%% poistui palvelimelta. Hänellä on 5 minuuttia aikaa palata ennen kuin hänet poistetaan partysta." +general_goliath.553="Yleiselle kanavalle siirtyminen epäonnistui, ilmoitathan tästä ylläpidolle." +general_goliath.554="Et ole partyssa, joten sinut siirrettiin kanavalle ALL." +general_goliath.555="Tämä party on tällä hetkellä mykistetty." +general_goliath.556="Tietojen hakeminen epäonnistui, ilmoitathan tästä ylläpidolle." +general_goliath.557="Oho, tämän Partyn chat on hidastettu. Yritä uudelleen %%seconds%%s kuluttua" +general_goliath.558="Party >" +general_goliath.559="%%player%% kutsui kaikki guildin %%guild%% jäsenet partyynsa!\n" +general_goliath.560="Pelaajien enimmäismäärä ei voi ylittää sataa." +general_goliath.561="================== VAROITUS ==================\nTämä LAKKAUTTAA GUILDIN ja poistaa kaikki sen jäsenet.\nKaikki Guildin keräämä experience TUHOTAAN. Tätä ei voi kumota.\nJos haluat varmasti jatkaa, käytä komentoa /guild confirm 10 sekunnin sisällä." +general_goliath.562="Kanssasi partyssa: " +general_goliath.563=" sekä %%count%% pelaaja lisää!" +general_goliath.564=" sekä %%count%% pelaajaa lisää!" +general_goliath.565="Et täytä tämän virstanpylväspalkinnon ehtoja!" +general_goliath.566="Olet jo lunastanut tämän virstanpylväspalkinnon!" +general_goliath.567="Lunastit onnistuneesti seuraavat:" +general_goliath.568="Lahjanantajan saavutus" +general_goliath.569="Legendaarinen Lahjanantajan hattu" +general_goliath.570="Legendaarinen Lahjanantajan asu" +general_goliath.571="Legendaarinen Gifterino Companion" +general_goliath.572="Jokin meni vikaan käsitellessä tuota! Yritä hetken kuluttua uudelleen." +general_goliath.573="Yksi pelaaja kiitti sinua viimeisen minuutin aikana!" +general_goliath.574="%%amount%% pelaajaa kiitti sinua viimeisen minuutin aikana!" +general_goliath.575="Palkinnot" +general_goliath.576="Tuo ei ole kelvollinen käyttäjänimi!" +general_goliath.577="Jokin meni vikaan. Ole hyvä ja yritä uudelleen hetken kuluttua!" +general_goliath.578="Kenelläkään ei ole juuri nyt aktiivista network boosteria! Yritä myöhemmin uudelleen." +general_goliath.579="Käsittelemme vielä viimeisintä /tip -komentoasi!" +general_goliath.580="Ei löydetty pelaajaa nimellä '%%player%%'" +general_goliath.581="Et voi kiittää itseäsi!" +general_goliath.582="Kiitit yhtä pelaajaa yhdessä pelissä!" +general_goliath.583="Kiitit yhtä pelaajaa %%games%% eri pelissä!" +general_goliath.584="Kiitit %%amount%% pelaajaa yhdessä pelissä!" +general_goliath.585="Kiitit %%amount%% pelaajaa %%games%% eri pelissä!" +general_goliath.586="Kiitit yhtä pelaajaa!" +general_goliath.587="Kiitit %%amount%% pelaajaa!" +general_goliath.588="Olet jo kiittänyt kaikkia, joilla on aktiivinen booster, joten ei ole ketään ketä kiittää juuri nyt!" +general_goliath.589="Kiitit (anonyymisti) pelaajaa %%player%% pelissä %%gameType%%!" +general_goliath.590="Kiitit pelaajaa %%player%% pelissä %%gameType%%!" +general_goliath.591="Olet jo kiittänyt tätä pelaajaa tänään pelissä %%gameType%%! Yritä toista pelaajaa!" +general_goliath.592="Tämä pelaaja ei ole paikalla, yritä toista pelaajaa!" +general_goliath.593="Ei aktiivisia boostereita pelissä %%gameType%%!" +general_goliath.594="Olet jo kiittänyt jotakuta viimeisen tunnin aikana pelissä %%gameType%%! Odota hetki ja yritä uudelleen!" +general_goliath.595="Partyssasi tulee olla täsmälleen %%count%% pelaajaa voidaksenne pelata tätä!" +general_goliath.596="Jokin meni vikaan enkä voinut löytää tuota karttaa! Ole hyvä ja ilmoita tästä ylläpidolle!" +general_goliath.597="Ei saatavilla palvelimia tässä kartassa! Yritä kohta uudelleen!" +general_goliath.598="Vain partyn johtaja voi teleportata sinut peliin! Odota että hän klikkaa NPC-hahmoa tai käytä komentoa /party leave" +general_goliath.599="Et voi aloittaa yksityistä peliä, kun partyssa olet vain sinä itse!" +general_goliath.600="Partysi on liian suuri, että se voisi liittyä peliin %%gameType%%: %%map%%! Enintään %%count%% pelaajaa per party!" +general_goliath.601="Partyssasi tulee olla vähintään %%count%% pelaajaa voidaksenne pelata tätä!" +general_goliath.602="Partysi on liian suuri tähän karttaan! Yritä toista karttaa!" +general_goliath.603="Partysi ei voi jonottaa peliin %%gameType%%: %%map%% koska pelaaja %%player%% ei ole paikalla!" +general_goliath.604="Partysi ei voi jonottaa peliin %%gameType%%: %%map%% koska pelaajalla %%player%% ei ole oikeuksia liittyä tälle palvelimelle!" +general_goliath.605="Anteeksi, emme löytäneet palvelimia, joissa olisi tarpeeksi tilaa pelille %%game%%: %%map%%! Yritä uudelleen muutaman minuutin kuluttua!" +general_goliath.606="Siirretään sinut palvelimelle %%server%%!" +general_goliath.607="Ei palvelinta saatavilla! Yritä hetken kuluttua uudelleen!" +general_goliath.608="Peliä ei löytynyt '%%gameType%%'." +general_goliath.609=" on talossa %%name%%" +general_goliath.610="%%name%% ei ole lähettänyt viestejä lähiaikoina!" +general_goliath.611="%%name%% ei ole lähettänyt sinulle yksityisviestejä lähiaikoina!" +general_goliath.612="%%name%% ei ole lähettänyt guild-viestejä lähiaikoina!" +general_goliath.613="%%name%% ei ole lähettänyt party-viestejä lähiaikoina!" +general_goliath.614="================== VAROITUS ==================\nTämä LAKKAUTTAA GUILDIN ja poistaa kaikki sen jäsenet.\nKaikki Guildin keräämä experience TUHOTAAN. Tätä ei voi kumota.\nJos haluat varmasti jatkaa, käytä komentoa /guild confirm 10 sekunnin sisällä." +general_goliath.615="Et voi hiljentää guildin jäsentä, jolla on korkeampi arvonimi kuin sinulla!" +general_goliath.616="Liityit pelaajan %%player%% partyyn!" +general_goliath.617="Liityit pelaajan %%player%% partyyn!" +general_goliath.618="Palkintojen yhteenveto" +general_goliath.619="[VAROITUS] Joku on luonut sinua koskevan chat-ilmiannon, ja tiimimme on nyt tarkistanut sen.\nVaikka tällä kertaa ei ryhdyttykään toimenpiteisiin, muistathan, että chat-säännöt koskevat myös YOUTUBE-rankillisia pelaajia.\nSäännöt: https://hypixel.net/rules\nSisällöntuottajien yhteyshenkilö: creators@hypixel.net" +general_goliath.620="Sinun on oltava VIP+ luodaksesi guildin!\nVoit kuitenkin liittyä toisten guildeihin!" +general_goliath.621="Sinulla ei ole oikeuksia käyttää tätä komentoa, sinun tulee olla %%mvp%% tai %%yt%%" +general_goliath.622="Hän on jo guildissa!" +general_goliath.623="asetti oikeuden %%details%% arvonimelle %%target%%" +general_goliath.624="poisti oikeuden %%details%% arvonimeltä %%target%%" +general_goliath.625="pyysi lupaa liittyä" +general_goliath.626="asetti arvonimen %%rank%% oletusarvonimeksi" +general_goliath.627="Hypixel API -avaimesi nollattiin!\n\nSyy: %%reason%%" +general_goliath.628="Kaikki tilastosi on pyyhitty väärinkäytön seurauksena, mukaan lukien Tournament- ja Ranked SkyWars -tilastosi.\nMikäli uskot tämän olevan virhe, otathan yhteyttä\n%%underline%%support.hypixel.net" +general_goliath.629="SkyBlock-profiilisi %%profileName%% on pyyhitty koska yhteistyöpelin jäsenen todettiin boostanneen.\nMikäli uskot tämän olevan virhe, voit ottaa yhteyttä tukeen: %%underline%%support.hypixel.net" +general_goliath.630="SkyBlock-profiilisi %%profileName%% on pyyhitty koska yhteistyöpelin jäsenen todettiin boostanneen.\n\nMikäli uskot tämän olevan virhe, voit ottaa yhteyttä tukeen: %%underline%%support.hypixel.net" +general_goliath.631="Guild: Tervetuloviesti (Esikatselu)" +general_goliath.632="Guild: Tervetuloviesti" +general_goliath.633="%%pet%% companionisi nimi nollattiin, koska se rikkoi Hypixelin palvelimen sääntöjä.\n\nNimi:\n%%name%%\n\n%%underline%%hypixel.net/rules" +general_goliath.634="Ansaitsit" +general_goliath.635="%%experience%% Hypixel-experienceä" +general_goliath.636="+%%earned%% %%reason%%" +general_goliath.637="Peliaikabonus" +general_goliath.638="%%earned%% %%gameType%% -kolikko" +general_goliath.639="%%earned%% %%gameType%% -kolikkoa" +general_goliath.640="+%%coins%% Pelipalkinto" +general_goliath.641="+%%earned%% %%reason%%" +general_goliath.642="%%earned%% Guild Experienceä" +general_goliath.643="+%%earned%% %%reason%%" +general_goliath.644="Guild Experience laskettiin %%percent%%%:iin,\nkoska Guildisi on saavuttanut päivittäisen rajan." +general_goliath.645="Pelissäsi oli %%amount%% %%rank%%-pelaajaa (tai korkeampaa)" +general_goliath.646="%%player%% liittyi partyyn." +general_goliath.647="Partyn jäsenet (%%count%%)" +general_goliath.648="Partyn johtaja: %%player%%" +general_goliath.649="Partyn moderaattorit: %%players%%" +general_goliath.650="Partyn jäsenet: %%players%%" +general_goliath.651="Party > " +general_goliath.652="Siirtämisen tila" +general_goliath.653="Sinulla on vahvistetusti Microsoft-tili!" +general_goliath.654="Tilisi on vahvistetusti siirretty." +general_goliath.655="Nykyinen %%type%% -taso" +general_goliath.656="Rangaistuksen tiedot" +general_goliath.657="Päivämäärä: %%date%%" +general_goliath.658="Syy: %%reason%%" +general_goliath.659="Tila: %%status%%" +general_goliath.660="Päättyy: %%date%%" +general_goliath.661="Päättyi: %%date%%" +general_goliath.662="Klikkaa näyttääksesi valituksen!" +general_goliath.663="Ei mitään" +general_goliath.664="Aktiivinen (Pysyvä)" +general_goliath.665="Aktiivinen" +general_goliath.666="Kilpailuporttikiellon tila" +general_goliath.667="Kilpailullisten pelimuotojen porttikielloilla varmistetaan näiden pelimuotojen reiluus ja poistetaan toistuvat sääntöjen rikkojat." +general_goliath.668="Klikkaa saadaksesi lisää tietoa!" +general_goliath.669="Olet saanut monta tyypin '%%type%%' rangaistusta viime aikoina. Tulevat samankaltaiset rangaistuksesi ovat tavallista pidempiä." +general_goliath.670="Olet saanut yhden tai useamman tyypin '%%type%%' rangaistuksen viime aikoina. Tulevat samankaltaiset rangaistuksesi ovat tavallista pidempiä." +general_goliath.671="Tilanteesi on hyvä, ja sinulla on vain vähän, jos lainkaan, viimeaikaisia tyypin '%%type%%' rangaistuksia." +general_goliath.672="Hiljentäminen" +general_goliath.673="Porttikiellot" +general_goliath.674="mute" +general_goliath.675="anna porttikielto" +general_goliath.676="Hypixel Atlas" +general_goliath.677="Klikkaa sen pelin tunnusta, jonka uusintoja haluat katsoa." +general_goliath.678="ANSAITSE LISÄÄ EXPERIENCEÄ" +general_goliath.679="Pyydä Atlas-ilmiantoa peliin %%game%%." +general_goliath.680="Vaatimukset" +general_goliath.681="%%amount%% pelin %%game%% %%stat%%" +general_goliath.682="Hypixel-level %%level%%" +general_goliath.683="Et täytä vaatimuksia!" +general_goliath.684="Klikkaa pyytääksesi ilmiantoa!" +general_goliath.685="Ei tarpeeksi päätöksiä!" +general_goliath.686="Ei mitään" +general_goliath.687="Atlas-tilastot" +general_goliath.688="Päätöksiä lähetetty: %%amount%%" +general_goliath.689="Tarkkuus: %%color%%%%amount%%" +general_goliath.690="Nämä tilastot saattavat olla tallentuneina välimuistiin jopa %%minutes%% minuutin ajan!" +general_goliath.691="Ei ilmiantoja saatavilla juuri nyt! gg :)" +general_goliath.692="Tarkastusloki" +general_goliath.693="Vaihda Guildin Discordia" +general_goliath.694="Guildin asetukset" +general_goliath.695="Näytä tilastot" +general_goliath.696="Sihteeri" +general_goliath.697="Jäsen" +general_goliath.698="Virheellinen komento! Käyttääksesi -a kirjoita \"/tip -a \"" +general_goliath.699="Se oli esimerkki! Kirjoita paikalla olevan pelaajan nimi siihen!" +general_goliath.700="Kiittäminen on tällä hetkellä poissa käytöstä, ja Boosterit on pysäytetty, ne tulevat takaisin pian!" +general_goliath.701="Et voi käyttää /tip-komentoa seuraavaan 5 minuuttiin! Ethän spämmää komentoa!" +general_goliath.702="Hidasta vähän! Voit käyttää /tip-komentoa muutaman sekunnin välein." +general_goliath.703="Otettiin /tip-viestit käyttöön!" +general_goliath.704="Poistettiin /tip-viestit käytöstä!" +general_goliath.705="Käytä tätä komentoa kiittäksesi toista pelaajaa kolikoilla." +general_goliath.706="Esimerkki komennon käytöstä: /tip Steve Skywars tai /tip -a Steve Skywars lähettääksesi sen nimettömästi." +general_goliath.707="Voit myös käyttää komentoa /tip all kiittääksesi kaikista aktiivisista boostereista!" +general_goliath.708="%%player%% poistettiin partystasi, koska hän poistui palvelimelta." +general_goliath.709="Party hajotettiin, koska kaikki kutsut vanhentuivat ja party on tyhjä." +general_goliath.710="Olet jo kutsunut pelaajan %%player%% guildiisi! Odota että hän hyväksyy kutsun!" +general_goliath.711="Chat-sääntöjen rikkominen tai huijaaminen" +general_goliath.712="Sopimaton käyttäjänimi" +general_goliath.713="Kiellettyjen menetelmien käyttäminen pelitilastojen parantamiseksi" +general_goliath.714="Kiellettyjen modifikaatioiden käyttäminen epäreilun edun saavuttamiseksi" +general_goliath.715="Yhteistyö toisen tiimin kanssa epäreilun edun saavuttamiseksi" +general_goliath.716="Sopimattomat guildin tiedot" +general_goliath.717="Sopimaton pelinsisäinen esine" +general_goliath.718="Sopimaton lemmikin nimi" +general_goliath.719="Sopimaton skin tai viitta" +general_goliath.720="Sopimaton kyltti tai hologrammi" +general_goliath.721="Tuon nimistä pelaajaa ei löydetty. Kirjoititko nimen oikein?" +general_goliath.722="Käytä tätä komentoa haastaaksesi toinen party\n8v8 Cops vs Crims -taisteluun! Komento on\n/party challenge " +general_goliath.723="Et ole partyssa, jossa on täsmälleen 8 pelaajaa." +general_goliath.724="Ei löydy pelaajaa tuolla nimellä!" +general_goliath.725="Tuo pelaaja ei ole partyssa, jossa on täsmälleen 8 pelaajaa." +general_goliath.726="CvC-haaste pelaajan %%other%% partylle on vanhentunut!" +general_goliath.727="CvC-haaste pelaajan %%other%% partylta on vanhentunut!" +general_goliath.728="Partysi haastoi pelaajan %%other%% partyn CvC-otteluun!\n\nHeillä on 5 minuuttia aikaa vastata ennen haasteen vanhentumista." +general_goliath.729="Pelaajan %%other%% party haastoi partysi CvC-otteluun!\n\nPartysi johtajalla on 5 minuuttia aikaa käyttää komentoa /party challenge %%name%% ennen haasteen vanhentumista." +general_goliath.730="Pelaajan %%player%% party yritti ottaa haasteen vastaan, mutta %%reason%%" +general_goliath.731="Ei voitu aloittaa haastetta, sillä %%reason%%. Yritä uudelleen muutaman sekunnin kuluttua." +general_goliath.732="Katso kohti kohdetta, josta haluat ilmoittaa, ja käytä komentoa /worldreport tehdäksesi ilmoituksen" +general_goliath.733="Olet tekemässä %%type%%-ilmoitusta" +general_goliath.734="Klikkaa tekstiä, josta haluat ilmoittaa:" +general_goliath.735="Klikkaa linkittääksesi Discord-tilisi" +general_goliath.736="Huh, säikäytit minut!" +general_goliath.737="Et voi poistua tältä alueelta!" +general_goliath.738="Kysymys kuuluu... mitä SINÄ teet!?" +general_goliath.739="En mitään." +general_goliath.740="%%player_name%% ei ole kaverilistallasi!" +general_goliath.741="Roolin %%rank%% oikeudet" +general_goliath.742="Klikkaa nähdäksesi sivun %%page%%" +general_goliath.743="Tunnisteen väri" +general_goliath.744="Discord" +general_goliath.745="%%name%%n valinta" +general_goliath.746="%%name%% -lobbyn valinta" +general_goliath.747="Parhaiden kavereiden liittymis- ja poistumisviestit käytössä!" +general_goliath.748="Täytyy olla pienempi numero!" +general_goliath.749="%%color%%%%experience%% Event Experienceä" +general_goliath.750="Käytä tätä komentoa kiittäksesi toista pelaajaa kolikoilla." +general_goliath.751="Esimerkkikäyttö: %%commandA%% tai %%commandB%% lähettääksesi sen nimettömästi." +general_goliath.752="Tiesitkö, että voit käyttää komentoa %%command%% kiittääksesi kaikista aktiivisista boostereista?" +general_goliath.753="Klikkaa tästä kiittääksesi kaikista aktiivisista boostereista" +general_goliath.754="Klikkaa käyttääksesi komentoa /tip all" +general_goliath.755="Ilmoita" +general_goliath.756="Ilmoita pelaajasta %%name%%" +general_goliath.757="Kenestä tahdot ilmoittaa?" +general_goliath.758="%%yes%%" +general_goliath.759="Lähetä ilmoitus" +general_goliath.760="KYLLÄ" +general_goliath.761="%%no%%" +general_goliath.762="Peruuta ilmoitus" +general_goliath.763="En löytänyt sinulle ketään, josta voisit tehdä ilmoituksen" +general_goliath.764="EI" +general_goliath.765="Käytä komentoa /report " +general_goliath.766="Klikkaa ilmoittaaksesi tästä pelaajasta." +general_goliath.767="Pidä kädessäsi esinettä, josta haluat ilmoittaa ja käytä komentoa /itemreport lähettääksesi ilmoituksen" +general_goliath.768="Haluatko lisätä tämän pelaajan estettyjen pelaajien listallesi?" +general_goliath.769="Haluatko lähteä tästä guildista?" +general_goliath.770="Haluatko poistaa tämän pelaajan kaverilistaltasi?" +general_goliath.771="Ilmoita esineestä %%item_name%%" +general_goliath.772="%%type%%-ilmoitus" +general_goliath.773="Ilmianna talo" +general_goliath.774="Ilmianna saari" +general_goliath.775="%%game%% -lobby" +general_goliath.776="%%game%%" +#general_goliath.777="" # No translation available +general_goliath.778="En löytänyt pelaajaa, josta halusit ilmoittaa!" +general_goliath.779="Et voi ilmiantaa itseäsi" +general_goliath.780="Tuntematon ilmoitustyyppi" +general_goliath.781="Et voi ilmoittaa tuosta" +general_goliath.782="En tiedä, kuinka käsitellä tätä ilmoitustyyppiä" +general_goliath.783="Odotathan ennen kuin ilmoitat tästä pelaajasta uudelleen!" +general_goliath.784="Et voi liittyä ryhmään, sillä sen johtaja on estänyt sinut!" +general_goliath.785="Tämä pelaaja on lisännyt sinut estettyjen pelaajien listalleen!" +general_goliath.786="Tämä pelaaja on lisännyt sinut estettyjen pelaajien listalleen" +general_goliath.787="Et voi kutsua tätä pelaajaa, sillä hän on estänyt sinut." +general_goliath.788="Lähetetään ilmoitusta..." +general_goliath.789="Odota..." \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/main_lobby.properties b/configuration/i18n/fi_FI/official/main_lobby.properties new file mode 100644 index 000000000..4f8a64d1e --- /dev/null +++ b/configuration/i18n/fi_FI/official/main_lobby.properties @@ -0,0 +1,1063 @@ +main_lobby.0="Pisteitä yhteensä: %%points%%" +main_lobby.1="Kohteita ammuttu: %%killed%%" +main_lobby.2="Aikaa kulutettu: %%time%%" +main_lobby.3="Jousipyssy 2000™" +main_lobby.4="Rank: %%rank%%" +main_lobby.5="Saavutukset: %%achievements%%" +main_lobby.6="Hypixel-level: %%level%%" +main_lobby.7="Lobby: %%lobby%%" +main_lobby.8="Pelaajia: %%players%%" +main_lobby.9="Olen jo lähettämässä sinua kohteeseen %%name%%!" +main_lobby.10="Pahoitteluni, minulla on vaikeuksia lähettää sinua kohteeseen %%name%% - anna minulle hetki!" +main_lobby.11="Sinun täytyy käyttää vähintään versiota 1.8 käyttääksesi Player Housingia!" +main_lobby.12="Hyppää portaaliin," +main_lobby.13="tai klikkaa kompassiasi päästäksesi pelaamaan." +main_lobby.14="Voit myös" +main_lobby.15="klikata jotakin NPC-hahmoa portaalin lähistöllä." +main_lobby.16="Älä unohda tutkia paikkoja!" +main_lobby.17="Löydät paljon salaisuuksia!" +main_lobby.18="Tsekkaa tavaraluettelosi." +main_lobby.19="Löydät sieltä saavutuksia, kosmeettisia esineitä ja paljon muuta!" +main_lobby.20="www.hypixel.net - Uutisia, keskustelua ja muuta!" +main_lobby.21="Klikkaa NPC-hahmoa pelataksesi!" +main_lobby.22="[NPC] Kirvesmies: Housing ei ole tällä hetkellä saatavilla! Tule myöhemmin takaisin." +main_lobby.23="Player Housing" +main_lobby.24="Duels" +main_lobby.25="Smash Heroes" +main_lobby.26="Warlords" +main_lobby.27="Mega Walls" +main_lobby.28="TNT Games" +main_lobby.29="Prototype" +main_lobby.30="Build Battle" +main_lobby.31="Murder Mystery" +main_lobby.32="Arcade" +main_lobby.33="UHC Champions" +main_lobby.34="Blitz SG" +main_lobby.35="Mini Walls" +main_lobby.36="Cops and Crims" +main_lobby.37="Speed UHC" +main_lobby.38="Classic Games" +main_lobby.39="Bed Wars" +main_lobby.40="SkyWars" +main_lobby.41="The Pit" +main_lobby.42="Mysteeripöly: %%dust%%" +main_lobby.43="Pixel Painters" +main_lobby.44="Olet saanut superpalkinnon!" +main_lobby.45="Olet jo ansainnut palkinnon tänä vuonna!" +main_lobby.46="Tämä peli on väliaikaisesti poissa käytöstä!" +main_lobby.47="Viikoittaiset ennätykset" +main_lobby.48="Pumpkin Smash" +main_lobby.49="Ennätyksesi: %%best%%" +main_lobby.50="Päivittyy joka 5. minuutti" +main_lobby.51="N/A" +main_lobby.52="TURBO BAT RACERS" +main_lobby.53="Valitse rata (Klikkaa)" +main_lobby.54="Parhaat ajat" +main_lobby.55="Ennätyksesi: %%best%%" +main_lobby.56="HELPPO" +main_lobby.57="KESKIVAIKEA" +main_lobby.58="VAIKEA" +main_lobby.59="Läpäisit radan %%course%% ajassa %%duration%%!" +main_lobby.60="Rata läpäisty ajassa %%duration%%!" +main_lobby.61="Yritä uudestaan rikkoaksesi aikasi tai yritä toista rataa!" +main_lobby.62="Hyvää työtä! Päihitit aiemman ennätyksesi %%time%%!" +main_lobby.63="Valitettavasti et ole rikkonut parasta aikaasi %%time%% vielä!" +main_lobby.64="Epäonnistuit pisteellä %%checkpoint%%/%%total%%" +main_lobby.65="EPÄONNISTUIT!" +main_lobby.66="SEURAAVA RATA" +main_lobby.67="%%remaining%% sekunnissa" +main_lobby.68="MENE!" +main_lobby.69="Valmistaudu!" +main_lobby.70="Kilpa alkaa %%seconds%% sekunnissa!" +main_lobby.71="Valittiin rata %%name%% ja sen tulostaulukot!" +main_lobby.72="Ilkeä pommi räjäytti sinut!" +main_lobby.73="Kurpitsanmätkijä 3000" +main_lobby.74="Käytetään kurpitsojen murskaamiseen. Antaa myös ikävän päähieronnan." +main_lobby.75="Luovuta" +main_lobby.76="Mätki kurpitsoja maalitauluihin!" +main_lobby.77="Aikaa jäljellä: %%timeleft%%" +main_lobby.78="Pisteet: %%score%%" +main_lobby.79="Kohde: %%percentCleared%%%" +main_lobby.80="Wuhuu! Selvisit siitä, ja pistemääräsi oli %%score%%!" +main_lobby.81="Yritä uudestaan rikkoaksesi ennätyksesi!" +main_lobby.82="Jeeee! Murskasit edellisen pistemääräsi, joka oli %%score%%!" +main_lobby.83="Valitettavasti et ole rikkonut parasta pistemäärääsi %%score%% vielä!" +main_lobby.84="Kuolit %%elapsed%% sekunnin jälkeen, pistemääräsi oli %%score%%!" +main_lobby.85="Kirjataan saavutuksen avaamisen yhteydessä" +main_lobby.86="SAAVUTUKSET" +main_lobby.87=" Hypixelissä" +main_lobby.88="1. Suorita tehtäviä:" +main_lobby.89=" %%underline%%SELAA TEHTÄVIÄ" +main_lobby.90="Klikkaa avataksesi Saavutusvalikon!" +main_lobby.91="2. Hanki pisteitä:" +main_lobby.92=" PISTEET: %%points%%" +main_lobby.93="Ne ovat saavutuspisteesi!" +main_lobby.94="3. Ansaitse Palkintoja:" +main_lobby.95=" %%underline%%NÄYTÄ PALKINNOT" +main_lobby.96="Klikkaa avataksesi \nSaavutuspalkintovalikon!" +main_lobby.97="Saavutusopas" +main_lobby.98="Kirjataan tasonnousun yhteydessä" +main_lobby.99="Top Hypixelin pelaajat" +main_lobby.100="Saavutuspisteet" +main_lobby.101="Saavutuspisteesi: %%points%%" +main_lobby.102="Hypixel-level" +main_lobby.103="Levelisi: %%level%%" +main_lobby.104="Päälobby: " +main_lobby.105="Löydetyt lahjat: " +main_lobby.106="Peeta" +main_lobby.107="KLIKKAA TELEPORTATAKSESI" +main_lobby.108="Turbo Bat Racers" +main_lobby.109="Koreja löydetty: " +main_lobby.110="Löysit jo tämän Karkkikorin!" +main_lobby.111="Löysit Karkkikorin!" +main_lobby.112="Onnittelut! Löysit kaikki Karkkikorit!" +main_lobby.113="Sait palkinnon sitoutumisestasi!" +main_lobby.114="Karkinmetsästyspalkinto" +main_lobby.115="Parhaan kokemuksen saavuttamiseksi klikkaa alla olevaa tekstiä asettaaksesi Lumipartikkelit päälle tässä lobbyssa!" +main_lobby.116="Klikkaa asettaaksesi Lumipartikkelit päälle" +main_lobby.117="Voit asettaa ne pois päältä koska tahansa komennolla /snow" +main_lobby.118="Et voi tehdä tuota juuri nyt." +main_lobby.119="Pääsiäismunat: " +main_lobby.120="Olet jo löytänyt tämän munan!" +main_lobby.121="Löysit pääsiäismunan!" +main_lobby.122="Munajahdin mahtava palkinto" +main_lobby.123="+%%achievement%% -saavutus!" +main_lobby.124="Onnittelut! Löysit kaikki pääsiäismunat!" +main_lobby.125="Pääsiäisopas" +main_lobby.126="PÄÄSIÄISMUNA LÄHISTÖLLÄ!" +main_lobby.127="Kalastusonki 3000" +main_lobby.128="Käytä tätä kalastaaksesi laiturilta kalastusmökin vieressä!" +main_lobby.129="Lohi" +main_lobby.130="Voi ei, emme voineet antaa sinulle kuumaa perunaa koska olit saanut sen jo aikaisemmin!" +main_lobby.131="Kalakokoelma" +main_lobby.132="Kalastustilastosi" +main_lobby.133=" - Kaloja napattu: %%amount%%" +main_lobby.134=" - Roskaa ongittu: %%amount%%" +main_lobby.135=" - Aarteita löydetty: %%amount%%" +main_lobby.136=" - Erikoiskaloja napattu: %%amount%%" +main_lobby.137="Käytä Kalastusonki 3000 kalastaaksesi takanasi olevalta laiturilta! Jos olet kyllin kärsivällinen, saatat jopa napata syvyyksistä joitain erikoisuuksia." +main_lobby.138="Tietoa kalastuksesta" +main_lobby.139="Napattu!" +main_lobby.140="???" +main_lobby.141="Ei napattu!" +main_lobby.142="???" +main_lobby.143="Hupskala" +main_lobby.144="Pallokalaemoji" +main_lobby.145="Nemo" +main_lobby.146="Taaksepäin heittävä limapallo" +main_lobby.147="Hai" +main_lobby.148="Kahen kilon siika" +main_lobby.149="Kuuma peruna" +main_lobby.150="Hups, väärä peli" +main_lobby.151="Ehkä hän on taas eksynyt?" +main_lobby.152="Täälläkö se siis on ollut koko ajan?" +main_lobby.153="Näyttää aika pieneltä." +main_lobby.154="Tulukaa kahtoon!" +main_lobby.155="On se se, se se on!" +main_lobby.156="Eniten napattu: %%mode%%" +main_lobby.157="Kalastusmökki ei ole tällä hetkellä aktiivinen!" +main_lobby.158="Tule takaisin toiste!" +main_lobby.159="Kalakauppiaan asun hattu" +main_lobby.160="Kalakauppiaan asun rintapanssari" +main_lobby.161="Kalakauppiaan asun housut" +main_lobby.162="Kalakauppiaan asun kengät" +main_lobby.163="Huikala" +main_lobby.164="Suklaapatukka" +main_lobby.165="Kurpitsalatte" +main_lobby.166="Vau, niin pelottavaa!" +main_lobby.167="Saattaa olla hieman kostea." +main_lobby.168="Ei olisi syksy ilman kurpitsamaustetta." +main_lobby.169="Yhteensä" +main_lobby.170="Valitse kosmeettisia esineitä Keräilyesinevalikosta!" +main_lobby.171="Lunasta tämä SkyBlock-kala Jerryltäsi!" +main_lobby.172="%%festival%%kala" +main_lobby.173="Lobbyn kosmeettinen esine" +main_lobby.174="Apple Bobbing" +main_lobby.175="Parhaat %%mode%% -pisteet" +main_lobby.176="Joku pelaa jo tätä peliä! Odota, että hänen pelinsä päättyy!" +main_lobby.177="Apple Bobbing" +main_lobby.178="%%who%% PELAA TÄTÄ" +main_lobby.179="Hypi ja nappaa niin monta omenaa kuin voit!" +main_lobby.180="Huu! Sait %%score%% pistettä!" +main_lobby.181="Lopetit pelattuasi\n%%elapsed%%\nsekuntia keräten\n%%score%%pistettä!" +main_lobby.182="VÄISTÄ TÄMÄ!" +main_lobby.183="ISKE TÄMÄ KOHTEESEEN" +main_lobby.184="Ansaitse kosmeettisia esineitä!" +main_lobby.185="EPÄKUOLLEIDEN\nAMPUMARATA" +main_lobby.186="Ansaitse 333 pistettä ennen 1 min" +main_lobby.187="ansaitaksesi 10 saavutuspistettä" +main_lobby.188="Turbo Bat Racers" +main_lobby.189="Portaita ylös!" +main_lobby.190="Pisteet 1 minuutin jälkeen" +main_lobby.191="Pisteet 3 minuutin jälkeen" +main_lobby.192="Ei päivity välittömästi" +main_lobby.193="PARHAAT PISTEET %%year%%" +main_lobby.194="Oi katso, likainen kypärä." +main_lobby.195="Siinäpä vasta likainen paita." +main_lobby.196="Iljettävät, sammaleiset housut." +main_lobby.197="Nämä saappaat ovat hajoamaisillaan." +main_lobby.198="NÄKYMÄTÖN KÄYTTÄJÄ PELAAMASSA" +main_lobby.199="Vau, onkeesi tarttui %%color%%%%item%%! %%lore%%" +main_lobby.200="Vau, onkeesi tarttui %%color%%%%item%%! %%lore%%" +main_lobby.201="Pelaajan %%name%% onkeen tarttui %%color%%%%item%%! %%lore%%" +main_lobby.202="Pelaajan %%name%% onkeen tarttui %%color%%%%item%%! %%lore%%" +main_lobby.203="Vilukala" +main_lobby.204="BrrRrRRr" +main_lobby.205="Jäätynyt kala" +main_lobby.206="Lämmitä mikrossa 30 sekuntia." +main_lobby.207="Jouluinen pallokalahattu" +main_lobby.208="Katso tätä söpöä hattua!" +main_lobby.209="Tässä lobbyssa on liikaa veneitä! Yritä myöhemmin uudelleen." +main_lobby.210="Sinulla oli jo vene hetki sitten!" +main_lobby.211="Kyllä kapteeni! Tässä on veneesi!" +main_lobby.212="Munakala" +main_lobby.213="Älä riko sitä, se hajoaa herkästi!" +main_lobby.214="Särkynyt muna" +main_lobby.215="Kanaparka. :(" +main_lobby.216="Raaka kinkku" +main_lobby.217="No, eipähän tarvitse lähteä kauppaan." +main_lobby.218="Syötä se kanille!" +main_lobby.219="Märkä pääsiäispulla" +main_lobby.220="Opettelethan nauhurilta soivan kappaleen." +main_lobby.221="Onkipäivitykset" +main_lobby.222="Lisää kalastusnopeutta" +main_lobby.223="Lisää mahdollisuutta kalastaa aarteita" +main_lobby.224="Lisää hieman mahdollisuutta kalastaa erikoiskaloja" +main_lobby.225="Päivitä kalastusonkesi lumouksia!" +main_lobby.226="Onkipäivitykset" +main_lobby.227="Vaaditut kalat" +main_lobby.228="Vaaditut aarteet" +main_lobby.229="Vaaditut roskat" +main_lobby.230="Lumoustaso oli liian korkea tilastoihisi nähden, ja sitä laskettiin!" +main_lobby.231="Olet jo lunastanut tämän päivityksen!" +main_lobby.232="Kalastusonkesi päivitettiin lumouksella %%enchantName%% %%enchantTier%%!" +main_lobby.233="Et täytä vielä vaatimuksia!" +main_lobby.234="Kalastuspalkinnot" +main_lobby.235="Kausitapahtumien aikana saatavilla olevat palkinnot!" +main_lobby.236="Olet jo lunastanut nämä palkinnot!" +main_lobby.237="Lunastit palkinnon %%name%%!" +main_lobby.238="Kultainen pallokalahattu" +main_lobby.239="Kannettava lampi -vempain" +main_lobby.240="Kokenut kalastaja -viiri" +main_lobby.241="Merirokko" +main_lobby.242="Se on kasvanut sinuun kiinni." +main_lobby.243="Leviathan" +main_lobby.244="No siinäpä todella saalis!" +main_lobby.245="Tähdensyöjän suomut" +main_lobby.246="Destiny on kohtalosi." +main_lobby.247="Aurinkovoide" +main_lobby.248="Turvallisuus ensin!" +main_lobby.249="Aivan kuten rannalla!" +main_lobby.250="Mahi-mahi" +main_lobby.251="Niin maukas!" +main_lobby.252="Viehe" +main_lobby.253="Meren onni" +main_lobby.254="Keräilijä" +main_lobby.255="Ilmoita bugeista ja jätä palautetta osoitteessa hypixel.net/ptl" +main_lobby.256="Sopii jälkiruoaksi!" +main_lobby.257="Silmämuna" +main_lobby.258="Miten tämä tänne päätyi..." +main_lobby.259="Suunnistajan kompassi" +main_lobby.260="Elämme kadonneiden aikaa; älä katoa itse." +main_lobby.261="Munatoti" +main_lobby.262="Nyt on se hetki, kun kaikki alkavat riidellä." +main_lobby.263="Kasvava lumipallo" +main_lobby.264="Oi miten sinua kaipaankaan..." +main_lobby.265="Kalastuslyöntiviesti" +main_lobby.266="Jouluinen kalaviiri" +main_lobby.267="KLIKKAA PELATAKSESI" +main_lobby.268="Tervetuloa Hypixeliin!" +main_lobby.269="Mitä haluaisit tehdä?" +main_lobby.270="1. %%underline%%Vaihda kieli." +main_lobby.271="Klikkaa vaihtaaksesi kielesi" +main_lobby.272="2. %%underline%%Aloita tutoriaali." +main_lobby.273="Klikkaa aloittaaksesi tutoriaalin" +main_lobby.274="3. %%underline%%Pelaa pelejä." +main_lobby.275="Klikkaa teleportataksesi NPC-hahmojen luo." +main_lobby.276="%%underline%%Sulje tämä kirja." +main_lobby.277="Klikkaa sulkeaksesi tämän kirjan." +main_lobby.278="SkyBlock-saaresi on osa paljon suurempaa maailmankaikkeutta..." +main_lobby.279="Odotas, miten minä tänne päädyin?" +main_lobby.280="Jerry" +main_lobby.281="Näistä kaivoksista linna saa tarvitsemansa resurssit." +main_lobby.282="Voit lähteä ajelulle kaivosvaunulla, mutta ole varovainen! Matkalla saattaa olla mutka jos toinenkin!" +main_lobby.283="Lähde vuoristorata-ajelulle" +main_lobby.284="Pyöri karusellissa" +main_lobby.285="Olet jo kaivosvaunussa!" +main_lobby.286="Joku käytti tätä aivan vasta, odota muutama sekunti ennen kuin yrität uudelleen!" +main_lobby.287="Paina KYYKKY-näppäintä poistuaksesi Vuoristoradalta ja palataksesi sen alkuun!" +main_lobby.288="Paintball" +main_lobby.289="Kukapa ei pitäisi hauskoista Paintball-taistoista?" +main_lobby.290="Haasta ystäväsi, ja katsokaa kuka selviytyy!" +main_lobby.291="Harjoittele Paintballia ystäviesi kanssa!" +main_lobby.292="Paintballit" +main_lobby.293="Syötit oikean koodin!" +main_lobby.294="Tuo koodi oli väärä!" +main_lobby.295="Aarrearkku" +main_lobby.296="Saavutukset ovat haasteita, joita voi suorittaa ympäri Hypixelin palvelinta palkintoja vastaan!" +main_lobby.297="Voit tarkastella saavutustesi edistymistä koska tahansa puhumalla minulle uudelleen tai menemällä Profiilini-valikkoon." +main_lobby.298="Tervetuloa linnaan!" +main_lobby.299="Katso minne astut!" +main_lobby.300="Jatka matkaasi." +main_lobby.301="Vau, vartiointi on tylsää." +main_lobby.302="Minun on pidettävä vahtia." +main_lobby.303="Hmm." +main_lobby.304="Jalkani ovat väsyneet." +main_lobby.305="Vartija" +main_lobby.306="Jousiampuja" +main_lobby.307="Albus" +main_lobby.308="Kirjastonhoitaja Albus" +main_lobby.309="Shhh!" +main_lobby.310="Hiljaa, jotkut lukevat täällä!" +main_lobby.311="Kunnioita kirjaston sääntöjä!" +main_lobby.312="Voisitko kävellä hiljempaa?" +main_lobby.313="Kiitos, että kunnioitat sääntöjä." +main_lobby.314="Joidenkin todella pitäisi osata kunnioittaa hiljaisuutta." +main_lobby.315="Haluan vain lukea rauhassa." +main_lobby.316="Numero on %%number%%, toivottavasti ymmärrät mitä se tarkoittaa." +main_lobby.317="Kiitos kun kuuntelit, olet ansainnut kunnioitukseni." +main_lobby.318="Löysin kirjasta numeron %%number%%, joka liittyy jotenkin sinuun." +main_lobby.319="En ole varma mitä se tarkoittaa, mutta toivotan sinulle onnea!" +main_lobby.320="Eleanor" +main_lobby.321="Kirjastonhoitaja Eleanor" +main_lobby.322="Kiinnostaisiko kirja?" +main_lobby.323="Miten voin auttaa?" +main_lobby.324="Illybad" +main_lobby.325="Pianisti Illybad" +main_lobby.326="Buchard" +main_lobby.327="Leipuri Buchard" +main_lobby.328="Mikään ei voita maukasta kakkua!" +main_lobby.329="Mitähän jos tekisin donitsit mutakakkutaikinasta..." +main_lobby.330="*mutinaa jauhoista*" +main_lobby.331="Milloin tämä leipä oikein on valmis..." +main_lobby.332="Vankilakoira" +main_lobby.333="Hau!" +main_lobby.334="Vuh." +main_lobby.335="Auuuu!" +main_lobby.336="Daidalos" +main_lobby.337="Kuningas eksyi labyrinttiin jokin aika sitten." +main_lobby.338="Tunnelit avautuvat ja sulkeutuvat jatkuvasti tuossa salaperäisessä sokkelossa." +main_lobby.339="Olisikohan sitä mahdollista kartoittaa..." +main_lobby.340="Quinten" +main_lobby.341="Buchard tekee todella hyvää kakkua..." +main_lobby.342="Lordi Siopilos" +main_lobby.343="Tervetuloa! Olen jousien mestari!" +main_lobby.344="Minne kuningas on kadonnut..." +main_lobby.345="Kuinka voin auttaa?" +main_lobby.346="Lady Alikay" +main_lobby.347="Hei! Olen suunnittelun mestari!" +main_lobby.348="Näissä vanhoissa kirjoissa on oltava jotain..." +main_lobby.349="Miksi tässä täytyy olla matikkaa." +main_lobby.350="Lordi Uberhay" +main_lobby.351="Hei! Minä olen panssareiden mestari." +main_lobby.352="Meidän täytyy valmistautua..." +main_lobby.353="Mistä saisimme lisää varusteita?" +main_lobby.354="11. heinäkuuta 2019\n\nVuosien ajan SkyBlock on ollut yksi palvelimen kysytyimmistä pelimuodoista, ja tänään julkaisemme oman versiomme siitä Prototype Lobbyyn!" +main_lobby.355="21. syyskuuta 2012\n\nTervetuloa Hypixel.netiin. Se on tällä hetkellä Alfa-tilassa, joten kaikista virheistä ja ongelmista voi kertoa minulle!" +main_lobby.356="26. tammikuuta 2014\n\nPaljon uusia ominaisuuksia julkaistiin tänään! Ensinnäkin, guildit ovat vihdoin täällä, joten juhlitaan sitä!" +main_lobby.357="1. elokuuta 2014\n\nElokuun megapäivitys on täällä!" +main_lobby.358="21. helmikuuta 2015\n\nWarlords on nyt avoimessa betassa! Koko ylläpito on korjannut kiireisesti 3 tunnin Early Access -vaiheessa löytyneitä virheitä." +main_lobby.359="11. huhtikuuta 2015\n\nHypixeliläiset! Valmistautukaa PvP-kokemukseen, jollaista ei tällä palvelimella ole koskaan ennen nähty!!!" +main_lobby.360="14. kesäkuuta 2015\n\nSkyWars on nyt kaikkien pelattavissa palvelimella! Liity kompassista!" +main_lobby.361="20. elokuuta 2015\n\nMystery Boxit ovat täällä! Housing on täällä (betassa)! Uusi lemmikkijärjestelmä! Vanity Shop -uudistus!" +main_lobby.362="5. tammikuuta 2017\n\nMahtavia uutisia! Seuraavien päivien aikana julkaisemme Prototype Lobbyn (PTL) kaikille pelaajille." +main_lobby.363="20. helmikuuta 2017\n\nViimeisin pelitestauksemme on lisätty Hypixel Prototype Lobbyyn – esittelyssä Murder Mystery!" +main_lobby.364="27. kesäkuuta 2017\n\nSe on täällä viimein - Bed Wars on nyt julkaistu!" +main_lobby.365="27. heinäkuuta 2018\n\nTänään julkaisemme Guild-päivityksen! Se on yksi suurimmista päivityksistämme koskaan!" +main_lobby.366="13. joulukuuta 2018\n\nSunnuntaista lähtien olemme kaikki laskeneet päiviä, minuutteja ja jopa sekunteja siihen, kun ensimmäinen Hytale-traileri julkaistaan." +main_lobby.367="10. maaliskuuta 2021\n\nTänään julkistamme innoissamme aivan uuden ominaisuuden palvelimelle - Hypixel SMP!" +main_lobby.368="10. maaliskuuta 2022\n\nTänään olemme erittäin innoissamme voidessamme ilmoittaa, että virallinen Hypixel SkyBlock Wiki on saatavilla osoitteessa" +main_lobby.369="KLIKKAA LUKEAKSESI LISÄÄ" +main_lobby.370="Klikkaa nähdäksesi koko julkaisun!" +main_lobby.371="Tervetuloa laiturille!" +main_lobby.372="Täällä voit kalastaa aarteita ja roskaa, mutta saatat myös löytää kausittaisia erikoisuuksia!" +main_lobby.373="Klikkaa minua uudelleen saadaksesi onkesi!" +main_lobby.374="Laiturimestari" +main_lobby.375="Tervetuloa kalastusmökkiin!" +main_lobby.376="Täällä voit kalastaa kaikenlaista, puhu Laiturimestarille aloittaaksesi!" +main_lobby.377="Kalasta kadonneita aarteita!" +main_lobby.378="Vaihtaa koukkusi efektiä kalastaessasi päälobbyssa." +main_lobby.379="Tämän vaihtoehdon valitseminen poistaa Ongenkoukun jäljen käytöstä." +main_lobby.380="Et ole napannut tarpeeksi Erikoiskaloja tähän!" +main_lobby.381="Nappaa 1 erikoiskala" +main_lobby.382="Nappasit turskan!" +main_lobby.383="Nappasit lohen!" +main_lobby.384="Nappasit vuokkokalan!" +main_lobby.385="Nappasit pallokalan!" +main_lobby.386="Voi ei, koukkuusi takertui kulho!" +main_lobby.387="Voi ei, koukkuusi takertui nahkaa!" +main_lobby.388="Voi ei, koukkuusi takertui nahkasaappaat!" +main_lobby.389="Voi ei, koukkuusi takertui mädäntynyttä lihaa!" +main_lobby.390="Voi ei, koukkuusi takertui keppi!" +main_lobby.391="Voi ei, koukkuusi takertui lankaa!" +main_lobby.392="Voi ei, koukkuusi takertui luu!" +main_lobby.393="Voi ei, koukkuusi takertui mustepussi!" +main_lobby.394="Voi ei, koukkuusi takertui ansalankakoukku!" +main_lobby.395="Voi ei, koukkuusi takertui lumpeenlehti!" +main_lobby.396="Voi ei, koukkuusi takertui vesipullo!" +main_lobby.397="Voi ei, koukkuusi takertui rikkinäinen onki!" +main_lobby.398="Voi ei, koukkuusi takertui likomärkä paperinpala!" +main_lobby.399="Voi ei, koukkuusi takertui jäniksen nahka!" +main_lobby.400="Nostit syvyyksistä lumotun kirjan, se on aarre!" +main_lobby.401="Nostit syvyyksistä nimilapun, se on aarre!" +main_lobby.402="Nostit syvyyksistä satulan, se on aarre!" +main_lobby.403="Nostit syvyyksistä lumotun jousen, se on aarre!" +main_lobby.404="Nostit syvyyksistä lumotun ongen, se on aarre!" +main_lobby.405="Nostit syvyyksistä timantin, se on aarre!" +main_lobby.406="Nostit syvyyksistä timanttimiekan, se on aarre!" +main_lobby.407="Nostit syvyyksistä kultahakun, se on aarre!" +main_lobby.408="Nostit syvyyksistä kompassin, se on aarre!" +main_lobby.409="Nostit syvyyksistä smaragdin, se on aarre!" +main_lobby.410="Nappasit salaisen kalan!" +main_lobby.411="Nostit syvyyksistä %%amount%% pelin %%game%% kolikkoa!" +main_lobby.412="Nostit syvyyksistä %%amount%% Hypixel-experienceä!" +main_lobby.413="Roskisdyykkaaja" +main_lobby.414="Lisää mahdollisuutta kalastaa roskaa" +main_lobby.415="Kalastuksen tulostaulukko" +main_lobby.416="Kalakokoelmavalikko" +main_lobby.417="Näytä kalakokoelmasi, päivitä onkeasi, tarkastele tilastojasi, ja paljon muuta!" +main_lobby.418="Lunasta onki" +main_lobby.419="Ei saatavilla juuri nyt!" +main_lobby.420="Valitsit jäljen %%trail%%!" +main_lobby.421="Tämä jälki ei ole juuri nyt saatavilla!" +main_lobby.422="Ongenkoukun jäljet" +main_lobby.423="Lunasta onki" +main_lobby.424="Lunasta onki aloittaaksesi kalastuksen!" +main_lobby.425="Klikkaa lunastaaksesi!" +main_lobby.426="Mestarin palkintotaso I" +main_lobby.427="Mestarin palkintotaso II" +main_lobby.428="Mestarin palkintotaso III" +main_lobby.429="Kesäpalkintotaso I" +main_lobby.430="Kesäpalkintotaso II" +main_lobby.431="Kesäpalkintotaso III" +main_lobby.432="Kesäpalkintotaso IV" +main_lobby.433="Kesäpalkintotaso V" +main_lobby.434="Kesäpalkintotaso VI" +main_lobby.435="Kesäpalkintotaso VII" +main_lobby.436="Halloweenin palkintotaso I" +main_lobby.437="Halloweenin palkintotaso II" +main_lobby.438="Halloweenin palkintotaso III" +main_lobby.439="Halloweenin palkintotaso IV" +main_lobby.440="Halloweenin palkintotaso V" +main_lobby.441="Halloweenin palkintotaso VI" +main_lobby.442="Halloweenin palkintotaso VII" +main_lobby.443="Talvipalkintotaso I" +main_lobby.444="Talvipalkintotaso II" +main_lobby.445="Talvipalkintotaso III" +main_lobby.446="Talvipalkintotaso IV" +main_lobby.447="Talvipalkintotaso V" +main_lobby.448="Talvipalkintotaso VI" +main_lobby.449="Talvipalkintotaso VII" +main_lobby.450="Lopetettiin palkinnon %%reward%% seuranta." +main_lobby.451="Seurataan %%reward%%." +main_lobby.452="KYLLÄ" +main_lobby.453="EI" +main_lobby.454="Käytössä:" +main_lobby.455="Näköjään löysit labyrintin." +main_lobby.456="Tämä luolien verkosto kulkee koko lobbyn halki, ja sillä on monta ulos- ja sisäänkäyntiä." +main_lobby.457="Se yhdistää monta pistettä Hypixelin historiassa." +main_lobby.458="Emme ole kyenneet kartoittamaan jokaista tunnelia, mutta jos uskaltaudut syvemmälle, toivotan sinulle onnea!" +main_lobby.459="Saatat löytää muinaisia esineitä sieltä, täältä. Ehkä löydätkin ne kaikki!" +main_lobby.460="Kerää piilotettuja esineitä sokkelosta!" +main_lobby.461="Olet jo löytänyt tämän esineen!" +main_lobby.462="Löysit Labyrinttiesineen %%name%%!\nPuhu Lobby-tutkija Theseukselle tarkastellaksesi esineitäsi!" +main_lobby.463="Labyrinttiesineet" +main_lobby.464="Esineet edustavat pisteitä Hypixelin historiassa. Löydä ne kaikki labyrintista!" +main_lobby.465="Löydetty: %%color%%%%found%%/%%total%%" +main_lobby.466="Klikkaa nähdäksesi kokoelmasi!" +main_lobby.467="Seikkaile labyrintissa löytääksesi tämän esineen!" +main_lobby.468="LÖYDETTY!" +main_lobby.469="EI LÖYDETTY!" +main_lobby.470="v0.3.1 Prototyyppisädease" +main_lobby.471="Paradoksaalinen äärettömyyden jousi" +main_lobby.472="Kokeellinen turboahdettu mikroauto" +main_lobby.473="Kiistämättömän rikkauden ja kunnioituksen hattu" +main_lobby.474="Herobrinen miekka" +main_lobby.475="Murtunut kiitollisuuden golem" +main_lobby.476="Tylsynyt vampyyrin hammas" +main_lobby.477="Speleologin hakku" +main_lobby.478="Kavereita paikalla: %%friends%%" +main_lobby.479="Guildista paikalla: %%guild%%" +main_lobby.480="Guildista paikalla: Ei guildia!" +main_lobby.481="Kaikki pelit" +main_lobby.482="SUOSITTU" +main_lobby.483="Teleporttaa sinut tietylle alueelle." +main_lobby.484="Aktiviteetit:" +main_lobby.485="Olet jo täällä!" +main_lobby.486="Klikkaa teleportataksesi!" +main_lobby.487="Teleportattiin alueelle %%zone%%!" +main_lobby.488="Puhu Lobby-tutkijalle tai käytä komentoa /stuck päästäksesi takaisin spawnille!" +main_lobby.489="Klikkaa palataksesi spawnille!" +main_lobby.490="%%magic%%H Avasit Heittokoukkuvempaimen %%magic%%H\nLaita hiiri tämän viestin päälle saadaksesi tietää, miten sitä käytetään!" +main_lobby.491="Klikkaa tästä tai avaa tavaraluettelossasi oleva\nKeräilyesineet-valikko avataksesi Vempainvalikon." +main_lobby.492="Spawn" +main_lobby.493="Hei! Voit huomata tämän lobbyn olevan melko valtava astuessasi mukavan keskusalueemme ulkopuolelle." +main_lobby.494="Voin auttaa sinua pääsemään eri kohteisiin nopeammin, jos haluat!" +main_lobby.495="Minulla sattuu olemaan ylimääräinen Heittokoukkuvempain. josta saattaa myös olla apua." +main_lobby.496="Hauskaa tutkiskelua!" +main_lobby.497="Klikkaa NPC-hahmoja liittyäksesi peleihin!" +main_lobby.498="Tämä linna saattaa olla uusi tässä maassa, mutta se pitää sisällään monia salaisuuksia." +main_lobby.499="Muista tutkia jokainen huone!" +main_lobby.500="Tutki linnan salaisuuksia!" +main_lobby.501="Rauniot" +main_lobby.502="Nämä rauniot ovat olleet täällä pitkään, mutta valtaistuin on pysynyt ehjänä." +main_lobby.503="Vaikka se onkin kasvanut umpeen, voit silti tuntea sen historian." +main_lobby.504="Ehkä toiset pelaajat ovat olleet täällä, kun tämä rakennelma oli vielä kunnossa." +main_lobby.505="Kylä" +main_lobby.506="Tervetuloa kylään!" +main_lobby.507="Täällä suurin osa asukkaista elää, aivan linnan juurella." +main_lobby.508="Tutkithan myös linnaa, siellä on paljon piilotettuja salaisuuksia!" +main_lobby.509="Puhu minulle uudelleen, jos haluat palata spawnille!" +main_lobby.510="Maatila" +main_lobby.511="Tämä maatila tuottaa ruoan kylälle ja linnalle." +main_lobby.512="Täällä kasvatetaan paljon erilaisia kasveja!" +main_lobby.513="Satama" +main_lobby.514="Tämä satama on usein hyvin vilkas!" +main_lobby.515="Sataman kautta kuljetetaan meille paljon tavaraa, kuten esimerkiksi kaikki joulukoristeemme!" +main_lobby.516="Muinaiset patsaat" +main_lobby.517="Nämä patsaat ovat olleet täällä todella pitkään, lähes aikojen alusta saakka." +main_lobby.518="Joskus ne ovat olleet lobbyn korkeimpia rakennelmia, mutta ovat sittemmin häipyneet taka-alalle." +main_lobby.519="Ne kuitenkin jatkavat vartiointiaan kallioiden takana, useimpien pelaajien katseiden ulkopuolella." +main_lobby.520="Lobbytutkija Tom" +main_lobby.521="Lobbytutkija Oliver" +main_lobby.522="Lobbytutkija Charlotte" +main_lobby.523="Lobbytutkija Victoria" +main_lobby.524="Lobbytutkija Percy" +main_lobby.525="Lobbytutkija Theseus" +main_lobby.526="Lobbytutkija Nico" +main_lobby.527="Lobbytutkija Lily" +main_lobby.528="Lobbytutkija Sophia" +main_lobby.529="Lobbytutkija Iris" +main_lobby.530="Lobbytutkija Simon" +main_lobby.531="Alueteleportteri" +main_lobby.532="Tutkimaton alue" +main_lobby.533="Tutki lobbya löytääksesi ja avataksesi tämän alueen!" +main_lobby.534="Et ole löytänyt tätä aluetta vielä, tutki lobbya löytääksesi sen!" +main_lobby.535="%%magic%%H Löysit alueen %%zone%%! %%magic%%H" +main_lobby.536="Palaa spawnille" +main_lobby.537="Matkusta kohteeseen:" +main_lobby.538="SkyBlock" +main_lobby.539="Halloween-opas" +main_lobby.540="Onkija" +main_lobby.541="Se näyttää aika pelottavalta." +main_lobby.542="Savipallo" +main_lobby.543="Eihän tuo ole muna!" +main_lobby.544="Vesisyntyisestä kauneudesta." +main_lobby.545="Kirsikankukka" +main_lobby.546="Niin nätti!" +main_lobby.547="Vaihda onkesi koukussa kalastaessa näkyviä partikkeleita." +main_lobby.548="Nappaa 1 aarre-esine" +main_lobby.549="Et ole napannut tarpeeksi aarteita tähän!" +main_lobby.550="Et ole napannut tarpeeksi roskaa tähän!" +main_lobby.551="Nappaa 1 roskaesine" +main_lobby.552="Aarteen loisto" +main_lobby.553="Rakastettu roska" +main_lobby.554="Kuka päästi nämä äänekkäät suut kirjastooni?" +main_lobby.555="En tiedä keitä nämä adminit ovat, mutta heidänkin täytyy noudattaa sääntöjä!" +main_lobby.556="Kuka päästi nämä ihmiset keittiööni??" +main_lobby.557="Hei! Älä polta sitä!" +main_lobby.558="Vaaditut erikoiskalat" +main_lobby.559="Kesäopas" +main_lobby.560="Tervetuloa Hypixelin %%festival%%tapahtumaan!" +main_lobby.561="Ansaitse Event Experienceä pelaamalla pelejä ja suorittamalla tehtäviä." +main_lobby.562="Mitä enemmän nouset tasoissa, sitä hienompia palkintoja voit avata!" +main_lobby.563="Seuraa edistymistäsi klikkaamalla minua uudestaan tai menemällä Profiilini-valikkoon!" +main_lobby.564="Tutustu uusimpaan uutispostaukseemme, jossa kerromme tästä tapahtumasta tarkemmin!" +main_lobby.565="Klikkaa avataksesi!" +main_lobby.566="Pidä silmällä sivustoamme tapahtuman uutispostauksen varalta!" +main_lobby.567="Uutispostaus tulossa!" +main_lobby.568="Event-sivu" +main_lobby.569="EVENT-" +main_lobby.570="SIVUN" +main_lobby.571="Klikkaa alta avataksesi koko Event-sivun!" +main_lobby.572="Hohtava mehiläispesä" +main_lobby.573="Se hohtaa!" +main_lobby.574="Kesäpalkintotaso VIII" +main_lobby.575="Pallokalalemmikki" +main_lobby.576="Event-level: %%color%%%%level%%" +main_lobby.577="Onnistui!" +main_lobby.578="Arkhimedeen jälki" +main_lobby.579="Et ole deaktivoinut helmeä %%orb%% tarpeeksi monta kertaa!" +main_lobby.580="Nostit syvyyksistä %%color%%%%amount%% Event Experienceä!" +main_lobby.581="Harvinaisuus: %%rarity%%" +main_lobby.582="Deaktivoinnit: %%count%%" +main_lobby.583="Löydetty!" +main_lobby.584="Ei löydetty!" +main_lobby.585="Epätavallinen" +main_lobby.586="Äärimmäisen harvinainen" +main_lobby.587="Nyksin varjo" +main_lobby.588="Afroditen sydän" +main_lobby.589="Zeuksen kipinä" +main_lobby.590="Voi ei, koukkuusi takertui palanutta lihaa!" +main_lobby.591="Voi ei, koukkuusi takertui puuhiiltä!" +main_lobby.592="Klikkaa tarkastellaksesi tätä Kausittaisjulkaisu-uutista" +main_lobby.593="Tätä käytetään Päälobbyn kalastusongen päivittämiseen." +main_lobby.594="Hypixel-levelopas" +main_lobby.595="Nappasit paistetun turskan!" +main_lobby.596="Vulkanuksen laiturimestari" +main_lobby.597="Käytössä:" +main_lobby.598="Epäonnistui!" +main_lobby.599="%%magic%%H Avasit Vulkanuksen siunaus -lumouksen! %%magic%%H\nLunasta se Ongen lumoukset -valikossa." +main_lobby.600="Nostit syvyyksistä kultamiekan, se on aarre!" +main_lobby.601="Parannus prosessi" +main_lobby.602="Klikkaa nähdäksesi esineen tilastot!" +main_lobby.603="Löydä ne kaikki ansaitaksesi mahtavan palkinnon!" +main_lobby.604="Ympäristö: %%color%%%%environment%%" +main_lobby.605="Kalastustilastot: Kaikki" +main_lobby.606="Klikkaa nähdäksesi lisää tilastoja!" +main_lobby.607="Voit yrittää uudelleen!" +main_lobby.608="Pidä silmällä sivustoamme hypixel.net tapahtuman uutispostauksen varalta!" +main_lobby.609="Et voi käyttää kosmeettisia esineitä tällä alueella!" +main_lobby.610="Aarteita löydetty: %%amount%%" +main_lobby.611="Kaloja napattu: %%amount%%" +main_lobby.612="Nostit syvyyksistä sulaa kultaa, se on aarre!" +main_lobby.613="Ongenkoukun jäljet" +main_lobby.614="%%magic%%H Sait Aurinkotitaanin liekin %%magic%%H" +main_lobby.615="Tuo koodi on vanhentunut!" +main_lobby.616="Nappasit hiiltyneen pallokalan!" +main_lobby.617="Aurinkotitaanin liekki" +main_lobby.618="Nostit syvyyksistä ender-silmän, se on aarre!" +main_lobby.619="Saavutusopas" +main_lobby.620="Voi ei, koukkuusi takertui pihvi!" +main_lobby.621="Käytä komentoa /presents" +main_lobby.622="Voi ei, koukkuusi takertui laavaämpäri!" +main_lobby.623="KLIKKAA LUNASTAAKSESI" +main_lobby.624="Et voi käyttää tuota vuoristoradalla!" +main_lobby.625="Kalastuksen koko tulostaulukko" +main_lobby.626="Ei kiltaa!" +main_lobby.627="Löytöpaikka: %%color%%%%environment%%" +main_lobby.628="Jokin meni vikaan puhuessasi tuolle NPC-hahmolle!" +main_lobby.629="Voi ei, koukkuusi takertui nether-tiili!" +main_lobby.630="Tulensiedätysprosessi epäonnistui!\nPuhu Vulkanuksen laiturimestarille yrittääksesi uudelleen." +main_lobby.631="KLIKKAA PELATAKSESI" +main_lobby.632="Nappasit paistetun lohen!" +main_lobby.633="Klikkaa nähdäksesi päivitykset!" +main_lobby.634="[NPC] %%name%%" +main_lobby.635="Nostit syvyyksistä roihusauvan, se on aarre!" +main_lobby.636="Vuoristorata on tällä hetkellä poissa käytöstä, palaa pian takaisin!" +main_lobby.637="Syötettiin koodi %%code%%" +main_lobby.638="Voi ei, koukkuusi takertui hiiltä!" +main_lobby.639="Nostit syvyyksistä rengashaarniskan rintapanssarin, se on aarre!" +main_lobby.640="Lumouksen %%enchant%% päivitykset" +main_lobby.641="Nostit syvyyksistä roihujauhetta, se on aarre!" +main_lobby.642="%%magic%%H %%reward%% Edistyminen: %%amountHas%%/%%amountNeeded%%" +main_lobby.643="Nostit syvyyksistä magmavoidetta, se on aarre!" +main_lobby.644="Ongen lumoukset" +main_lobby.645="10 lohen suomua" +main_lobby.646="%%second%%s" +main_lobby.647="Ei voida teleportata sinua juuri nyt, yritä uudelleen hetken kuluttua!" +main_lobby.648="%%magic%%H Keräsit 10 lohen suomua %%magic%%H" +main_lobby.649="Palkintoja omistautuneesta kalastuksesta!" +main_lobby.650="Guild-opas" +main_lobby.651="Pahoitteluni, minulla on vaikeuksia lähettää sinua kohteeseen %%name%% - anna minulle hetki!" +main_lobby.652="Ei yhtään napattu!" +main_lobby.653="Löydä ne kaikki ansaitaksesi superpalkinnon!" +main_lobby.654="%%magic%%H Avasit Heittokoukkuvempaimen %%magic%%H\nLaita hiiri tämän viestin päälle saadaksesi tietää, miten sitä käytetään!" +main_lobby.655="Et ole löytänyt tätä ainesosaa vielä!" +main_lobby.656="Poistettiin lumipartikkelit käytöstä! Voit ottaa ne käyttöön koska tahansa komennolla /snow!" +main_lobby.657="Voi ei, koukkuusi takertui käynyt hämähäkinsilmä!" +main_lobby.658="Otettiin lumipartikkelit käyttöön! Voit asettaa ne pois päältä koska tahansa komennolla /snow!" +main_lobby.659="Et voi käyttää tätä vempainta täällä!" +main_lobby.660="Et ole vielä napannut yhtään erikoiskalaa!" +main_lobby.661="Halloween-kallopakkaus" +main_lobby.662="Tämä pakkaus sisältää karmivia kalloja, joita voit käyttää Housing-tontillasi!" +main_lobby.663="Työstä 10 000 Arcade-kolikkoa!" +main_lobby.664="Työstä 1000 Hypixel-experienceä!" +main_lobby.665="Työstä 10 SkyWars-sielua!" +main_lobby.666="Työstä 2500 Bed Wars -kolikkoa!" +main_lobby.667="Pelästynyt-lyöntiviesti" +main_lobby.668="Työstä Pelästynyt-lyöntiviesti, jota MVP+-pelaajat voivat käyttää ylläpidon jäseniin!" +main_lobby.669="Ongen lumoukset" +main_lobby.670="Linna" +main_lobby.671="Kaivos" +main_lobby.672="Labyrintti" +main_lobby.673="Paintball-taisto" +main_lobby.674="Kalastusmökki" +main_lobby.675="Halloween-tapahtuma" +main_lobby.676="Joulutapahtuma" +main_lobby.677="Pääsiäistapahtuma" +main_lobby.678="Kesätapahtuma" +main_lobby.679="Käynnissä ei ole yhtään tapahtumaa!" +main_lobby.680="Päälobbyn aktiviteetit" +main_lobby.681="Päälobbyn aktiviteetit" +main_lobby.682="Katso mitä aktiviteettejä päälobbyssa on tämän tapahtuman aikaan!" +main_lobby.683="Löydä tämä aktiviteetti lobbysta!" +main_lobby.684="Tämä aktiviteetti ei ole juuri nyt saatavilla!" +main_lobby.685="Klikkaa tästä teleportataksesi takaisin Tapahtumaoppaan luo!" +main_lobby.686="Karkkijahti" +main_lobby.687="Etsi karkkikoreja lobbysta ansaitaksesi palkinnon!" +main_lobby.688="Jousiammunta" +main_lobby.689="Käytä zombeja harjoitusmaalitauluina kilpaillessasi sijoituksista!" +main_lobby.690="Pumpkin Smash" +main_lobby.691="Mäiski kurpitsoja maalitauluihin ansaitaksesi pisteitä, mutta varo ilkeitä pommeja!" +main_lobby.692="Turbo Bat Racers" +main_lobby.693="Ratsasta lepakollasi lobbyn halki kulkevan esteradan läpi - saatavilla eri vaikeustasoja." +main_lobby.694="Noidan pata" +main_lobby.695="Löydä piilotettuja ainesosia ja hauduta reseptejä saadaksesi ainutlaatuisia esineitä Noidan padasta!" +main_lobby.696="Kalastus" +main_lobby.697="Kalasta aarteita ja kausittain saatavia kaloja ympäri lobbya. Täytä kokoelma!" +main_lobby.698="Hauskaa kevättä!" +main_lobby.699="Pidä mahtava kevät!" +main_lobby.700="Rakastan tätä vuodenaikaa!" +main_lobby.701="Harmi, että joudun istumaan tässä." +main_lobby.702="Säikähditkö?" +main_lobby.703="Vanhentunut holvin koodi: 372" +main_lobby.704="Ei tapahtumaa!" +main_lobby.705="Hiekkakasa" +main_lobby.706="Kumiankka" +main_lobby.707="Tämän ei pitäisi olla täällä!" +main_lobby.708="Sulaa rautaa" +main_lobby.709="Onko täällä kuuma?" +main_lobby.710="Tavallinen kala" +main_lobby.711="Odotas, mitä?" +main_lobby.712="Laavahai" +main_lobby.713="Jopa pelottavampi kuin tavallinen hai!" +main_lobby.714="Smaragdinen ongenkoukun jälki" +main_lobby.715="Legendaarinen viiri: Kalastaja" +main_lobby.716="Legendaarinen status: Kalastaja" +main_lobby.717="Akvaariokaapu" +main_lobby.718="Pelästynyt pallokala -hattu" +main_lobby.719="Karmiva kala -vempain" +main_lobby.720="Karmiva kalastaja -viiri" +main_lobby.721="Kalakaapu" +main_lobby.722="Haadeksen koukku" +main_lobby.723="Puhu Järven neidolle oppiaksesi kalastamaan jääkaloja Päälobbyssa! Saatavilla vain joulutapahtuman ajan!" +main_lobby.724="Järven neito" +main_lobby.725="Järven neito" +main_lobby.726="Kalastustilastosi: %%color%%%%environment%%" +main_lobby.727="Virheellinen kalastusympäristö! Käytä yhtä seuraavista tai jätä tyhjäksi yhteenlaskettuja tilastoja varten: %%options%%" +main_lobby.728="Laavassa kalastaminen vaatii Vulkanuksen siunaus -lumouksen.\nPuhu Vulkanuksen laiturimestarille saadaksesi lisätietoa!" +main_lobby.729="Jää on liian paksua rikottavaksi tässä kohtaa. Kokeile vuoriston lampia!" +main_lobby.730="Vesi on jäätynyt, mutta jää on ohutta. Puhu Järven neidolle saadaksesi lisätietoa Neptunuksen raivo -lumouksesta." +main_lobby.731="Napataksesi kylmän veden kaloja sinulla täytyy olla Neptunuksen raivo -lumous, joten puhu Järven neidolle.\nSaat tällä hetkellä vain tavallisia kaloja." +main_lobby.732="Et ole napannut tarpeeksi kaloja JÄÄSSÄ tätä varten!" +main_lobby.733="Tämä esine oli saatavilla vain tapahtuman %%event%% %%year%% ajan." +main_lobby.734="Nappaa 1 kala AVANNOSTA" +main_lobby.735="Nappaa %%amount%% kalaa AVANNOSTA" +main_lobby.736="Ei saatavilla" +main_lobby.737="Muuttaa ongen tavaraluettelossasi." +main_lobby.738="Jäinen onki" +main_lobby.739="Muuta onkeasi tavaraluettelossasi ja tekstissä, joka näkyy napatessasi erikoiskalan!" +main_lobby.740="Tämä esine ei ole saatavilla tapahtuman %%event%% %%year%% jälkeen!" +main_lobby.741="Nappasit taimenen!" +main_lobby.742="Nappasit ahvenen!" +main_lobby.743="Nappasit hauen!" +main_lobby.744="Voi ei, koukkuusi takertui lumipallo!" +main_lobby.745="Voi ei, koukkuusi takertui jäänsiru!" +main_lobby.746="Voi ei, koukkuusi tarttui kasa lehtiä!" +main_lobby.747="Voi ei, koukkuusi takertui jäätynyttä lihaa!" +main_lobby.748="Nostit syvyyksistä rautamiekan, se on aarre!" +main_lobby.749="Kalastusonki: %%rod%%" +main_lobby.750="Antaa mahdollisuuden kalastaa avannosta." +main_lobby.751="Neptunuksen raivo" +main_lobby.752="Puhu Järven neidolle Jääkalastusalueella Joulutapahtuman aikana joulukuussa." +main_lobby.753="Jäätynyt ateria" +main_lobby.754="Välitön illallinen!" +main_lobby.755="Jouluvalot" +main_lobby.756="Vaatii vain pientä selvittämistä." +main_lobby.757="Valikon asetukset" +main_lobby.758="Kalakokoelmavalikon asetukset." +main_lobby.759="Nappaamattomat kalat: %%toggle%%" +main_lobby.760="Piilotettu" +main_lobby.761="Näkyvillä" +main_lobby.762="Valikon kuvakkeet: %%toggle%%" +main_lobby.763="Tavalliset" +main_lobby.764="Yksinkertaistetut" +main_lobby.765="Klikkaa vaihtaaksesi nappaamattomien kalojen tilaa!" +main_lobby.766="Oikeaklikkaa vaihtaaksesi valikon kuvakkeiden tilaa!" +main_lobby.767="Veden jäätyessä elämä pinnan alla ei katoa mihinkään." +main_lobby.768="Lähistöllä on muutama lampi, joissa elää kaloja, jotka pitävät kylmästä, mutta elävät piilossa jään alla." +main_lobby.769="Jää on kuitenkin ohutta." +main_lobby.770="Tässä on lumous, jolla voit rikkoa jään ja nostaa piileviä salaisuuksia syvältä kylmän lammen pohjasta." +main_lobby.771="Valitsit esineen %%cosmetic%%!" +main_lobby.772="Tämä esine ei ole juuri nyt saatavilla!" +main_lobby.773="Tämä ympäristö on saatavilla vain tiettyjen kausitapahtumien aikaan." +main_lobby.774="Kalastustilastot: %%color%%%%environment%%" +main_lobby.775="Mestarin palkintotaso IV" +main_lobby.776="Vilukala 3" +main_lobby.777="Kaveriopas" +main_lobby.778="Hypixel-levelopas" +main_lobby.779="Guild-opas" +main_lobby.780="Vaihda onkesi koukussa kalastettaessa näkyviä partikkeleita." +main_lobby.781="Onkivavat" +main_lobby.782="Et ole avannut tätä palkintoa vielä!" +main_lobby.783="Eventin kalastuspalkinto" +main_lobby.784="Kesän kalastuspalkinto" +main_lobby.785="Halloweenin kalastuspalkinto" +main_lobby.786="Joulun kalastuspalkinto" +main_lobby.787="Pääsiäisen kalastuspalkinto" +main_lobby.788="Kevään onki" +main_lobby.789="Pääsiäisen palkintotaso I" +main_lobby.790="Pääsiäisen palkintotaso II" +main_lobby.791="Pääsiäisen palkintotaso III" +main_lobby.792="Kausittaisen kalastuspalkinnon seuranta poistettiin käytöstä, koska se ei ole enää saatavilla!" +main_lobby.793="Palkinnon seuranta poistettiin käytöstä, koska lunastit sen." +main_lobby.794="%%magic%%H %%reward%% Edistyminen: SUORITETTU!" +main_lobby.795="Löydä kimmeltäviä piilotettuja pääsiäismunia ympäri lobbya saadaksesi palkinnon!" +main_lobby.796="Etsi piilotettuja pääsiäismunia ympäri lobbya saadaksesi palkinnon!" +main_lobby.797="Päälobbyn kalastus" +main_lobby.798="LUKITTU %%amountHas%%/%%amountReq%% %%dropType%%" +main_lobby.799="Vaaditut %%dropType%%: %%amount%%" +main_lobby.800="Myyttiset kalat" +main_lobby.801="Löydä salaperäisiä kaloja syvältä veden alta." +main_lobby.802="Salaperäinen ja voimakas kala." +main_lobby.803="Salaperäinen kala, jonka voi napata Myyttinen koukku -lumouksella." +main_lobby.804="Myyttisiä kaloja napattu: %%amount%%" +main_lobby.805=" - Myyttisiä kaloja napattu: %%amount%%" +main_lobby.806="Myyttiset kalat" +main_lobby.807="Myyttinen koukku" +main_lobby.808="Antaa mahdollisuuden kalastaa myyttisiä kaloja" +main_lobby.809="Ei löydetty!" +main_lobby.810="Löysit ainesosan %%ingredient%%!\nKäytä sitä Noidan padalla lähellä spawnia!" +main_lobby.811="Klikkaa minua!" +main_lobby.812="HYPPÄÄ" +main_lobby.813="Olet jo työstänyt tämän!" +main_lobby.814=" HYVÄÄ PÄÄSIÄISTÄ" +main_lobby.815="Klikkaa omistamiasi ainesosia täyttääksesi reseptin!" +main_lobby.816="Klikkaa lisätäksesi!" +main_lobby.817="Painoennätys: %%weight%%" +main_lobby.818="KARMIVAA HALLOWEENIA" +main_lobby.819="Hups! Yritä myöhemmin uudelleen!" +main_lobby.820="Ominaisuudet:" +main_lobby.821="Lobbyn ominaisuudet:" +main_lobby.822="Lumipallot" +main_lobby.823="Työstit esineen %%name%%!" +main_lobby.824="Resepti:" +main_lobby.825="Klikkaa tästä lukeaksesi uutispostauksen!" +main_lobby.826="ONNISTUIT!" +main_lobby.827="Teleportattu takaisin spawnille!" +main_lobby.828="Hypixelissä" +main_lobby.829="Ei ainesosia!" +main_lobby.830=" %%underline%%LUE LISÄÄ" +main_lobby.831="LUNASTETTU" +main_lobby.832="Tallentamaton" +main_lobby.833="Et ole työstänyt tätä!" +main_lobby.834="Resepti ei kelpaa!" +main_lobby.835="Nappaa %%orb%% kerran" +main_lobby.836="Kalastuspalkinnot ovat juuri nyt poissa käytöstä, palaa pian takaisin!" +main_lobby.837="Vuosittaiset ennätykset" +main_lobby.838="Pisteet: %%points%% - Osumat: %%hits%% - Aika: %%time%%" +main_lobby.839=" %%underline%%LISÄTIETOA PIAN" +main_lobby.840="Kelpaavaa reseptiä ei ole syötetty!" +main_lobby.841=" ✦ PELI-ILMOITUS HYPIXELILTÄ ✦" +main_lobby.842="Kalastusvalikko" +main_lobby.843="Löydä tämä ainesosa lobbysta!" +main_lobby.844="Napattu: %%count%%" +main_lobby.845="Löydä hohtavia piilotettuja karkkikoreja lobbysta saadaksesi palkinnon!" +main_lobby.846="Nappasit %%weight%% kg painoisen myyttisen kalan %%mythicalFish%%!" +main_lobby.847="Lumipallo" +main_lobby.848="Löysit %%color%% villaa!" +main_lobby.849="Sinun täytyy löytää kaikki %%total%% villaa, jotka on piilotettu ympäri Päälobbya päästäksesi Holviin! Olet löytänyt tähän mennessä %%found%%." +main_lobby.850="Myös Hypixelissä:" +main_lobby.851="Klikkaa poistaaksesi!" +main_lobby.852="Kaikki kalastus" +main_lobby.853="Viikoittaiset ennätykset" +main_lobby.854="Ympäristö: %%color%%%%environment%% | Tyyppi:%%dropColor%%%%drop%%" +main_lobby.855="PALKINNOT POISSA KÄYTÖSTÄ" +main_lobby.856="Olet löytänyt kaikki villat, joten pääset nyt Holviin!" +main_lobby.857="Paikka: %%name%%" +main_lobby.858="Whoosh! Löysit kaikki %%total%% villaa, joten pääset nyt Holviin!" +main_lobby.859="%%festival%% %%year%%" +main_lobby.860="Olet jo löytänyt tämän ainesosan!" +main_lobby.861="Olet jo löytänyt tämän aaveen!" +main_lobby.862="Tyhjä paikka" +main_lobby.863="Kalastusonkesi päivitettiin lumouksella %%enchantName%%!" +main_lobby.864="Käytät jo tätä ainesosaa!" +main_lobby.865="KLIKKAA TÄSTÄ!" +main_lobby.866="%%player%% nappasi ÄÄRIMMÄISEN HARVINAISEN myyttisen kalan %%mythicalFish%%!" +main_lobby.867="Ei guildia!" +main_lobby.868="Tämä reseptiyhdistelmä ei kelpaa!" +main_lobby.869="Myyttinen kala nousee syvyyksistä!" +main_lobby.870="Käytät jo tätä!" +main_lobby.871="Et voi ratsastaa lemmikillä pelatessasi!" +main_lobby.872="UUSI PAINOENNÄTYS!" +main_lobby.873="Onnittelut! Löysit kaikki aaveet!" +main_lobby.874="Klikkaa alla olevia ainesosia työstääksesi!" +main_lobby.875="Löysit aaveen!" +main_lobby.876="Yhdistelmä nollattu!" +main_lobby.877="Kalastus – %%festival%% %%year%%" +main_lobby.878="Olet työstänyt tämän!" +main_lobby.879=" HYVÄÄ KESÄÄ" +main_lobby.880="Löydä kimaltelevia piilotettuja pääsiäismunia ympäri lobbya saadaksesi palkinnon!" +main_lobby.881="Padan reseptikirja" +main_lobby.882="Nappaa %%orb%% %%amount%% kertaa" +main_lobby.883="%%weight%%kg" +main_lobby.884="???" +main_lobby.885="Noidan pata" +main_lobby.886="%%magic%%H %%reward%% Edistyminen: %%amountHas%%/%%amountNeeded%% %%dropType%%" +main_lobby.887="Rikoit koukkusi ja myyttinen kala pääsi karkuun!" +main_lobby.888="Käytät juuri nyt tätä ainesosaa reseptissä!" +main_lobby.889="Onnittelut, syötit koodin onnistuneesti!" +main_lobby.890="Löydä ainesosia ympäri lobbya työstääksesi palkintoja! Saatko selville kaikki reseptit?" +main_lobby.891="Vuosittaiset ennätykset" +main_lobby.892="Tämä tapahtuma on ohi nyt, pahoittelut!" +main_lobby.893="Kala napsaisi siimasi poikki ja pääsi karkuun!" +main_lobby.894="Klikkaa nähdäksesi reseptisi!" +main_lobby.895="Varastosi on täynnä!" +main_lobby.896="Vedestä nousi %%weight%% kg painoinen %%mythicalFish%%!" +main_lobby.897="Siimasi napsahti poikki ja myyttinen kala pääsi karkuun!" +main_lobby.898="Jo työstetty!" +main_lobby.899="Kokeile käyttää eri ainesosia!" +main_lobby.900="Et ole napannut helmeä %%orb%% tarpeeksi montaa kertaa!" +main_lobby.901="Metsän kauhu" +main_lobby.902="Joenvarren kosto" +main_lobby.903="Kryptinen linna" +main_lobby.904="Epäkuolleiden jousiammunta" +main_lobby.905="Turbo Bat Racers" +main_lobby.906="Pumpkin Smash" +main_lobby.907="Epäkuolleiden jousiammunta" +main_lobby.908="Erikoiskalat" +main_lobby.909="Kerää kirjo ainutlaatuisia kaloja eri vuodenaikoina!" +main_lobby.910="Erikoiskalat" +main_lobby.911="Erikoiskalat ovat ainutlaatuisia kaloja, joita voit napata vain kerran." +main_lobby.912="Joitakin voit saada vuoden ympäri, mutta jotkin ilmestyvät vesistöihimme vain tiettyinä vuodenaikoina ja tietyissä kalastusympäristöissä." +main_lobby.913="Pystytkö nappaamaan ne kaikki?" +main_lobby.914="Myyttiset kalat" +main_lobby.915="Myyttinen kala on ainutlaatuinen kala, jota esiintyy erikoiskaloja enemmän." +main_lobby.916="Ne ovat ärhäkämpiä, ja sinun on taisteltava pyydystääksesi ne." +main_lobby.917="Napataksesi Myyttisen kalan sinun täytyy ottaa käyttöösi Myyttinen koukku -lumous." +main_lobby.918="Helioksen kekäle" +main_lobby.919="Onkivapa 3000" +main_lobby.920="Kummitusonki" +main_lobby.921="Tapahtumaopas" +main_lobby.922="Selenen tomu" +main_lobby.923="Lahjajahti" +main_lobby.924="Etsi piilotettuja lahjoja jokaisesta lobbysta Hypixelissä saadaksesi palkinnon!" +main_lobby.925="Löydä kimaltelevia piilotettuja lahjoja JOKAISESTA lobbysta saadaksesi palkinnon!" +main_lobby.926="Laskee kuinka kauan kalalla kestää ilmestyä." +main_lobby.927="Luettelo kaikista mahdollisuuksistasi, lumoukset mukaan laskettuina." +main_lobby.928="Suhteelliset mahdollisuudet tarkoittavat sinuun vaikuttavia mahdollisuuksia, joissa on laskettu mukaan kaikki muutkin laskutoimitukset." +main_lobby.929="Kaikki mahdollisuudet" +main_lobby.930="Tuloksesi:" +main_lobby.931="Harvinaisuusmahdollisuudet:" +main_lobby.932="%%chance%%%" +main_lobby.933="Ei viehettä" +main_lobby.934="%%type%%" +main_lobby.935="Min: %%minTime%%s" +main_lobby.936="Max: %%maxTime%%s - (Vieheen taso x %%decrementPer%%s)" +main_lobby.937="%%chance%%% + (Lumouksen %%enchant%% taso x %%chancePerLevel%%%%%gray%%)" +main_lobby.938="Selittää mahdollisuudet tälle kalastuksesta saatavalle esinetyypille." +main_lobby.939="Oletko kiinnostunut kalastuksen taustalla vaikuttavasta matematiikasta? Katso selityksiä laskutoimituksista ja niiden vaikutuksesta sinuun." +main_lobby.940="Ei lumousta %%enchant%%" +main_lobby.941="Kalastusaika" +main_lobby.942="%%chance%%% (%%enchantLevel%%)" +main_lobby.943="Klikkaa nähdäksesi matemaattiset selitykset!" +main_lobby.944="Perusmahdollisuuksissa ei oteta lukuun muita laskutoimituksia." +main_lobby.945="Max: %%maxTime%%s (%%lureLevel%%)" +main_lobby.946="%%chance%%% %%drop%%" +main_lobby.947="Perusmahdollisuudet:" +main_lobby.948="Kalastusmahdollisuuksien erittely" +main_lobby.949="Esimerkiksi, jos sinulla on korkea Meren onnen taso, luonnollisesti mahdollisuutesi kaikkeen muuhun laskee." +main_lobby.950="Min: %%minTime%%s" +main_lobby.951="Matematiikkaselite" +main_lobby.952="%%chance%%% %%drop%%" +main_lobby.953="Peruslaskutoimitus:" +main_lobby.954="Suhteelliset mahdollisuudet:" +main_lobby.955="Jouluinen onki" +main_lobby.956="kalastaminen Päälobbyssa" +main_lobby.957="Helioksen henkäys -jälki" +main_lobby.958="Roskakori" +main_lobby.959="Laita pyydetyt ainesosat uuniin." +main_lobby.960="Klikkaa tätä!" +#main_lobby.961="" +main_lobby.962="Et voi käyttää lobbyn kosmeettisia esineitä, kun pelaat!" +main_lobby.963="Estetty paikka" +main_lobby.964="MENE!" +main_lobby.965="Varastosi on täynnä!" +main_lobby.966="Sinulla ei ole oikeita ainesosia! Näet uunin päältä, mitä tarvitset!" +main_lobby.967="Leivoit yhteensä %%score%% herkun!" +main_lobby.968="Leivoit yhteensä %%score%% herkkua!" +#main_lobby.969="" +main_lobby.970="Valitettavasti et ole vielä päihittänyt parasta pistemäärääsi %%score%% vielä!" +main_lobby.971="Et voi pelata tätä, kun sinulla on Puku päällä!" +#main_lobby.972="" +main_lobby.973="KLIKKAA PELATAKSESI" +main_lobby.974="Ajastin aloitettu, leivo niin paljon herkkuja kuin pystyt!" +main_lobby.975="Pisteet: %%score%%" +main_lobby.976="Paras: %%score%%" +main_lobby.977="Jokin meni vikaan!" +main_lobby.978="Tervetuloa Hypixelin %%year%%%%suffix%%-vuotisjuhlaan!" +main_lobby.979="Joka vuosi me juhlimme vuosittaisella Bingo-aktiviteetilla." +main_lobby.980="Valitse pelikategoria, jota haluat pelata, ja suorita tavoitteet täyttääksesi bingokortit!" +main_lobby.981="Bingokorttien täyttäminen palkitsee sinut Bingo Buckseilla , joita voit käyttää eksklusiivisiin kosmeettisiin palkintoihin! ✅" +#main_lobby.982="" +main_lobby.983="Nappaa %%amount%% Erikoiskalaa (%%current%%/%%amount%%)" +#main_lobby.984="" +#main_lobby.985="" +#main_lobby.986="" +#main_lobby.987="" +#main_lobby.988="" +#main_lobby.989="" +#main_lobby.990="" +main_lobby.991="Klikkaa nähdäksesi palkinnot!" +#main_lobby.992="" +#main_lobby.993="" +#main_lobby.994="" +#main_lobby.995="" +#main_lobby.996="" +#main_lobby.997="" +#main_lobby.998="" +#main_lobby.999="" +#main_lobby.1000="" +#main_lobby.1001="" +#main_lobby.1002="" +#main_lobby.1003="" +main_lobby.1004="Onkivapa" +#main_lobby.1005="" +#main_lobby.1006="" +#main_lobby.1007="" +main_lobby.1008="Kasvi" +main_lobby.1009="Olento" +#main_lobby.1010="" +#main_lobby.1011="" +#main_lobby.1012="" +#main_lobby.1013="" +#main_lobby.1014="" +#main_lobby.1015="" +#main_lobby.1016="" +#main_lobby.1017="" +#main_lobby.1018="" +#main_lobby.1019="" +#main_lobby.1020="" +#main_lobby.1021="" +#main_lobby.1022="" +#main_lobby.1023="" +#main_lobby.1024="" +#main_lobby.1025="" +#main_lobby.1026="" +#main_lobby.1027="" +#main_lobby.1028="" +#main_lobby.1029="" +#main_lobby.1030="" +#main_lobby.1031="" +#main_lobby.1032="" +#main_lobby.1033="" +#main_lobby.1034="" +#main_lobby.1035="" +#main_lobby.1036="" +#main_lobby.1037="" +#main_lobby.1038="" +#main_lobby.1039="" +#main_lobby.1040="" +#main_lobby.1041="" +#main_lobby.1042="" +#main_lobby.1043="" +#main_lobby.1044="" +#main_lobby.1045="" +#main_lobby.1046="" +#main_lobby.1047="" +#main_lobby.1048="" +#main_lobby.1049="" +#main_lobby.1050="" +#main_lobby.1051="" +#main_lobby.1052="" +#main_lobby.1053="" +#main_lobby.1054="" +#main_lobby.1055="" +#main_lobby.1056="" +main_lobby.1057="Myrkyllinen peruna" +#main_lobby.1058="" +main_lobby.1059="Kultainen omena" +#main_lobby.1060="" +#main_lobby.1061="" +#main_lobby.1062="" \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/misc.properties b/configuration/i18n/fi_FI/official/misc.properties new file mode 100644 index 000000000..9e7036158 --- /dev/null +++ b/configuration/i18n/fi_FI/official/misc.properties @@ -0,0 +1,519 @@ +mcp_miscellaneous.0="Ansaitut kolikot yhteensä: %%earned%%" +mcp_miscellaneous.1=" +%%earned%% %%reason%%" +mcp_miscellaneous.2="Ansaittu Experience yhteensä: %%experience%%" +mcp_miscellaneous.3=" +%%earned%% %%reason%%" +mcp_miscellaneous.4="Vain partyn johtaja voi teleportata sinut peliin! Odota että hän tekee niin, tai voit myös tehdä /party leave" +mcp_miscellaneous.5="Et voi olla partyssa liittyessäsi %%gametype%% solo -peliin!" +mcp_miscellaneous.6="Partyssasi voi olla enintään 2 pelaajaa liittyäksesi %%gametype%%-tiimipeliin!" +mcp_miscellaneous.7="Partyssasi tulee olla neljä pelaajaa liittyessäsi ystävien tilaan!" +mcp_miscellaneous.8="Partyssasi voi olla enintään 3 pelaajaa liittyäksesi %%gametype%%-tiimipeliin!" +mcp_miscellaneous.9="Et voi olla partyssa liittyessäsi pelin %%gametype%% ranked-peliin!" +mcp_miscellaneous.10="Partysi ei voi jonottaa peliin %%gametype%%: %%map%% koska %%player%% ei ole paikalla!" +mcp_miscellaneous.11="Sinun tulee olla neljän pelaajan partyssa liittyäksesi ystävien tilaan!" +mcp_miscellaneous.12="Tarvitset vähintään %%required%% tappoa missä tahansa pelimuodossa pelataksesi pelin %%gametype%% ranked-muotoa!" +mcp_miscellaneous.13="Anteeksi, emme löytäneet palvelimia, joissa olisi tarpeeksi tilaa pelille %%gametype%%: %%map%%! Yritä uudelleen muutaman minuutin kuluttua!" +mcp_miscellaneous.14="Löydettiin peli %%gametype%%: %%map%%! Siirretään sinut palvelimelle %%server%%!" +mcp_miscellaneous.15="Ei saatavilla palvelimia, joissa olisi tilaa partylle! Yritä kohta uudelleen!" +mcp_miscellaneous.16="Siirretään sinut palvelimelle %%server%%!" +mcp_miscellaneous.17="Partyssasi voi olla enintään %%number%% pelaajaa liittyäksesi %%gametype%% solo -peliin!" +mcp_miscellaneous.18="Ansaitsit yhteensä %%exp%% Experienceä" +mcp_miscellaneous.19="Ei löydetty pelaajaa tuolla nimellä!" +mcp_miscellaneous.20="Virheellinen komento! '/%%command%% %%args%%'" +mcp_miscellaneous.21="Syöte ei kelpaa!" +mcp_miscellaneous.22="Klikkaa ehdottaaksesi komentoa %%command%%" +mcp_miscellaneous.23="Tämä pelaaja ei ole paikalla!" +mcp_miscellaneous.24="Sinut on hiljennetty." +mcp_miscellaneous.25="Olet hiljennettynä syystä %%reason%%." +mcp_miscellaneous.26="Tapahtui virhe käyttäessäsi tuota komentoa! Ilmoitathan tästä ylläpidolle!" +mcp_miscellaneous.27="Sinun tulee olla lobbyssa käyttääksesi tätä komentoa!" +mcp_miscellaneous.28="Asetukset:" +mcp_miscellaneous.29="Virhe ilmaantui käsitellessä tuota. Yritä myöhemmin uudelleen." +mcp_miscellaneous.30="Et ole partyn johtaja!" +mcp_miscellaneous.31="Vain Partyn johtaja voi käyttää tätä" +mcp_miscellaneous.32="Pelissäsi oli %%amount%% %%rank%%-pelaajaa (tai korkeampaa)" +mcp_miscellaneous.33="Ansaittu Hypixel-experience yhteensä: %%experience%%" +mcp_miscellaneous.34="Ansaitsit yhteensä %%exp%% Hypixel-experienceä" +mcp_miscellaneous.35="Poistaa pelaajan kavereistasi" +mcp_miscellaneous.36="Housing on väliaikaisesti poistettu käytöstä huoltoa varten!" +mcp_miscellaneous.37="Et voi estää tätä pelaajaa!" +mcp_miscellaneous.38="Lisättiin pelaaja %%player%% estettyjen listallesi." +mcp_miscellaneous.39="Olet jo estänyt tämän pelaajan! /ignore remove pelaaja poistaaksesi eston!" +mcp_miscellaneous.40="Et voi estää itseäsi." +mcp_miscellaneous.41="Virheellinen komento! Käytä: /ignore add pelaaja" +mcp_miscellaneous.42="Poistettiin pelaaja %%player%% estettyjen listaltasi." +mcp_miscellaneous.43="Et ole estänyt tätä pelaajaa! /ignore add pelaaja estääksesi tämän!" +mcp_miscellaneous.44="Virheellinen komento! Käytä: /ignore remove pelaaja" +mcp_miscellaneous.45="Pelaaja" +mcp_miscellaneous.46="Poista pelaaja estettyjen listaltasi" +mcp_miscellaneous.47="Estä pelaaja" +mcp_miscellaneous.48="Listaa estetyt pelaajat" +mcp_miscellaneous.49="(sivu)" +mcp_miscellaneous.50="En tiedä kuinka käsitellä sivunumeroa %%number%%!" +mcp_miscellaneous.51="Virheellinen komento! Käytä: /ignore list (sivu)" +mcp_miscellaneous.52="Sivunumeron tulee olla positiivinen!" +mcp_miscellaneous.53="------ Estetyt käyttäjät (Sivu %%page%%/%%max_page%%) ------" +mcp_miscellaneous.54="Oletko varma? Tämä lähettää sinut lobbyyn. Kirjoita /delivery uudelleen vahvistaaksesi" +mcp_miscellaneous.55="Virheellinen komento! /joinlobby #" +mcp_miscellaneous.56="Yritetään teleportata sinua lobbyyn %%lobby%%" +mcp_miscellaneous.57="Numero ei kelpaa!" +mcp_miscellaneous.58="Lobby" +mcp_miscellaneous.59="En ole varma mitä tarkoitit: %%input%%" +mcp_miscellaneous.60="Ei löydetty päälobbya johon sinut voitaisiin teleportata!" +mcp_miscellaneous.61="Teleporttaa sinut päälobbyyn" +mcp_miscellaneous.62="Tämä komento teleporttaa sinut päälobbyyn. Käytä komentoa /main" +mcp_miscellaneous.63="Ethän spammaa komentoa!" +mcp_miscellaneous.64="Oikeaklikkaa kompassia lobbyssa valitaksesi pelin!" +mcp_miscellaneous.65="Voit ilmiantaa huijareita käyttämällä komentoa\n/watchdogreport (pelaajan nimi) (huijauskeinot)" +mcp_miscellaneous.66="Voit ilmiantaa chatin väärinkäytöstä komennolla\n/chatreport (pelaajan nimi)" +mcp_miscellaneous.67="Jokin taisi mennä vikaan, yritä uudelleen hetken kuluttua!" +mcp_miscellaneous.68="Ilmianna pelaaja Watchdogille" +mcp_miscellaneous.69="Viesti" +mcp_miscellaneous.70="Virheellinen komento! Käytä komentoa /swaplobby (numero)" +mcp_miscellaneous.71="Tämä lobby on täynnä!" +mcp_miscellaneous.72="Tuntematon lobby!" +mcp_miscellaneous.73="Lähetetään sinut palvelimelle %%server%%" +mcp_miscellaneous.74="Sinun tulee olla lobbyssa käyttääksesi tätä komentoa!" +mcp_miscellaneous.75="Keskustelu, jossa olit mukana, vanhentui ja sinut siirrettiin takaisin julkiselle kanavalle." +mcp_miscellaneous.76="Ole hyvä ja yritä tätä komentoa uudelleen hetken kuluttua." +mcp_miscellaneous.77="Voit lähettää viestin vain puolen sekunnin välein!" +mcp_miscellaneous.78="Ole hyvä ja älä toista samaa viestiä uudelleen ja uudelleen." +mcp_miscellaneous.79="Virheellinen komento! Käytä: /msg (pelaaja) (viesti)" +mcp_miscellaneous.80="Olet avannut liian monta keskustelua ylläpidon kanssa. Hidasta vähän!" +mcp_miscellaneous.81="Tapahtui virhe! Yritä uudelleen hetken kuluttua!" +mcp_miscellaneous.82="Et voi lähettää viestiä tälle henkilölle hiljennettynä. Hiljennyksesi päättyy %%time%% kuluttua" +mcp_miscellaneous.83="Tällä pelaajalla on mykistys käytössä eikä hänelle voi lähettää viestiä juuri nyt!" +mcp_miscellaneous.84="Voit lähettää viestejä vain pelaajille, jotka ovat kaverilistallasi!" +mcp_miscellaneous.85="Tämä pelaaja on lisännyt sinut estettyjen pelaajien listalleen!" +mcp_miscellaneous.86="Avattiin keskustelu pelaajan %%name%% kanssa seuraavien viiden minuutin ajaksi. Käytä komentoa /chat a poistuaksesi." +mcp_miscellaneous.87="Virheellinen komento! Käytä komentoa /r (viesti)" +mcp_miscellaneous.88="Kukaan ei ole lähettänyt sinulle viestiä viimeisen viiden minuutin aikana!" +mcp_miscellaneous.89="+%%amount%% Karmaa!" +mcp_miscellaneous.90="Tuo ei ole gift!" +mcp_miscellaneous.91="Sinun tulee olla vähintään Hypixel-level 5 voidaksesi lähettää giftejä!" +mcp_miscellaneous.92="Lähetit giftin, joka sisältää %%award%% %%name%% , pelaajalle %%player%%!" +mcp_miscellaneous.93="Vastaanotit giftin pelaajalta %%sender%%!" +mcp_miscellaneous.94="Vieraile lobbysta löytyvällä Mysteeriholvilla avataksesi sen!" +mcp_miscellaneous.95="Jotain outoa tapahtui lähettäessä tuota! Yritä kirjautua uudelleen palvelimelle. Mikäli tämä jatkuu, ilmoitathan ylläpidolle." +mcp_miscellaneous.96="Reseptiä ei löytynyt!" +mcp_miscellaneous.97="Sinulla ei ole tarpeeksi mysteeripölyä työstääksesi tuota!" +mcp_miscellaneous.98="Työstit esineen %%name%%" +mcp_miscellaneous.99="Avasit %%amount%% Hypixel-experiencen pussin" +mcp_miscellaneous.100="Sinulla ei ole enää yhtään tällaista EXP-pussia jäljellä!" +mcp_miscellaneous.101="Olet jo käyttänyt tuon! Yritä kirjautua palvelimelle uudelleen!" +mcp_miscellaneous.102="Säteilet" +mcp_miscellaneous.103="Seuraavasta pelaamastasi pelistä sinä ja" +mcp_miscellaneous.104="muut pelaajat saavat pussillisen " +mcp_miscellaneous.105="Olet nyt kaveri pelaajan %%name%% kanssa" +mcp_miscellaneous.106="Sinulla on %%count%% odottavaa kaveripyyntöä. Käytä komentoa /f requests nähdäksesi ne kaikki!" +mcp_miscellaneous.107="Kaveripyyntösi pelaajalle %%name%% on vanhentunut." +mcp_miscellaneous.108="Kaveripyyntö pelaajalta %%name%% on vanhentunut." +mcp_miscellaneous.109="Olet jo tämän henkilön kaveri!" +mcp_miscellaneous.110="Olet jo lähettänyt kaveripyynnön tälle pelaajalle!" +mcp_miscellaneous.111="Tämä pelaaja on estänyt sinua lähettämästä kaveripyyntöjä hänelle!" +mcp_miscellaneous.112="Et voi lähettää kaveripyyntöjä tälle pelaajalle!" +mcp_miscellaneous.113="Tämä henkilö on asettanut kaveripyynnöt pois päältä!" +mcp_miscellaneous.114="Odota ennen kuin lähetät toisen pyynnön tälle pelaajalle!" +mcp_miscellaneous.115="Virheellinen komento! Käytä komentoa /friend accept pelaaja" +mcp_miscellaneous.116="Tämä pelaaja ei ole pyytänyt sinua kaverikseen! Kokeile komentoa /friend %%name%%" +mcp_miscellaneous.117="Hyväksy kaveripyyntö" +mcp_miscellaneous.118="Virheellinen komento! Käytä komentoa /friend deny pelaaja" +mcp_miscellaneous.119="Hylkäsit pelaajan %%name%% kaveripyynnön!" +mcp_miscellaneous.120="%%name%% ei ole lähettänyt sinulle kaveripyyntöä!" +mcp_miscellaneous.121="Hylkää kaveripyyntö" +mcp_miscellaneous.122="Voit käyttää tätä komentoa vain 10 sekunnin välein!" +mcp_miscellaneous.123="Kavereiden näkymättömyys pois päältä." +mcp_miscellaneous.124="Kavereiden näkymättömyys päällä." +mcp_miscellaneous.125="Vaihda näkymättömyyden tilaa kaverilistalla" +mcp_miscellaneous.126="Näytä kaveripyynnöt" +mcp_miscellaneous.127="Virheellinen sivunumero!" +mcp_miscellaneous.128="Sivunumeron tulee olla positiivinen!" +mcp_miscellaneous.129="Virheellinen komento! Käytä komentoa /friend requests (sivu)" +mcp_miscellaneous.130="Kaveripyynnöt (Sivu %%page%%/%%max_page%%)" +mcp_miscellaneous.131="Klikkaa hylätäksesi kaveripyynnön" +mcp_miscellaneous.132="Klikkaa hyväksyäksesi kaveripyynnön" +mcp_miscellaneous.133="HYVÄKSY" +mcp_miscellaneous.134="HYLKÄÄ" +mcp_miscellaneous.135="ESTÄ" +mcp_miscellaneous.136="Klikkaa estääksesi pelaajan" +mcp_miscellaneous.137="Vaihda kaveripyyntöjen tilaa" +mcp_miscellaneous.138="Muut pelaajat eivät voi lähettää sinulle enää kaveripyyntöjä." +mcp_miscellaneous.139="Muut pelaajat voivat lähettää sinulle kaveripyyntöjä." +mcp_miscellaneous.140="Sinulla ei ole vielä kavereita! Lisää heitä komennolla /friend add pelaaja" +mcp_miscellaneous.141="Listaa kaverisi" +mcp_miscellaneous.142="%%name%% on paikalla!" +mcp_miscellaneous.143="%%name%% ei ole paikalla!" +mcp_miscellaneous.144="Poistit pelaajan %%friend_name%% kaverilistaltasi!" +mcp_miscellaneous.145="%%player_name%% ei ole kaverilistallasi!" +mcp_miscellaneous.146="Virheellinen komento! Käytä komentoa /friend pelaaja" +mcp_miscellaneous.147="Virheellinen komento! Käytä komentoa /friend add pelaaja" +mcp_miscellaneous.148="Potki poissa olevat pelaajat partysta" +mcp_miscellaneous.149="Ei poissa olevia pelaajia potkittavana!" +mcp_miscellaneous.150="Kaverikomennot:" +mcp_miscellaneous.151="Et voi lisätä itseäsi kaveriksi!" +mcp_miscellaneous.152="Sait kutsun, mutta sitä suorittaessa tapahtui virhe. Yritä uudelleen hetken kuluttua!" +mcp_miscellaneous.153="Klikkaa estääksesi kaikki tulevat kaveripyynnöt ja chat-viestit" +mcp_miscellaneous.154="Lisää pelaaja kaveriksesi" +mcp_miscellaneous.155="Lähetit kaveripyynnön pelaajalle %%name%%! Hänellä on 5 minuuttia aikaa hyväksyä!" +mcp_miscellaneous.156="Kaveripyyntö pelaajalta" +mcp_miscellaneous.157="Klikkaa estääksesi kaikki tulevat kaveripyynnöt ja chat-viestit tältä pelaajalta" +mcp_miscellaneous.158="Olet jo avannut tuon laatikon! Siinä oli %%item%%! Kokeile kirjautua palvelimelle uudelleen!" +mcp_miscellaneous.159="Sinulle annettiin %%number%% EXP tilisi linkkaamisesta!" +mcp_miscellaneous.160="PARTY" +mcp_miscellaneous.161="YLEINEN" +mcp_miscellaneous.162="Käytä tätä komentoa haastaaksesi toinen party" +mcp_miscellaneous.163="8v8 Cops and Crims -taisteluun! Käytä komentoa" +mcp_miscellaneous.164="/party challenge Pelaaja, missä Pelaaja on toisen partyn johtaja" +mcp_miscellaneous.165="Olet nyt kanavalla %%channel%%" +mcp_miscellaneous.166="Palvelinta ei löytynyt!" +mcp_miscellaneous.167="Sinun tulee olla partyssa voidaksesi liittyä partyn kanavalle!" +mcp_miscellaneous.168="Sinun tulee olla guildissa voidaksesi liittyä guildin kanavalle!" +mcp_miscellaneous.169="Pelaajaa %%player%% ei löytynyt" +mcp_miscellaneous.170="Emme löytäneet sinulle lobbya!" +mcp_miscellaneous.171="Jokin meni vikaan enkä voinut löytää tuota karttaa! Ole hyvä ja ilmoita tästä ylläpidolle!" +mcp_miscellaneous.172="Olet jo tämän pelaajan talossa!" +mcp_miscellaneous.173="Lähetetään sinut takaisin palvelimelle %%server%%..." +mcp_miscellaneous.174="Valitettavasti kaikki housing-palvelimet ovat juuri nyt täynnä! Yritä uudelleen hetken kuluttua!" +mcp_miscellaneous.175="Lähetetään sinut palvelimelle %%server%%..." +mcp_miscellaneous.176="Kaikki Housing-palvelimet ovat tällä hetkellä käytössä. Yritä uudelleen hetken kuluttua." +mcp_miscellaneous.177="Komento ei kelpaa!" +mcp_miscellaneous.178="Löydettiin peli %%game%%: %%map%%! Lähetetään sinut palvelimelle %%servername%%!" +mcp_miscellaneous.179="[syy]" +mcp_miscellaneous.180="[asetus]" +mcp_miscellaneous.181="[tunniste]" +mcp_miscellaneous.182="[arvo]" +mcp_miscellaneous.183="Mikäli sinulla on maksuihin liittyviä kysymyksiä, vieraile osoitteessa " +mcp_miscellaneous.184="support.hypixel.net" +mcp_miscellaneous.185="https://support.hypixel.net/" +mcp_miscellaneous.186="Ilmoita palvelimen ongelmista ja bugeista foorumeilla: " +mcp_miscellaneous.187="hypixel.net/forums/35/" +mcp_miscellaneous.188="https://hypixel.net/forums/35/" +mcp_miscellaneous.189="Näitkö sääntöjä rikkoneen pelaajan? Ilmianna hänet foorumeilla: " +mcp_miscellaneous.190="hypixel.net/forums/37/" +mcp_miscellaneous.191="https://hypixel.net/forums/37/" +mcp_miscellaneous.192="Tarvitsetko lisää apua? Kurkkaa apuosiotamme: " +mcp_miscellaneous.193="hypixel.net/forums/5/" +mcp_miscellaneous.194="https://hypixel.net/forums/5/" +mcp_miscellaneous.195="Saadaksesi apua ja tukea vieraile osoitteessa http://mc.163.com/hypixel" +mcp_miscellaneous.196="Et voi olla partyssä liittyessäsi Murder Mystery Hardcore -peliin!" +mcp_miscellaneous.197="En ole varma millä palvelimella olet!" +mcp_miscellaneous.198="Virheellinen komento! Käytä komentoa: /tpa pelaaja tai /tpa accept pelaaja" +mcp_miscellaneous.199="Ei löydetty pelaajaa nimellä '%%name%%'!" +mcp_miscellaneous.200="Tämä pelaaja ei ole pyytänyt lupaa teleportata luoksesi, tai pyyntö on vanhentunut!" +mcp_miscellaneous.201="Tämä pelaaja ei ole enää paikalla!" +mcp_miscellaneous.202="Tämän pelaajan luo ei voi enää teleportata!" +mcp_miscellaneous.203="Teleporttasit pelaajan %%name%% luo" +mcp_miscellaneous.204="%%name%% teleporttasi luoksesi!" +mcp_miscellaneous.205="Sinun tulee olla vähintään VIP+ käyttääksesi tätä komentoa!" +mcp_miscellaneous.206="Osta VIP+ ja paljon muuta osoitteesta http://store.hypixel.net/" +mcp_miscellaneous.207="Et voi teleportata tämän pelaajan luo! Hän ei ole samassa lobbyssa kuin sinä!" +mcp_miscellaneous.208="Et voi teleportata tämän pelaajan luo!" +mcp_miscellaneous.209="Virheellinen komento! '/%%command%%'" +mcp_miscellaneous.210="%%leader%% ylensi pelaajan %%player%% partyn johtajaksi!" +mcp_miscellaneous.211="Gift Pack -ostoksesi käsiteltiin onnistuneesti: " +mcp_miscellaneous.212="Ostotapahtumasi käsiteltiin:" +mcp_miscellaneous.213="Virheellinen komento! Käytä komentoa /housing partywarp pelaaja" +mcp_miscellaneous.214="Sinulla voi olla vain %%count%% aktiivista kutsua samanaikaisesti!" +mcp_miscellaneous.215="Voit lähettää vain %%count%% hyväksymätöntä kutsua joka %%mins%%. minuutti!" +mcp_miscellaneous.216="%red%%Olet lähettänyt liian monta party-kutsua ja kyseinen toiminto on estetty sinulta %%time%% ajaksi" +mcp_miscellaneous.217="Löydettiin keskeneräinen %%game%% -peli! Teleportataan sinut palvelimelle %%server%%..." +mcp_miscellaneous.218="Ei löydetty keskeneräisiä pelejä, joissa olisi tarpeeksi tilaa! Yritä liittyä uuteen peliin!" +mcp_miscellaneous.219="Olet lähettänyt liian monta kaveripyyntöä viimeisten %%time%% minuutin aikana! Sinun tulee odottaa %%lockout%% minuuttia voidaksesi lähettää niitä lisää." +mcp_miscellaneous.220="Olet saavuttanut kavereiden enimmäismäärän (%%amount%%)! Lisätäksesi uusia kavereita on sinun poistettava toisia. Jos haluat tyhjentää kaverilistasi, otathan yhteyttä ylläpitoon." +mcp_miscellaneous.221="Tällä pelaajalla on enimmäismäärä, %%amount%%, kavereita!" +mcp_miscellaneous.222="Et voi pelata ranked %%gametype%% tällä kaudella, sillä sinulla on yksi tai useampi rangaistus!" +mcp_miscellaneous.223="Lobby, jossa olit, käynnistettiin uudelleen, joten sinut lähetettiin toiseen lobbyyn." +mcp_miscellaneous.224="%%mode%%" +mcp_miscellaneous.225="Saatavilla olevat pelimuodot:" +mcp_miscellaneous.226="Sinua ei ole kutsuttu Dueliin, tai kutsu on jo vanhentunut!" +mcp_miscellaneous.227="Et voi haastaa itseäsi Dueliin!" +mcp_miscellaneous.228="Et voi kutsua pelaajaa %%player%% Dueliin, sillä hän ei ole paikalla!" +mcp_miscellaneous.229="Et voi kutsua tätä pelaajaa Dueliin!" +mcp_miscellaneous.230="\"%%mode%%\" ei ole kelvollinen Duels-pelimuoto!" +mcp_miscellaneous.231="Duel-komennot:" +mcp_miscellaneous.232="/duel - Avaa valikon, jolla voit kutsua pelaajan Dueliin." +mcp_miscellaneous.233="/duel - Kutsu pelaaja Dueliin. Käytä komentoa /duel modes nähdäksesi mitä pelimuotoja /duel-komento tukee tällä hetkellä." +mcp_miscellaneous.234="/duel modes - Listaa komennolla /duel saatavilla olevat pelimuodot." +mcp_miscellaneous.235="/duel accept - Hyväksy pelaajalta saatu Duel-kutsu." +mcp_miscellaneous.236="Duelin käynnistäminen epäonnistui. %%name%% ja %%invited%% ovat samassa partyssa!" +mcp_miscellaneous.237="Duelin käynnistäminen epäonnistui. %%name%% ei ole partyssa tarpeeksi monen pelaajan kanssa liittyäkseen pelimuodon %%mode%% Dueliin!" +mcp_miscellaneous.238="Duelin käynnistäminen epäonnistui. %%target%% ei ole partyssa tarpeeksi monen pelaajan kanssa liittyäkseen pelimuodon %%mode%% Dueliin!" +mcp_miscellaneous.239="Hyväksyit pelaajan %%player%% Duel-kutsun!" +mcp_miscellaneous.240="%%player%% hyväksyi Duel-kutsun!" +mcp_miscellaneous.241="Virhe ilmaantui teleportatessa peliin!" +mcp_miscellaneous.242="Duelia ei voida aloittaa. %%player%% ei ole paikalla!" +mcp_miscellaneous.243="Virhe käynnistettäessä Duelia. Virheellinen määrä pelaajia!" +mcp_miscellaneous.244="Et voi kutsua samassa partyssa olevaa pelaajaa pelimuodon %%mode%% Dueliin!" +mcp_miscellaneous.245="Et ole partyssa tarpeeksi monen pelaajan kanssa liittyäksesi pelimuodon %%mode%% Dueliin!" +mcp_miscellaneous.246="%%target%% ei ole partyssa tarpeeksi monen pelaajan kanssa liittyäkseen pelimuodon %%mode%% Dueliin!" +mcp_miscellaneous.247="Kutsuit pelaajan %%invitedplayer%% partyn pelimuodon %%mode%% Dueliin! Hänellä on 60 sekuntia aikaa hyväksyä." +mcp_miscellaneous.248="Kutsuit pelaajan %%invitedplayer%% pelimuodon %%mode%% Dueliin! Hänellä on 60 sekuntia aikaa hyväksyä." +mcp_miscellaneous.249="%%player%% kutsui partysi pelimuodon %%mode%% Dueliin!" +mcp_miscellaneous.250="%%player%% kutsui sinut peliin %%mode%%!" +mcp_miscellaneous.251="KLIKKAA TÄSTÄ hyväksyäksesi! Sinulla on 60 sekuntia aikaa hyväksyä." +mcp_miscellaneous.252="Klikkaa käyttääksesi komentoa\n/duel accept %%player%%" +mcp_miscellaneous.253="Lähettää Duel-kutsun pelaajalle" +mcp_miscellaneous.254="Tuolla nimellä ei löytynyt palvelinta. Ole hyvä ja ota yhteyttä ylläpitoon saadaksesi apua." +mcp_miscellaneous.255="Ei löydetty palvelinta tuolla nimellä." +mcp_miscellaneous.256="Ei löydetty pelaajaa tällä palvelimella." +mcp_miscellaneous.257="Lähetetään sinut palvelimelle %%server%% teleportataksesi satunnaiseen pelaajaan!" +mcp_miscellaneous.258="En voi tehdä noin juuri nyt, kokeile uudelleen myöhemmin." +mcp_miscellaneous.259="Minulla oli ongelmia asettaessa sinua jonoon palvelimelle." +mcp_miscellaneous.260="Et voi tehdä tätä partyssa!" +mcp_miscellaneous.261="%%player%% ei ole enää tässä pelissä." +mcp_miscellaneous.262="Voit käyttää pikakutsua enintään %%limit%% kertaa!" +mcp_miscellaneous.263="Sinulla ei ole oikeuksia tälle kanavalle!" +mcp_miscellaneous.264="------ Ei estettyjä pelaajia ------" +mcp_miscellaneous.265="Duel-kutsu pelaajalta %%sender%% on vanhentunut." +mcp_miscellaneous.266="Duel-kutsu pelaajalle %%sender%% on vanhentunut." +mcp_miscellaneous.267="Voittobonus" +mcp_miscellaneous.268="Vaihtaa partyn mykistyksen tilaa" +mcp_miscellaneous.269="Luo partyn äänestys!" +mcp_miscellaneous.270="Poista kaikki kaverisi" +mcp_miscellaneous.271="%%experience%% Battle Pass Experienceä" +mcp_miscellaneous.272="+%%earned%% %%reason%%" +mcp_miscellaneous.273="%%earned%% %%gameType%% -kolikko" +mcp_miscellaneous.274="%%earned%% %%gameType%% -kolikkoa" +mcp_miscellaneous.275="+%%coins%% Pelipalkinto" +mcp_miscellaneous.276="+%%earned%% %%reason%%" +mcp_miscellaneous.277="%%experience%% Hypixel-experienceä" +mcp_miscellaneous.278="+%%earned%% %%reason%%" +mcp_miscellaneous.279="Peliaikabonus" +mcp_miscellaneous.280="Ansaitsit" +mcp_miscellaneous.281="Bow Duel" +mcp_miscellaneous.282="Bow Duels" +mcp_miscellaneous.283="Classic Duel" +mcp_miscellaneous.284="Classic Duels" +mcp_miscellaneous.285="UHC Duel" +mcp_miscellaneous.286="UHC Duels" +mcp_miscellaneous.287="UHC Doubles" +mcp_miscellaneous.288="UHC Teams" +mcp_miscellaneous.289="Mega Walls Duel" +mcp_miscellaneous.290="Mega Walls Duels" +mcp_miscellaneous.291="Mega Walls Doubles" +mcp_miscellaneous.292="Sumo Duel" +mcp_miscellaneous.293="Sumo Duels" +mcp_miscellaneous.294="SkyWars Duel" +mcp_miscellaneous.295="SkyWars Duels" +mcp_miscellaneous.296="SkyWars Doubles" +mcp_miscellaneous.297="Combo Duel" +mcp_miscellaneous.298="Combo Duels" +mcp_miscellaneous.299="Nodebuff Duel" +mcp_miscellaneous.300="Nodebuff Duels" +mcp_miscellaneous.301="Op Duel" +mcp_miscellaneous.302="Op Duels" +mcp_miscellaneous.303="Op Doubles" +mcp_miscellaneous.304="Blitz Duel" +mcp_miscellaneous.305="Blitz Duels" +mcp_miscellaneous.306="Bow Spleef Duel" +mcp_miscellaneous.307="Bow Spleef Duels" +mcp_miscellaneous.308="Ei saatavilla palvelimia, joissa olisi tilaa partylle! Yritä kohta uudelleen! (2)" +mcp_miscellaneous.309="Kutsuit tyhjän partysi palvelimellesi :(" +mcp_miscellaneous.310="Kutsuit %%warped%% palvelimellesi." +mcp_miscellaneous.311="yhden pelaajan" +mcp_miscellaneous.312="Kutsuit %%warped%% pelaajan Partysi palvelimellesi." +mcp_miscellaneous.313="Sinun täytyy olla %%rank%%käyttääksesi tätä komentoa!" +mcp_miscellaneous.314="kysymys/vastaus/vastaus[/vastaus]" +mcp_miscellaneous.315="Kutsuttiin pelaaja %%players%% partyysi!" +mcp_miscellaneous.316="Klikkaa tästä liittyäksesi tai kirjoita /party accept %%player%%!" +mcp_miscellaneous.317="Kaveri > %%player%% poistui." +mcp_miscellaneous.318="Kaveri > %%player%% liittyi." +mcp_miscellaneous.319="HYPIXEL NETWORK" +mcp_miscellaneous.320="Klikkaa valitaksesi vaihtoehdon..." +mcp_miscellaneous.321="Klikkaa valitaksesi!" +mcp_miscellaneous.322="* Löytyi palvelimen ongelma/vika" +mcp_miscellaneous.323="* Ilmianna sääntöjä rikkovia pelaajia" +mcp_miscellaneous.324="* Kysy maksuihin liittyvä kysymys" +mcp_miscellaneous.325="Tarvitsetko lisää apua? Vieraile" +mcp_miscellaneous.326="foorumeillamme" +mcp_miscellaneous.327=" Sinulla on tällä hetkellä porttikielto Hypixelin kilpailuihin etkä pysty pelaamaan pelin %%name%% turnauksessa!" +mcp_miscellaneous.328="Koska partyn jäsenellä on porttikielto Hypixelin kilpailuihin, et pysty liittymään tällä partylla pelin %%name%% turnaukseen!" +mcp_miscellaneous.329="Pelaajalta: %%from%%" +mcp_miscellaneous.330="Pelaajalle: %%to%%" +mcp_miscellaneous.331="Tätä peliä ei tueta Minecraftin versiolla %%version%% tai myöhemmällä!" +mcp_miscellaneous.332="Sinun tulee olla vähintään Hypixel-level %%required%% pelataksesi peliä %%gametype%%!" +mcp_miscellaneous.333="Hypixel-levelisi kasvaa ansaitessasi experienceä tehtävistä, haasteista ja peleistä. Levelisi näkyy kokemuspalkissasi kaikissa lobbyissa." +mcp_miscellaneous.334="Sinun tulee olla vähintään Hypixel-level %%required%% pelataksesi pelin %%name%% turnauksessa!" +mcp_miscellaneous.335="Jalomielisyys\nPelissä, jossa ainakin yhdellä\npelaajalla on Jalomielisyyttä, saa jokainen\npelaaja pussillisen Hypixel-experienceä\npelin päätteeksi.\n\nKavereilta saatujen giftien avaaminen\nantaa Jalomielisyyttä." +mcp_miscellaneous.336="Ei saatavilla palvelimia tässä kartassa! Yritä kohta uudelleen!" +mcp_miscellaneous.337="Vain partyn johtaja voi teleportata sinut peliin! Odota että hän klikkaa NPC-hahmoa tai käytä komentoa /party leave" +mcp_miscellaneous.338="Et voi aloittaa yksityistä peliä, kun partyssa olet vain sinä itse!" +mcp_miscellaneous.339="Partysi on liian suuri, että se voisi liittyä peliin %%gameType%%: %%map%%! Enintään 3 pelaajaa per party!" +mcp_miscellaneous.340="Partysi on liian suuri, että se voisi liittyä peliin %%gameType%%: %%map%%! Enintään 5 pelaajaa per party!" +mcp_miscellaneous.341="Partyssasi tulee olla täsmälleen 2 pelaajaa voidaksenne pelata tätä!" +mcp_miscellaneous.342="Partyssasi tulee olla ainakin 2 pelaajaa voidaksenne pelata tätä!" +mcp_miscellaneous.343="Partysi on liian suuri tähän karttaan! Yritä toista karttaa!" +mcp_miscellaneous.344="Anteeksi, emme löytäneet palvelimia, joissa olisi tarpeeksi tilaa pelille %%game%%: %%map%%! Yritä uudelleen muutaman minuutin kuluttua!" +mcp_miscellaneous.345="Ei palvelinta saatavilla! Yritä hetken kuluttua uudelleen!" +mcp_miscellaneous.346="Lähetetään palvelimelle %%server%%..." +mcp_miscellaneous.347="Tuon pelaajan talo on täynnä! Kokeile toista taloa!" +mcp_miscellaneous.348="Virheellinen salasana! Yritä uudelleen!" +mcp_miscellaneous.349="HUOMIO! Partysi pelaaja %%player%% ei ole paikalla!" +mcp_miscellaneous.350="ANTEEKSI! Palvelinta ei löytynyt!" +mcp_miscellaneous.351="ANTEEKSI! Sinua ei voitu sovittaa maailmaan palvelimelle " +mcp_miscellaneous.352="PALVELIN LÖYTYI! Lähetetään sinut palvelimelle %%server%%!" +mcp_miscellaneous.353="PALVELIN LÖYTY! Lähetetään sinut palvelimelle %%server%% (partysi on siellä)!" +mcp_miscellaneous.354="HUPS! Ei voitu liittyä The Pit -peliin täältä!" +mcp_miscellaneous.355="IIK! Yritätkö teleportata samalle pit-palvelimelle?" +mcp_miscellaneous.356="VIRHE! Ei löytynyt palvelinta, jolle yritit liittyä!" +mcp_miscellaneous.357="HÄMMENTYNYT? Pit-palvelin, jolle yritit liittyä, ei taida edes olla pit-palvelin!" +mcp_miscellaneous.358="EI VOITU LIITTYÄ! koska poistuit pitistä liian äskettäin!" +mcp_miscellaneous.359="LIITTYMINEN PERUTTU! %%reason%%" +mcp_miscellaneous.360="VIRHE! siirrettäessä sinua tälle palvelimelle! (1)" +mcp_miscellaneous.361="OOF! Sinua ei siirretty, koska olit taistelutilassa!" +mcp_miscellaneous.362="VIRHE! Ei voitu siirtää sinua pois nykyiseltä pit-palvelimeltasi!" +mcp_miscellaneous.363="VIRHE! siirrettäessä sinua tälle palvelimelle! (2)" +mcp_miscellaneous.364="Partysi ei voi jonottaa peliin %%gameType%%: %%map%% koska pelaaja %%player%% ei ole paikalla!" +mcp_miscellaneous.365="Partysi ei voi jonottaa peliin %%gameType%%: %%map%% koska pelaajalla %%player%% ei ole oikeuksia liittyä tälle palvelimelle!" +mcp_miscellaneous.366="Vain partyn johtaja voi teleportata sinut peliin! Odota että hän klikkaa NPC-hahmoa tai käytä komentoa /party leave" +mcp_miscellaneous.367="Satunnaisen talon löytäminen epäonnistui. Yritä myöhemmin uudelleen!" +mcp_miscellaneous.368="Partyn johtaja, %%leader%%, teleporttasi sinut taloonsa." +mcp_miscellaneous.369="Palaa takaisin" +mcp_miscellaneous.370="foorumeillamme" +mcp_miscellaneous.371="Hypixel Minigames" +mcp_miscellaneous.372="Löytyi palvelimen ongelma/vika" +mcp_miscellaneous.373="Ilmianna sääntöjä rikkova pelaaja" +mcp_miscellaneous.374="Ilmianna pelaaja" +mcp_miscellaneous.375="Lisätietoja täältä" +mcp_miscellaneous.376="Kauppa" +mcp_miscellaneous.377="Tuki" +mcp_miscellaneous.378="Sallitut modifikaatiot" +mcp_miscellaneous.379="Hypixelin säännöt & käytännöt" +mcp_miscellaneous.380="Yleisiä tietoja palvelimesta ja pelaamisesta" +mcp_miscellaneous.381="Palvelimella pelaaminen" +mcp_miscellaneous.382="Tietoa rankeista" +mcp_miscellaneous.383="Creator Program" +mcp_miscellaneous.384="Minecraft-tilisi linkittäminen" +mcp_miscellaneous.385="Linkitä ja liity Discordiimme" +mcp_miscellaneous.386="Linkitä tilisi foorumeilla" +mcp_miscellaneous.387="Voit tehdä tämän vain Halloweenina!" +mcp_miscellaneous.388="Et voi liittyä käynnissä olevaan peliin ollessasi partyssa." +mcp_miscellaneous.389="Virheellinen komento! Käytä komentoa /friend list (sivunumero / best)" +mcp_miscellaneous.390="Syötä asetettava tila!" +mcp_miscellaneous.391="Kelvolliset vaihtoehdot: %%options%%" +mcp_miscellaneous.392="Virheellinen tila, kelvolliset vaihtoehdot: %%options%%" +mcp_miscellaneous.393="Online-tilaksesi asetettiin %%status%%" +mcp_miscellaneous.394="Sinua ei ole hiljennetty! Tämän komennon tarkoitus on ilmoittaa pelaajille, kun sinut on hiljennetty!" +mcp_miscellaneous.395="Hei, hidasta vähän!" +mcp_miscellaneous.396="Aseta kaverin lempinimi" +mcp_miscellaneous.397="Pelaajan %%name%% lempinimi on nyt %%nick%%!" +mcp_miscellaneous.398="Pelaajalla %%name%% ei ole enää lempinimeä!" +mcp_miscellaneous.399="%%player_name%% ei ole kaverilistallasi!" +mcp_miscellaneous.400="Lempinimi voi olla enintään 16 merkkiä pitkä!" +mcp_miscellaneous.401="Hallinnoi pelaajan parhaan kaverin statusta" +mcp_miscellaneous.402="%%name%% ei ole enää paras kaverisi!" +mcp_miscellaneous.403="%%name%% on nyt paras kaverisi!" +mcp_miscellaneous.404="Vain partyn johtaja voi tehdä tämän!" +mcp_miscellaneous.405="Tournament Hall on tällä hetkellä suljettu!" +mcp_miscellaneous.406="Hypixel SkyBlockin säännöt löytyvät osoitteesta %%url%%" +mcp_miscellaneous.407="Hypixelin säännöt löytyvät osoitteesta %%url%%" +mcp_miscellaneous.408="Tuota lobbya ei ole." +mcp_miscellaneous.409="Tuo lobby ei ole juuri nyt saatavilla. Ole hyvä, ja yritä myöhemmin uudelleen!" +mcp_miscellaneous.410="Klikkaa tästä linkittääksesi foorumitilisi!" +mcp_miscellaneous.411="Poissa" +mcp_miscellaneous.412="Partyn johtaja, %%player%%, kutsui sinut palvelimelleen." +mcp_miscellaneous.413="Partyn johtaja, %%leader%%, kutsui sinut SkyBlockiin, mutta et voi liittyä Limbosta." +mcp_miscellaneous.414="✖ %%player%% ei ole paikalla" +mcp_miscellaneous.415="✖ %%player%% ei voi teleportata Limbosta" +mcp_miscellaneous.416="✖ %%player%% ei voi pelata" +mcp_miscellaneous.417="✖ %%player%% ei voi liittyä, koska peli on täynnä!" +mcp_miscellaneous.418="✖ %%player%% ei voi liittyä, koska hän käyttää väärää Minecraftin versiota!" +mcp_miscellaneous.419="⚔ %%player%% teleporttasi tyrmääsi" +mcp_miscellaneous.420="✔ %%player%% teleporttasi palvelimellesi" +mcp_miscellaneous.421="✖ %%player%% ei pääse palvelimellesi!" +mcp_miscellaneous.422="✮ %%player%% on palvelimellasi" +mcp_miscellaneous.423="✖ Virhe teleportatessa pelaajaa %%player%%!" +mcp_miscellaneous.424="➜ %%player%% teleporttasi SkyBlockiin" +mcp_miscellaneous.425="✖ %%player%% ei teleportannut oikein!" +mcp_miscellaneous.426="Siirretään partya..." +mcp_miscellaneous.427="Tapahtui virhe siirtäessä partya!" +mcp_miscellaneous.428="SkyBlock -tyrmäteleporttaus (%%players%% pelaaja)" +mcp_miscellaneous.429="SkyBlock -tyrmäteleporttaus (%%players%% pelaajaa)" +mcp_miscellaneous.430="SkyBlock-partyn siirto (%%players%% pelaaja)" +mcp_miscellaneous.431="SkyBlock-partyn siirto (%%players%% pelaajaa)" +mcp_miscellaneous.432="Siirretään sinut kohteeseen %%server%%" +mcp_miscellaneous.433="MUISTUTUS: Online-tilasi on juuri nyt %%status%%" +mcp_miscellaneous.434="%%color%%%%experience%% Event Experienceä" +mcp_miscellaneous.435="%%color%%+%%earned%% %%reason%%" +mcp_miscellaneous.436="Et voi pyytää lupaa teleportata itsesi luo!" +mcp_miscellaneous.437="Olet jo pyytänyt lupaa teleportata jonkun luo! Odota, että hän hyväksyy pyynnön!" +mcp_miscellaneous.438="Olet pyytänyt lupaa teleportata pelaajan %%player%% luo! Hänellä on 30 sekuntia aikaa hyväksyä." +mcp_miscellaneous.439="%%player%% on pyytänyt lupaa teleportata luoksesi!" +mcp_miscellaneous.440="Klikkaa tästä hyväksyäksesi!" +mcp_miscellaneous.441="Klikkaa teleportataksesi %%player%% luoksesi!" +mcp_miscellaneous.442="GUILD" +mcp_miscellaneous.443="SIHTEERI" +mcp_miscellaneous.444="Sinun tulee olla SkyBlockissa voidaksesi liittyä tälle kanavalle!" +mcp_miscellaneous.445="Et voi pelata peliä %%gametype%% %%mode%% aiempien sääntörikkomusten vuoksi.\nLue lisää kilpailupelimuotojen porttikielloista täältä: %%url%%" +mcp_miscellaneous.446="Et voi pelata peliä %%gametype%% aiempien sääntörikkomusten vuoksi.\nLue lisää kilpailupelimuotojen porttikielloista täältä: %%url%%" +mcp_miscellaneous.447="Et voi pelata peliä %%gametype%% %%mode%% aiempien sääntörikkomusten vuoksi. Kilpailupelimuotojen porttikieltosi päättyy %%time%%.\nLue lisää kilpailupelimuotojen porttikielloista täältä: %%url%%" +mcp_miscellaneous.448="Et voi pelata peliä %%gametype%% aiempien sääntörikkomusten vuoksi. Kilpailupelimuotojen porttikieltosi päättyy %%time%%.\nLue lisää kilpailupelimuotojen porttikielloista täältä: %%url%%" +mcp_miscellaneous.449="Et voi pelata peliä %%gametype%% %%mode%% juuri nyt!" +mcp_miscellaneous.450="Näyttää kaikki saatavilla olevat kaverikomennot." +mcp_miscellaneous.451="Muuta kavereiden liittymis- ja poistumisviestien näkyvyyttä." +mcp_miscellaneous.452="Olet poistamassa KAIKKI kaverisi (paitsi parhaat kaverit). Haluatko varmasti tehdä tämän?" +mcp_miscellaneous.453="Klikkaa tyhjentääksesi kaveriluettelosi. (Tämä ei poista parhaita kavereitasi.)" +mcp_miscellaneous.454="Sinulla ei ole poistettavia kavereita. Tämä komento ei poista parhaita kavereitasi." +mcp_miscellaneous.455="Tätä komentoa voi käyttää ainoastaan suureen kaveriluetteloon. Komento ei poista parhaita kavereitasi." +mcp_miscellaneous.456="Poista kaikki kaverisi (paitsi parhaat kaverit)" +mcp_miscellaneous.457="Network Booster -jono" +mcp_miscellaneous.458="Ei Network Boostereita jonossa." +mcp_miscellaneous.459="pelaajalta" +mcp_miscellaneous.460="Kasatut boosterit" +mcp_miscellaneous.461="ja 1 muu" +mcp_miscellaneous.462="ja %%amount%% muuta" +mcp_miscellaneous.463="1 booster lisää jonossa." +mcp_miscellaneous.464="%%amount%% boosteria lisää jonossa." +mcp_miscellaneous.465="SKYBLOCK-YHTEISTYÖ" +mcp_miscellaneous.466="Partyssasi tulee olla %%number%% pelaajaa voidaksenne pelata %%gameType%%: %%mode%%!" +mcp_miscellaneous.467="Partyssasi tulee olla vähintään %%number%% pelaajaa voidaksenne pelata %%gameType%%: %%mode%%!" +mcp_miscellaneous.468="Et voi olla partyssa pelatessasi %%gameType%%: %%mode%%!" +mcp_miscellaneous.469="Partysi on liian suuri voidakseen pelata %%gameType%%: %%mode%%!\nPartyn enimmäiskoko tähän pelimuotoon on %%number%% pelaajaa." +mcp_miscellaneous.470="Sinun tulee olla partyssa, jossa on %%number%% pelaajaa voidaksenne pelata %%gameType%%: %%mode%%!" +mcp_miscellaneous.471="Sinun tulee olla partyssa, jossa on vähintään %%number%% pelaajaa voidaksenne pelata %%gameType%%: %%mode%%!" +mcp_miscellaneous.472="Tämä pelimuoto ei tue yksityisiä pelejä! Aseta yksityiset pelit pois käytöstä ennen liittymistä!" +mcp_miscellaneous.473="Olet saanut porttikiellon tähän taloon!" +mcp_miscellaneous.474="Hups! Jokin meni vikaan. Yritä myöhemmin uudelleen." +mcp_miscellaneous.475="Tässä talossa ei ole tarpeeksi tilaa koko partyllesi!" +mcp_miscellaneous.476="Et voi vierailla tässä talossa sen vierailusääntöjen takia!" +mcp_miscellaneous.477="Et voi vierailla tässä talossa, sillä se on asetettu yksityiseksi!" +mcp_miscellaneous.478="Tämä talo on salasanasuojattu! Varmista, että olet lobbyssa!" +mcp_miscellaneous.479="Tämä talo on täynnä! Yritä toista taloa!" +mcp_miscellaneous.480=" Kaverit (Sivu %%page%%/%%max_page%%) " +mcp_miscellaneous.481=" Parhaat kaverit (Sivu %%page%%/%%max_page%%) " +mcp_miscellaneous.482="Klikkaa näyttääksesi pelaajan %%player%% profiili" +mcp_miscellaneous.483="%%player%% ei ole juuri nyt paikalla" +mcp_miscellaneous.484="%%player%% on juuri nyt %%color%%poissa" +mcp_miscellaneous.485="%%player%% on juuri nyt %%color%%kiireinen" +mcp_miscellaneous.486="%%player%% on juuri nyt %%color%%%%status%%" +mcp_miscellaneous.487="%%player%% on Limbossa" +mcp_miscellaneous.488="%%player%% on Päälobbyssa" +mcp_miscellaneous.489="%%player%% on Tournament Hallissa" +mcp_miscellaneous.490="%%player%% on %%presence%%" +mcp_miscellaneous.491="%%player%% on %%lobby%% -lobbyssa" +mcp_miscellaneous.492="%%player%% on %%lobby%% -lobbyssa" +mcp_miscellaneous.493="%%player%% on tuntemattomassa maailmassa" +mcp_miscellaneous.494="%%player%% on pelaamassa SMP:tä" +mcp_miscellaneous.495="%%player%% on jossain" +mcp_miscellaneous.496="%%player%% on talossa %%name%%" +mcp_miscellaneous.497="%%player%% on Housingissa" +mcp_miscellaneous.498="%%player%% on Hypixel Pitissä" +mcp_miscellaneous.499="%%player%% on SkyBlockissa – %%island%%" +mcp_miscellaneous.500="%%player%% on SkyBlockissa" +mcp_miscellaneous.501="%%player%% on katsomassa replayta" +mcp_miscellaneous.502="%%player%% on %%game%% -pelissä" +mcp_miscellaneous.503="%%player%% on %%game%% -pelissä" +mcp_miscellaneous.504="Viimeksi nähty %%duration%% sitten" +mcp_miscellaneous.505="Kavereita %%duration%% ajan" +mcp_miscellaneous.506="Tämä pelaaja on estänyt sinut!" +mcp_miscellaneous.507="Tämä pelaaja ei ole paikalla!" +mcp_miscellaneous.508="Tämä komento ei ole juuri nyt saatavilla." +mcp_miscellaneous.509="Täällä ei ole odottavia ääniviestejä sinulle. Jotkin ääniviestit ovat voineet jo vanhentua." +mcp_miscellaneous.510="Olet ajan tasolla, ei enenmnpää odottavia ääniviestejä." +mcp_miscellaneous.511="Sinulla ei ole odottavia ääniviestejä." +mcp_miscellaneous.512="Virheellinen komento! '/friend %%command%%" +mcp_miscellaneous.513="Olet lähtenyt liian monesta %%game%% pelistä aikaisin!" +mcp_miscellaneous.514="Olet estetty liittymään uuteen peliin vasta 1 minuutin päästä." +#mcp_miscellaneous.515="" # No translation available +#mcp_miscellaneous.516="" # No translation available +#mcp_miscellaneous.517="" # No translation available +#mcp_miscellaneous.518="" # No translation available \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/prototype_lobby.properties b/configuration/i18n/fi_FI/official/prototype_lobby.properties new file mode 100644 index 000000000..ff96d5cbb --- /dev/null +++ b/configuration/i18n/fi_FI/official/prototype_lobby.properties @@ -0,0 +1,29 @@ +prototype_lobby.hype="Hype" +prototype_lobby.1="Hype: %%hype%%/%%maxHype%%" +prototype_lobby.2="Hypeä käytetään näyttämään, kuinka innoissasi olet Prototype-peleistä. Ansaitse Hypeä pelaamalla Prototype Lobbyn pelejä!" +prototype_lobby.3="Lisää hypeä peliin %%game%%" +prototype_lobby.4="Klikkaa lisätäksesi Hypeä peliin %%game%%!" +prototype_lobby.5="Hype" +prototype_lobby.6="Hypetä peliä %%game%%" +prototype_lobby.7="Lisää kaiken Hypesi peliin %%game%%." +prototype_lobby.8="Lisää %%hype%% Hypeä peliin %%game%%." +prototype_lobby.9="Klikkaa hypettääksesi!" +prototype_lobby.10="Anna kaikki Hype" +prototype_lobby.11="%%hype%% Hypeä" +prototype_lobby.12="Lisäsit %%hype%% Hypeä peliin %%game%%!" +prototype_lobby.13="Sinulla ei ole yhtään Hypeä. Ansaitse sitä pelaamalla Prototype Lobbyn minipelejä!" +prototype_lobby.14="Sinulla ei ole tarpeeksi Hypeä. Ansaitse sitä pelaamalla Prototype Lobbyn minipelejä!" +prototype_lobby.15="Tämä lobby on juuri nyt suljettu." +prototype_lobby.16=" Olet saavuttanut Hype-rajasi! Lisää Hypeä Prototype Lobbyn minipeleihin oikeaklikkaamalla Hype-timanttia!" +prototype_lobby.17="MAX HYPE" +prototype_lobby.18="Hypemittari" +prototype_lobby.19="KLIKKAA SAADAKSESI LISÄTIETOA" +prototype_lobby.20="JULKAISTU" +prototype_lobby.21="Hype: %%hype%%/%%maxHype%%" +prototype_lobby.22="Tervetuloa Prototype Lobbyyn" +prototype_lobby.23="Kaikki tämän lobbyn pelit ovat vasta kehitteillä." +prototype_lobby.24="Klikkaa tästä antaaksesi palautetta!" +prototype_lobby.25="Hype-timantti (Oikeaklikkaa)" +prototype_lobby.26="Tämän lobbyn pelit ovat vasta kehitteillä!" +prototype_lobby.27="Ilmoita bugeista ja jätä palautetta osoitteessa hypixel.net/ptl" +prototype_lobby.28="Tämä peli julkaistaan varmasti, sitä ei tarvitse hypettää!" \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/replays.properties b/configuration/i18n/fi_FI/official/replays.properties new file mode 100644 index 000000000..c5b64d29b --- /dev/null +++ b/configuration/i18n/fi_FI/official/replays.properties @@ -0,0 +1,123 @@ +replays.0="Katselet jo tuota replay-nauhoitusta!" +replays.1="Suorittanut %%player%%" +replays.2="Elokuvakamerat (BETA)" +replays.3="Klikkaa ilmiantaaksesi!" +replays.4="Toista nauhoitus uudelleen" +replays.5="Vasenklikkaa siirtyäksesi tähän aikaan!" +replays.6="Et voi laskea nopeutta enempää!" +replays.7="Ilmianna %%name%%" +replays.8="Tämä replay on liian lyhyt aikajanan luomiseksi" +replays.9="%%value%%s taaksepäin" +replays.10="%%name%% poissa käytöstä!" +replays.11="Replayta ei löydetty?!" +replays.12="Klikkaa poistuaksesi!" +replays.13="Et voi kasvattaa nopeutta enempää!" +replays.14="Klikkaa lukeaksesi lisää Replay Vieweristä" +replays.15="Teleporttaa pelaajan luo" +replays.16="Hallitse replayn katseluasetuksiasi." +replays.17="Asetukset" +replays.18="sinut" +replays.19="Replay Viewer" +replays.20="%%value%%s eteenpäin" +replays.21="Klikkaa laittaaksesi chattiin!" +replays.22="Klikkaa pysäyttääksesi" +replays.23="Lisää" +replays.24="Katsomasi Replay sammutettiin!" +replays.25="Valittuna nyt: %%option%%" +replays.26="Et voi ilmiantaa itseäsi!" +replays.27="Klikkaa tästä syöttääksesi jakokomennon chattiin!" +replays.28="Klikkaa jatkaaksesi" +replays.29="Klikkaa jakaaksesi!" +replays.30="Ilmianna pelaaja" +replays.31="Yhteytesi katkaistiin, sillä et tehnyt mitään! " +replays.32="Tämä pelaaja on poistunut!" +replays.33="Komento: /tp [kohdepelaaja]" +replays.34="Klikkaa keskeyttääksesi" +replays.35="Aika: %%time%% sekuntia" +replays.36="Et voi jakaa tätä replayta!" +replays.37="Ilmiantoa ei voida syöttää juuri nyt, yritä pian uudelleen!" +replays.38="Katsojan Asetukset" +replays.39="Tällä palvelimella ei ole replayta sinulle. Jos tämä tapahtuu jatkuvasti, ilmoitathan asiasta ylläpidolle." +replays.40="Ilmianna tämä pelaaja syystä %%type%%." +replays.41="Sinut asetetaan AFK-tilaan 10 sekunnin kuluttua!" +replays.42="Ei kirjanmerkkejä!" +replays.43="Näytä tämän nauhoituksen kirjanmerkit." +replays.44="Kirjanmerkkejä ei löytynyt!" +replays.45="Vasenklikkaa teleportataksesi!" +replays.46="Sinut potkittiin, koska sinulla on replay auki liian kauan! " +replays.47="Hypixel Replay Viewer" +replays.48=" LUE LISÄÄ" +replays.49="Jaa tämä replay oman aikasi ja sijaintisi kanssa." +replays.50="Replay-nauhoitusten kautta ilmiantaminen on tällä hetkellä poissa käytöstä. Yritäthän myöhemmin uudestaan!" +replays.51="Sinulla ei ole oikeuksia katsoa replay-nauhoituksia." +replays.52="Pelaajia ei löytynyt!" +replays.53="Hidasta nopeutta" +replays.54="Hypixel Replay on BETA-tilassa! Ilmoitathan vioista osoitteessa https://hypixel.net/bugs" +replays.55="Oikeaklikkaa jakaaksesi!" +replays.56="%%player%% käytti komentoa /%%command%%" +replays.57="Oikeaklikkaa katsoaksesi tämän pelaajan näkökulmasta!" +replays.58="Kirjanmerkit" +replays.59="Kiitos ilmiannostasi pelaajaa %%name%% vastaan! Tämä replay-nauhoitus lähetetään ilmiannon mukana." +replays.60="Klikkaa asettaaksesi %%setting%%: %%option%%" +replays.61="Pelaaja: %%player%%" +replays.62="Ei katsojaa!" +replays.63="Kirjanmerkki luotu!" +replays.64="Odota vähän ennen kuin käytät tuota!" +replays.65="Menit liian kauas kartasta!" +replays.66="Jaa" +replays.67="Sinut poistettiin koska replay-nauhoitus oli auki liian pitkään!" +replays.68="Lisää nopeutta" +replays.69="Teleportataan %%name%% pelaajan %%destination%% luo." +replays.70="%%color%%%%name%%" +replays.71="Poistu Replaystä" +replays.72="%%name%% otettu käyttöön!" +replays.73="Ei katsojaa?!" +replays.74="En tiedä mihin haluat teleportata!" +replays.75="Et voi luoda kirjanmerkkejä tälle replay-nauhoitukselle!" +replays.76="Ilmianna tämä pelaaja sääntöjen rikkomisesta. Tämä replay-nauhoitus lähetetään ilmiannon mukana." +replays.77="Odotetaan" +replays.78="Toistetaan" +replays.79="Keskeytetty" +replays.80="Loppunut" +replays.81="Olet saavuttanut aktiivisten kohokohtien enimmäismäärän! Yritä myöhemmin uudelleen!" +replays.82="Kohokohta lähetetty!" +replays.83="Lähetä kohokohta" +replays.84="Teitkö jotain siistiä? Jaa nykyinen aikaleimasi ja sijaintisi meille saadaksesi mahdollisuuden esitellä sitä Hypixelin sosiaalisessa mediassa!" +replays.85="Lähettämällä tämän kohokohdan hyväksyt, että Hypixelin palvelin saattaa käyttää materiaalia Hypixelin Twitterissä, TikTokissa, Instagramissa tai muulla sosiaalisen median alustalla. Varmistathan, että olet oikeassa sijainnissa ja oikeaan aikaan esitelläksesi kohokohtaa!" +replays.86="Klikkaa lähettääksesi!" +replays.87="Vasenklikkaa muuttaksesi kestoa." +replays.88="Päivämäärä: " +replays.89="Aika: " +replays.90="Tuo epäonnistui, yritä pian uudelleen!" +replays.91="Ladataan replayta ..." +replays.92="Kartta: " +replays.93="Peli: " +replays.94="Sinun on pelattava Minecraftia protokollaversiolla %%version%% tai uudemmalla katsoaksesi tämän replayn." +replays.95="Replay on keskeytetty." +replays.96="Pisin pykälä: " +replays.97="Replay on pysäytetty." +replays.98="Keskiklikkaa syöttääksesi UUID:n chattiin!" +replays.99="Lähetä päätös" +replays.100="Replay" +replays.101="Sinun on pelattava Minecraftia versiolla %%version%% tai uudemmalla katsoaksesi tämän replayn." +replays.102="Havainto: %%detection%%" +replays.103="Pelimuoto: " +replays.104="Löydettiin pelaajaa vastaava kirjanmerkki... ohitetaan %%ticks%% pykälään!" +replays.105="Pelaajat" +replays.106="Replay kohteesta " +replays.107="Chat-viestit" +replays.108="Piilota tai näytä pelin tappo- ja toimintoviestit." +replays.109="Chat-aikajana" +replays.110="Piilota tai näytä replayn aikajana chatissa." +replays.111="Näytä katsojat" +replays.112="Vaihda katsojien näkyvyyttä replayssa" +replays.113="Hämäränäkö" +replays.114="Vaihda pimeänäön tilaa replayta katsoessa." +replays.115="Lentonopeus" +replays.116="Kelausvälit" +replays.117="Ruokataso: %%level%%" +replays.118="Näytä partikkelit" +replays.119="Vaihda partikkeleiden näkyvyyttä replayta katseltaessa." +replays.120="Säädä lentonopeuttasi replayta katsoessasi. " +replays.121="Vaihda aikaväliä, jota käytetään, kun käytät eteen- ja taaksepäin-painikkeita. Voidaan myös vaihtaa vasenklikkaamalla painikkeita." +replays.122="Vaihda sivussa näkyvän ajan edistymisen tilaa replayta toistettaessa." \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/social_menu.properties b/configuration/i18n/fi_FI/official/social_menu.properties new file mode 100644 index 000000000..722fdf039 --- /dev/null +++ b/configuration/i18n/fi_FI/official/social_menu.properties @@ -0,0 +1,246 @@ +social_menu.0="Guildin johtaja on vastuussa guildchatin moderoinnista." +social_menu.1="Suositellut:" +social_menu.2="Potki guildista" +social_menu.3="Poistu guildista" +social_menu.4="Klikkaa potkiaksesi pelaaja guildista" +social_menu.5="Klikkaa poistuaksesi guildista, jossa olet." +social_menu.6="Klikkaa peruuttaaksesi." +social_menu.7="Partyn johtaja on vastuussa partychatin moderoinnista." +social_menu.8="Potki partysta" +social_menu.9="Poistu partysta" +social_menu.10="Klikkaa potkiaksesi pelaajan partystasi." +social_menu.11="Klikkaa tästä poistuaksesi partysta." +social_menu.12="Jos pelaaja häiritsee sinua yksityisviesteissä, suosittelemme poistamaan hänet ystävälistaltasi." +social_menu.13="Poista ystävä & estä" +social_menu.14="Klikkaa poistaaksesi tämän pelaajan ystävistäsi ja estä hänet." +social_menu.15="Poista ystävä" +social_menu.16="Klikkaa poistaaksesi tämän pelaajan ystävistäsi." +social_menu.17="ILMOITA" +social_menu.18="Yhteisöpaneeli" +social_menu.19="Poista kaveri" +social_menu.20="Klikkaa poistaaksesi pelaaja %%player%% kaverilitaltasi." +social_menu.21="Lisää kaveri" +social_menu.22="Klikkaa lähettääksesi kaveripyyntö pelaajalle %%player%%." +social_menu.23="Vain Sihteerit ja Guildin johtaja voivat tehdä tämän." +social_menu.24="Vain Guildin johtaja voi tehdä tämän." +social_menu.25="Tämä pelaaja ei ole guildissasi." +social_menu.26="Sinun tulee olla guildissa tehdäksesi tämän." +social_menu.27="Potki guildista" +social_menu.28="Klikkaa poistaaksesi pelaaja %%player%% guildistasi." +social_menu.29="Kutsu guildiin" +social_menu.30="Klikkaa kutsuaksesi pelaaja %%player%% guildiisi." +social_menu.31="Anna syy" +social_menu.32="Et voi kutsua pelaajaa %%player%% guildiisi, sillä tämä on jo guildissa." +social_menu.33="Alenna Jäseneksi" +social_menu.34="Klikkaa alentaaksesi pelaaja %%player%% guildisi Jäseneksi." +social_menu.35="Ylennä Sihteeriksi" +social_menu.36="Klikkaa ylentääksesi pelaaja %%player%% guildisi Sihteeriksi." +social_menu.37="Et voi käyttää tätä, sillä et ole guildissa." +social_menu.38="Et voi käyttää tätä, sillä pelaaja %%player%% ei ole guildissasi." +social_menu.39="Poista pelaaja estettyjen listaltasi" +social_menu.40="Klikkaa poistaaksesi pelaaja %%player%% estettyjen listaltasi." +social_menu.41="Estä pelaaja" +social_menu.42="Klikkaa lisätäksesi pelaaja %%player%% estettyjen listallesi." +social_menu.43="Potki partysta" +social_menu.44="Klikkaa poistaaksesi pelaaja %%player%% partystasi." +social_menu.45="Kutsu partyyn" +social_menu.46="Klikkaa kutsuaksesi pelaaja %%player%% partyysi." +social_menu.47="Vain partyn johtaja voi potkia pelaajia partysta." +social_menu.48="Ylennä partyn johtajaksi" +social_menu.49="Klikkaa ylentääksesi pelaaja %%player%% partyn johtajaksi." +social_menu.50="Et voi käyttää tätä, sillä pelaaja %%player%% ei ole partyssasi." +social_menu.51="Sinun tulee olla partyn johtaja käyttääksesi tätä." +social_menu.52="Sinun tulee olla partyssa käyttääksesi tätä." +social_menu.53="Sulje" +social_menu.54="Ei mitään" +social_menu.55="Nykyinen: %%value%%" +social_menu.56="Vasenklikkaa vaihtaaksesi!" +social_menu.57="Oikeaklikkaa poistaaksesi!" +social_menu.58="Kuka tahansa voi nähdä linkkamasi sometilit!" +social_menu.59="Liitä Discord-käyttäjänimesi tai kutsulinkkisi chattiin:" +social_menu.60="Liitä %%socialMedia%%-linkkisi chattiin:" +social_menu.61=" > Pelaajan %%name%% Discord-käyttäjänimi on %%username%% <" +social_menu.62=" > Klikkaa tästä vieraillaksesi pelaajan %%name%% %%socialMedia%%-tilillä! < " +social_menu.63="Tämä %%socialMedia%%-sivu ei ole Hypixelin omistama tai operoima, joten emme voi taata sisällön sopivuutta. Avaa sivu omalla vastuullasi." +social_menu.64="Sinun %%socialMedia%%-linkkisi on nyt %%url%%!" +social_menu.65="URL %%url%% on virheellinen!" +social_menu.66="Tällä hetkellä PÄÄLLÄ" +social_menu.67="Tällä hetkellä POISSA PÄÄLTÄ" +social_menu.68="Chat-ilmianto" +social_menu.69="Klikkaa tästä ilmiantaaksesi pelaajan %%name%% chattiin liittyvistä rikkomuksista." +social_menu.70="Missä %%nimi%% rikkoi sääntöjä?" +social_menu.71="> Julkinen chat" +social_menu.72="> Yksityisviestit" +social_menu.73="> Partychat" +social_menu.74="> Guildin chat" +social_menu.75="Huijausilmianto" +social_menu.76="Klikkaa tästä ilmiantaaksesi pelaajan %%name%% kiellettyjen huijausten käyttämisestä." +social_menu.77="Guildin asetukset" +social_menu.78="Liityttävissä" +social_menu.79="Muokkaa monenlaisia Guildeihin liittyviä asetuksia, kuten mieltymyksiä ja koko guildiin vaikuttavia asetuksia." +social_menu.80="Voivatko pelaajat pyytää lupaa liittyä guildiin." +social_menu.81="Ilmoitukset" +social_menu.82="Näetkö guildisi jäsenten liittymis- ja poistumisilmoitukset." +social_menu.83="Guildin asetukset" +social_menu.84="Muokkaa guildin tunnistetta" +social_menu.85="Vaihtaa tunnisteen guildin jäsenten nimien vieressä." +social_menu.86="Et ole guildissa!" +social_menu.87="Vain guildin johtaja voi muokata tätä!" +social_menu.88="Syötä guildisi\ntunniste!" +social_menu.89="Sosiaalinen media" +social_menu.90="Klikkaa muokataksesi sosiaalisen median tilejäsi." +social_menu.91="Klikkaa tarkastellaksesi pelaajan %%player%% sosiaalisen median tilejä." +social_menu.92="Sosiaalinen media" +social_menu.93="Ei sosiaalisen median tilejä" +social_menu.94="%%player%% ei ole linkannut yhtään sosiaalisen median tiliään." +social_menu.95="Hitsi! Ei yhtään kavereita :(" +social_menu.96="Voit lisätä kavereita klikkaamalla \"Lisää kaveri\" -kirjaa oikeassa ylänurkassa tai komennolla /friend add Nimi!" +social_menu.97="Kaverit" +social_menu.98="Tarkastele Hypixel-kavereidesi profiileja ja juttele heidän kanssaan!" +social_menu.99="Klikkaa lisätäksesi kaveri kaverilistaasi." +social_menu.100="Ystävät voivat nähdä mitä muut tekevät palvelimella ja ketkä ovat paikalla." +social_menu.101="Syötä käyttäjänimi" +social_menu.102="Klikkaa poistaaksesi ystäväsi kaverilistaltasi." +social_menu.103="Guild" +social_menu.104="Muodosta guild muiden Hypixelin pelaajien kanssa valloittaaksenne eri pelimuotoja ja saavuttaaksenne yhteisiä palkintoja." +social_menu.105="Kutsu pelaaja" +social_menu.106="Poista pelaaja" +social_menu.107="Guildin arvonimi: %%rank%%" +social_menu.108="Liittynyt jäseneksi: %%time%%" +social_menu.109="Jäsen" +social_menu.110="Sihteeri" +social_menu.111="%%time%% sitten" +social_menu.112="Luo guild" +social_menu.113="Et ole guildissa" +social_menu.114="Klikkaa tästä luodaksesi oma guildisi!" +social_menu.115="Vain pelaajat, joilla on VIP+ tai korkeampi, voivat luoda guildeja, mutta kuka tahansa voi liittyä niihin." +social_menu.116="Klikkaa selataksesi guildeja nettisivuillamme!" +social_menu.117="Syötä guildin nimi" +social_menu.118="Klikkaa tarkastellaksesi guildeja Hypixel Foorumeilla" +social_menu.119="Klikkaa vieraillaksesi foorumeilla" +social_menu.120="Näytä profiili" +social_menu.121="Näyttää informaatiota profiilistasi." +social_menu.122="Party" +social_menu.123="Luo party ja liity pelaamaan pelejä yhdessä muiden pelaajien kanssa!" +social_menu.124="Siirrä party" +social_menu.125="Kutsuu pelaajan partyysi." +social_menu.126="Poistaa pelaajan partystasi." +social_menu.127="Teleportaa kaikki partyn jäsenet lobbyysi." +social_menu.128="Hajota party" +social_menu.129="Hajottaa nykyisen partyn." +social_menu.130="Poistu partysta" +social_menu.131="Poistu nykyisestä partysta." +social_menu.132="Mene Housingiin" +social_menu.133="Vieraile Housingissa" +social_menu.134="Näyttää informaatiota pelaajasta %%player%%." +social_menu.135="Viimeisimmät pelaajat" +social_menu.136="Tyhjennä viimeisimmät pelaajat" +social_menu.137="Tyhjentää viimeisimpien pelaajien listasi." +social_menu.138="Viimeisimpiä pelaajia ei löydetty" +social_menu.139="Pelaile muutama peli palvelimella, ja palaa tarkastelemaan pelaajia, joiden kanssa olet pelannut!" +social_menu.140="Viimeisimmät pelaajat" +social_menu.141="Tarkastele pelaajia, joiden kanssa olet pelannut viimeaikaisia pelejä." +social_menu.142="Virhe ladattaessa päätä" +social_menu.143="Tavattu pelaamassa: %%game%%" +social_menu.144="Hypixel-level: %%level%%" +social_menu.145="Guild: %%guild%%" +social_menu.146="Ei mitään" +social_menu.147="Online-tila: %%status%%" +social_menu.148="Paikalla" +social_menu.149="%%game%% -lobby #%%number%%" +social_menu.150="Päälobby %%number%%" +social_menu.151="Palvelin: %%server%%" +social_menu.152="Peli: %%game%%" +social_menu.153="Viimeksi paikalla: %%time%%" +social_menu.154="Tapahtui virhe, yritä uudelleen hetken kuluttua." +social_menu.155="Datan lataamisessa tapahtui virhe. Yritä uudelleen." +social_menu.156="Ei tuloksia" +social_menu.157="Ei tuloksia hakusanalla '%%query%%'!" +social_menu.158="VASENKLIKKAA palataksesi edelliselle sivulle" +social_menu.159="OIKEAKLIKKAA siirtyäksesi ensimmäiselle sivulle" +social_menu.160="Sivu %%current%%/%%total%%" +social_menu.161="VASENKILKKAA siirtyäksesi seuraavalle sivulle" +social_menu.162="OIKEAKLIKKAA siirtyäksesi viimeiselle sivulle" +social_menu.163="%%name%%: %%description%%" +social_menu.164="Aakkosellinen" +social_menu.165="Näytä kaikki listattuna A-Z" +social_menu.166="Viimeksi paikalla" +social_menu.167="Näytä kaikki siinä järjestyksessä, milloin he olivat viimeksi paikalla" +social_menu.168="Viimeksi tavattu" +social_menu.169="Näytä kaikki siinä järjestyksessä missä tapasit heidät" +social_menu.170="Aakkosellinen järjestys, mutta näytä online-tilassa olevat ensin" +social_menu.171="Guild Rank -järjestys, sitten aakkosellinen järjestys, sitten Online-tilanne" +social_menu.172="Järjestä Guild Rankin perusteella, sitten aakkosellisesti" +social_menu.173="VASENKLIKKAA selataksesi kaikkia saatavilla olevia järjestelyvaihtoehtoja." +social_menu.174="OIKEAKLIKKAA asettaaksesi järjestyksen käänteiseksi!" +social_menu.175="Vaihda järjestystä" +social_menu.176="Tämänhetkinen järjestys: %%sort%%" +social_menu.177="Järjestyksen suunta: %%order%%" +social_menu.178="Hae pelaajia" +social_menu.179="Tyhjennä hakutulokset" +social_menu.180="Ilmianna pelaaja" +social_menu.181="Luo party" +social_menu.182="Klikkaa kutsuaksesi pelaaja partyysi" +social_menu.183="Voit käyttää Yhteisövalikkoa vain lobbyssa" +social_menu.184="Virheellinen komento!" +social_menu.185="Ota huomioon: Vaikka voitkin linkata sosiaalisen median käyttötilejäsi profiiliisi, on sääntöjenvastaista mainostaa niitä muille pelaajille chatissa." +social_menu.186="Tämän säännön rikkominen johtaa hiljennykseen tai porttikieltoon." +social_menu.187="TARKASTELE SÄÄNTÖJÄ" +social_menu.188="https://hypixel.net/rules" +social_menu.189="YMMÄRRÄN" +social_menu.190="toinen" +social_menu.191="sekuntia" +social_menu.192="minuutti" +social_menu.193="minuuttia" +social_menu.194="tuntia" +social_menu.195="päivää" +social_menu.196="Klikkaa nähdäksesi asetukset pelaajalle %%player%%" +social_menu.197="Ei mitään" +social_menu.198="Klikkaa näyttääksesi pelaajan %%who%% profiili!" +social_menu.199="Klikkaa kutsuaksesi pelaaja Guildiisi." +social_menu.200="Muokkaa asetuksia, kuten tunnistetta, käyttöoikeuksia ja guild finder -asetuksia" +social_menu.201="Guildin tunniste" +social_menu.202="Avautuu nostamalla Guildin tasoa!" +social_menu.203="Vaihtaa guildin jäsenen nimen vieressä näkyvän tunnisteen väriä." +social_menu.204="Klikkaa nähdäksesi saatavilla olevat värit!" +social_menu.205="Näkyy Guild-etsimessä" +social_menu.206="Guildin pelit" +social_menu.207="Klikkaa valitaksesi pelejä!" +social_menu.208="Muuttaa Guild-etsimessä näkyvää pelilistaa." +social_menu.209="Guild-etsin" +social_menu.210="Etsi guildeja" +social_menu.211="Voit etsiä Hypixelin Foorumeilta guildeja joihin voisit liittyä." +social_menu.212="Klikkaa katsellaksesi" +social_menu.213="Guildin johtaja: " +social_menu.214="Jäsenet: " +social_menu.215="Guildin taso: " +social_menu.216="Pelit: " +social_menu.217="ei mitään" +social_menu.218="Klikkaa pyytääksesi lupaa liittyä" +social_menu.219="Olet jo tässä guildissa" +social_menu.220="Pyytääksesi liittymistä, sinun on ensin erottava nykyisestä guildistasi" +social_menu.221="Etsi Guild johon voit liittyä lempipeliesi perusteella" +social_menu.222="Järjestää viimeksi paikalla olleiden mukaan" +social_menu.223="Näyttää korkeimman Guildin rankin ensin" +social_menu.224="Kuinka kauan pelaaja on ollut guildissa" +social_menu.225="Järjestä Saavutuspisteiden mukaan" +social_menu.226="Järjestä Hypixel-levelin mukaan" +social_menu.227="Sinulla ei ole tarvittavia oikeuksia" +social_menu.228="Ilmianna %%player%%" +social_menu.229="Lähetä Duel-pyyntö" +social_menu.230="Muokkaamiseen tarvittavat oikeudet puuttuvat!" +social_menu.231="%%game%% -lobby" +social_menu.232="Järjestä edellisen paikallaoloajan mukaan" +social_menu.233="Alenna alemmalle arvonimelle" +social_menu.234="Klikkaa tästä alentaaksesi pelaajan %%player%% alemmalle guild-arvonimelle." +social_menu.235="Ylennä korkeammmalle arvonimelle" +social_menu.236="Klikkaa tästä ylentääksesi pelaajan %%player%% korkeammalle guild-arvonimelle." +social_menu.237="Alenna alemmalle guild-arvonimelle" +social_menu.238="Ylennä korkeammalle guild-arvonimelle" +social_menu.239="Ylennä partyssa" +social_menu.240="Klikkaa ylentääksesi pelaaja %%player%% partyssasi." +social_menu.241="Klikkaa nähdäksesi sosiaaliasetukset pelaajalle %%who%%" +social_menu.242="Party-komennot:\n" +social_menu.243="Ender-taso" +social_menu.244="Pimeä ender-taso" +social_menu.245="Pelaajat, joilla on MVP tai korkeampi\nvoivat käyttää komentoa /stats (nimi)\ntarkastellakseen muiden tilastoja." \ No newline at end of file diff --git a/configuration/i18n/fi_FI/official/toolbox_miscellaneous.properties b/configuration/i18n/fi_FI/official/toolbox_miscellaneous.properties new file mode 100644 index 000000000..8c0a646c0 --- /dev/null +++ b/configuration/i18n/fi_FI/official/toolbox_miscellaneous.properties @@ -0,0 +1,27 @@ +toolbox_miscellaneous.0="Penguin Companion" +toolbox_miscellaneous.1="Turtle Companion" +toolbox_miscellaneous.2="Gifterino Companion" +toolbox_miscellaneous.3="Black Pug Companion" +toolbox_miscellaneous.4="Duck Companion" +toolbox_miscellaneous.5="Frog Companion" +toolbox_miscellaneous.6="Sloth Companion" +toolbox_miscellaneous.7="Hp8 Companion" +toolbox_miscellaneous.8="White Pug Companion" +toolbox_miscellaneous.9="Shibe Companion" +toolbox_miscellaneous.10="Chimp Companion" +toolbox_miscellaneous.11="Panda Companion" +toolbox_miscellaneous.12="Elephant Companion" +toolbox_miscellaneous.13="Jack Dog Companion" +toolbox_miscellaneous.14="%%count%% Loot Chests" +toolbox_miscellaneous.15="%%days%% rankkia %%rank%%" +toolbox_miscellaneous.16="%%count%% Bed Wars Loot Chests" +toolbox_miscellaneous.17="%%count%% Spooky Bed Wars Loot Chests" +toolbox_miscellaneous.18="%%count%% Murder Mystery Loot Chests" +toolbox_miscellaneous.19="%%count%% Merry Bed Wars Loot Chests" +toolbox_miscellaneous.20="%%count%% Merry Murder Mystery Loot Chests" +toolbox_miscellaneous.21="%%count%% Lunar Bed Wars Loot Chests" +toolbox_miscellaneous.22="%%count%% SkyWars Loot Chests" +toolbox_miscellaneous.23="%%count%% Easter Bed Wars Loot Chests" +toolbox_miscellaneous.24="%%count%% Easter SkyWars Loot Chests" +toolbox_miscellaneous.25="%%count%% Golden Bed Wars Loot Chests" +toolbox_miscellaneous.26="Gorilla Companion" \ No newline at end of file diff --git a/configuration/i18n/hypixel_converter.py b/configuration/i18n/hypixel_converter.py new file mode 100644 index 000000000..1c5fb586d --- /dev/null +++ b/configuration/i18n/hypixel_converter.py @@ -0,0 +1,60 @@ +import os +import re + +format = { + "black": "black", + "dark_blue": "dark_blue", + "dark_green": "dark_green", + "dark_aqua": "dark_aqua", + "dark_red": "dark_red", + "dark_purple": "dark_purple", + "gold": "gold", + "gray": "gray", + "dark_gray": "dark_gray", + "blue": "blue", + "green": "green", + "aqua": "aqua", + "red": "red", + "light_purple": "light_purple", + "yellow": "yellow", + "white": "white", + "bold": "bold", + "italic": "italic", + "underlined": "underlined", + "strikethrough": "strikethrough", + "obfuscated": "obfuscated", + "reset": "reset" +} + + +def convert_line(line): + def replacer(match): + code = match.group(1) + + if code in format: + return f"<{format[code]}>" + else: + return match.group(0) + + return re.sub(r"%%(.*?)%%", replacer, line) + + +def main(): + file_path = input("relative file path: ").strip() + + if not os.path.isfile(file_path): + print("could not find file") + return + + with open(file_path, "r", encoding="utf-8") as f: + lines = f.readlines() + + converted_lines = [convert_line(line) for line in lines] + with open(file_path, "w", encoding="utf-8") as f: + f.writelines(converted_lines) + + print("converted the file") + + +if __name__ == "__main__": + main() diff --git a/configuration/server.toml b/configuration/server.toml index ba61d89f5..e0fa7f2a6 100644 --- a/configuration/server.toml +++ b/configuration/server.toml @@ -16,9 +16,9 @@ secret = "${FORWARDING_SECRET}" [world] spawn_position = [ - -22.5, - 31.06250, - 21.5, + 16.5, + 22.06250, + 8.5, ] spawn_rotation = [ -90.0, @@ -29,8 +29,7 @@ time = "day" [world.experimental] view_distance = 4 -schematic_file = "" -polar_file = "limbo.polar" +schematic_file = "limbo.schem" lock_time = false [world.boundaries] diff --git a/configuration/skyblock/furniture/hub_swords.json b/configuration/skyblock/furniture/hub_swords.json new file mode 100644 index 000000000..99a0f0848 --- /dev/null +++ b/configuration/skyblock/furniture/hub_swords.json @@ -0,0 +1,114 @@ +[ + { + "type": "minecraft:armor_stand", + "position": { + "x": -0.021884863069715266, + "y": -0.16696476165546414, + "z": -0.2075808103294321 + }, + "rotation": { + "yaw": 90.0, + "pitch": 0.0 + }, + "invisible": true, + "small": false, + "marker": false, + "showArms": true, + "showBasePlate": true, + "equipment": { + "mainhand": { + "id": "minecraft:wooden_sword", + "count": 1, + "snbt": "{count:1,id:\"minecraft:wooden_sword\"}" + } + }, + "pose": { + "head": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "body": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "leftArm": { + "x": -10.0, + "y": 0.0, + "z": -10.0 + }, + "rightArm": { + "x": 71.0, + "y": 50.0, + "z": -6.0 + }, + "leftLeg": { + "x": -19.0, + "y": 0.0, + "z": 15.0 + }, + "rightLeg": { + "x": 1.0, + "y": 0.0, + "z": 1.0 + } + } + }, + { + "type": "minecraft:armor_stand", + "position": { + "x": 0.5064550143374333, + "y": -0.25, + "z": 0.07497938488566547 + }, + "rotation": { + "yaw": -135.0, + "pitch": 0.0 + }, + "invisible": true, + "small": false, + "marker": false, + "showArms": true, + "showBasePlate": true, + "equipment": { + "mainhand": { + "id": "minecraft:iron_sword", + "count": 1, + "snbt": "{count:1,id:\"minecraft:iron_sword\"}" + } + }, + "pose": { + "head": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "body": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "leftArm": { + "x": -10.0, + "y": 0.0, + "z": -10.0 + }, + "rightArm": { + "x": 71.0, + "y": 25.0, + "z": -31.0 + }, + "leftLeg": { + "x": -1.0, + "y": 0.0, + "z": -4.0 + }, + "rightLeg": { + "x": 1.0, + "y": 0.0, + "z": 1.0 + } + } + } +] \ No newline at end of file diff --git a/configuration/skyblock/furniture/pufferfish.json b/configuration/skyblock/furniture/pufferfish.json new file mode 100644 index 000000000..254bc4299 --- /dev/null +++ b/configuration/skyblock/furniture/pufferfish.json @@ -0,0 +1,41 @@ +[ + { + "type": "minecraft:item_display", + "position": { + "x": 0.0625, + "y": 1.125, + "z": 0.0625 + }, + "rotation": { + "yaw": 0.0, + "pitch": 0.0 + }, + "translation": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "scale": { + "x": 0.8000001, + "y": 0.7999999, + "z": 0.8 + }, + "leftRotation": { + "x": 0.14315604, + "y": 0.27953273, + "z": -0.12069224, + "w": 0.94170135 + }, + "rightRotation": { + "x": 0.0, + "y": 0.0, + "z": 0.0, + "w": 1.0 + }, + "item": { + "id": "minecraft:player_head", + "count": 1, + "snbt": "{components:{\"minecraft:profile\":{id:[I;1026653912,-261338970,-1604133959,-588724720],properties:[{name:\"textures\",value:\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGQzMTM1ZjliNWNiZGRiZDczNTRmNmNlZjVhYzljNDMyMDc1MjEwNTg4ZTBhNTQwMjMxMzczYzEwZWM5NWRhMyJ9fX0=\"}]}},count:1,id:\"minecraft:player_head\"}" + } + } +] \ No newline at end of file diff --git a/configuration/skyblock/items/armor/miner.yml b/configuration/skyblock/items/armor/miner.yml index fd29f1507..98b95844b 100644 --- a/configuration/skyblock/items/armor/miner.yml +++ b/configuration/skyblock/items/armor/miner.yml @@ -1,40 +1,4 @@ items: - - id: DIAMOND_HELMET - material: DIAMOND_HELMET - rarity: RARE - components: - - id: STANDARD_ITEM - standard_item_type: HELMET - default_statistics: - defense: 15.0 - mining_speed: 10.0 - - id: DIAMOND_CHESTPLATE - material: DIAMOND_CHESTPLATE - rarity: RARE - components: - - id: STANDARD_ITEM - standard_item_type: CHESTPLATE - default_statistics: - defense: 15.0 - mining_speed: 10.0 - - id: DIAMOND_LEGGINGS - material: DIAMOND_LEGGINGS - rarity: RARE - components: - - id: STANDARD_ITEM - standard_item_type: LEGGINGS - default_statistics: - defense: 15.0 - mining_speed: 10.0 - - id: DIAMOND_BOOTS - material: DIAMOND_BOOTS - rarity: RARE - components: - - id: STANDARD_ITEM - standard_item_type: BOOTS - default_statistics: - defense: 15.0 - mining_speed: 10.0 - id: CHAINMAIL_HELMET rarity: COMMON material: CHAINMAIL_HELMET diff --git a/configuration/skyblock/items/vanilla/items/armor/diamond.yml b/configuration/skyblock/items/vanilla/items/armor/diamond.yml index f737049ad..2df2917be 100644 --- a/configuration/skyblock/items/vanilla/items/armor/diamond.yml +++ b/configuration/skyblock/items/vanilla/items/armor/diamond.yml @@ -1,7 +1,7 @@ items: - id: DIAMOND_HELMET material: DIAMOND_HELMET - rarity: COMMON + rarity: UNCOMMON components: - id: STANDARD_ITEM standard_item_type: HELMET @@ -23,7 +23,7 @@ items: defense: 15.0 - id: DIAMOND_CHESTPLATE material: DIAMOND_CHESTPLATE - rarity: COMMON + rarity: UNCOMMON components: - id: STANDARD_ITEM standard_item_type: CHESTPLATE @@ -46,7 +46,7 @@ items: defense: 40.0 - id: DIAMOND_LEGGINGS material: DIAMOND_LEGGINGS - rarity: COMMON + rarity: UNCOMMON components: - id: STANDARD_ITEM standard_item_type: LEGGINGS @@ -69,7 +69,7 @@ items: defense: 30.0 - id: DIAMOND_BOOTS material: DIAMOND_BOOTS - rarity: COMMON + rarity: UNCOMMON components: - id: STANDARD_ITEM standard_item_type: BOOTS diff --git a/docker-compose.yml b/docker-compose.yml index 6116be85e..1dc8d7c30 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -174,7 +174,7 @@ services: # - hypixel_network pico_limbo: - image: ghcr.io/ariksquad/picolimbo:master + image: ghcr.io/quozul/picolimbo:v1.12.2-mc26.1.2 container_name: pico_limbo restart: unless-stopped environment: diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 78a3aa7ff..767fb3e30 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,48 +1,50 @@ [versions] -adventure = "4.26.1" +adventure = "5.1.1" annotations = "26.1.0" atlasRedis = "1.1.5" byte-buddy = "1.18.7" caffeine = "3.2.3" configlib-yaml = "4.8.1" configurate-yaml = "4.2.0" -creative = "1.7.3" +creative = "1.13.13" fastutil = "8.5.18" gson = "2.11.0" guava = "33.5.0-jre" jackson-annotations = "2.20" jackson-bom = "3.1.0" -javapoet = "1.13.0" +javapoet = "0.16.0" jedis = "7.2.0" joml = "1.10.8" -json = "20251224" +json = "20260522" junit = "4.13.2" junit-jupiter = "6.0.3" kotlin-stdlib = "2.3.20" lombok = "1.18.42" -minestom = "2026.04.13-1.21.11" +minestom = "2026.06.05-26.1.2" mongodb = "5.6.4" netty-bom = "4.2.9.Final" -polar = "1.15.0" +polar = "1.16.0" protocollib = "5.4.0" reflections = "0.10.2" sentry-async-profiler = "8.35.0" slf4j = "2.0.17" snakeyaml = "2.5" -spark-common = "1.10.158-20260110.094844-1" -spark-core = "2.9.4" -spigot-api = "1.21-R0.1-SNAPSHOT" +spark = "1.10.158-20260110.094844-1" +sparkjava = "2.9.4" tinylog = "2.7.0" velocity-api = "3.5.0-SNAPSHOT" -viabackwards = "5.7.2" -vialoader = "4.0.6" -viarewind = "4.0.15" -viaversion = "5.7.1" +viarewind = "4.1.1" +viaversion = "5.9.1" +packetevents = "2.12.2" +shadow = "9.4.1" +examination = "1.3.0" +zstd-jni = "1.5.7-4" [libraries] adventure-api = { module = "net.kyori:adventure-api", version.ref = "adventure" } adventure-text-minimessage = { module = "net.kyori:adventure-text-minimessage", version.ref = "adventure" } adventure-text-serializer-gson = { module = "net.kyori:adventure-text-serializer-gson", version.ref = "adventure" } +examination-api = { module = "net.kyori:examination-api", version.ref = "examination" } # kind of a legacy API annotations = { module = "org.jetbrains:annotations", version.ref = "annotations" } atlas-redis = { module = "com.github.Swofty-Developments:AtlasRedisAPI", version.ref = "atlasRedis" } byte-buddy = { module = "net.bytebuddy:byte-buddy", version.ref = "byte-buddy" } @@ -60,7 +62,7 @@ jackson-annotations = { module = "com.fasterxml.jackson.core:jackson-annotations jackson-bom = { module = "tools.jackson:jackson-bom", version.ref = "jackson-bom" } jackson-core = { module = "tools.jackson.core:jackson-core" } jackson-databind = { module = "tools.jackson.core:jackson-databind" } -javapoet = { module = "com.squareup:javapoet", version.ref = "javapoet" } +javapoet = { module = "com.palantir.javapoet:javapoet", version.ref = "javapoet" } jedis = { module = "redis.clients:jedis", version.ref = "jedis" } json = { module = "org.json:json", version.ref = "json" } joml = { module = "org.joml:joml", version.ref = "joml" } @@ -83,13 +85,16 @@ reflections = { module = "org.reflections:reflections", version.ref = "reflectio sentry-async-profiler = { module = "io.sentry:sentry-async-profiler", version.ref = "sentry-async-profiler" } slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "snakeyaml" } -spark-common = { module = "me.lucko:spark-common", version.ref = "spark-common" } -spark-core = { module = "com.sparkjava:spark-core", version.ref = "spark-core" } -spigot-api = { module = "org.spigotmc:spigot-api", version.ref = "spigot-api" } +spark-common = { module = "me.lucko:spark-common", version.ref = "spark" } +spark-core = { module = "com.sparkjava:spark-core", version.ref = "sparkjava" } tinylog-api = { module = "org.tinylog:tinylog-api", version.ref = "tinylog" } tinylog-impl = { module = "org.tinylog:tinylog-impl", version.ref = "tinylog" } velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocity-api" } -viabackwards-common = { module = "com.viaversion:viabackwards-common", version.ref = "viabackwards" } -vialoader = { module = "com.viaversion:vialoader", version.ref = "vialoader" } +viabackwards-common = { module = "com.viaversion:viabackwards-common", version.ref = "viaversion" } viarewind-common = { module = "com.viaversion:viarewind-common", version.ref = "viarewind" } viaversion = { module = "com.viaversion:viaversion", version.ref = "viaversion" } +packetevents-velocity = { module = "com.github.retrooper:packetevents-velocity", version.ref = "packetevents" } +zstd-jni = { module = "com.github.luben:zstd-jni", version.ref = "zstd-jni" } + +[plugins] +shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c61a118f7..5dd3c0121 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/loader/build.gradle.kts b/loader/build.gradle.kts index b43d82f95..fb36dd922 100644 --- a/loader/build.gradle.kts +++ b/loader/build.gradle.kts @@ -4,7 +4,7 @@ import java.util.* plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" @@ -55,6 +55,9 @@ dependencies { implementation(project(":type.skywarsconfigurator")) implementation(project(":type.ravengardgeneric")) implementation(project(":type.ravengardlobby")) + implementation(project(":type.mainlobby")) + + implementation(project(":type.replayviewer")) implementation(project(":type.generic")) implementation(project(":commons")) @@ -219,7 +222,7 @@ tasks.register("runWithTestFlow") { println("[$serverName] $line") } } - } catch (e: Exception) { + } catch (_: Exception) { // Process was terminated, exit gracefully } }.apply { @@ -244,7 +247,7 @@ tasks.register("runWithTestFlow") { try { process.destroyForcibly() process.waitFor(5, TimeUnit.SECONDS) - } catch (e: Exception) { + } catch (_: Exception) { // Ignore errors during shutdown } } @@ -263,7 +266,7 @@ tasks.register("runWithTestFlow") { serverProcesses.forEach { process -> try { process.destroyForcibly() - } catch (e: Exception) { + } catch (_: Exception) { // Ignore errors } } @@ -271,7 +274,7 @@ tasks.register("runWithTestFlow") { } else { println("Type 'exit' to stop all servers") } - } catch (e: Exception) { + } catch (_: Exception) { // Input was interrupted, likely due to shut down break } @@ -286,14 +289,14 @@ tasks.register("runWithTestFlow") { serverProcesses.forEach { process -> process.waitFor() } - } catch (e: InterruptedException) { + } catch (_: InterruptedException) { println("\nReceived interrupt signal, shutting down...") // The shutdown hook will handle cleanup } finally { // Remove shutdown hook if we're exiting normally try { Runtime.getRuntime().removeShutdownHook(shutdownHook) - } catch (e: IllegalStateException) { + } catch (_: IllegalStateException) { // Shutdown already in progress, ignore } } diff --git a/loader/src/main/java/net/swofty/loader/Hypixel.java b/loader/src/main/java/net/swofty/loader/Hypixel.java index 6b852965c..c62339177 100644 --- a/loader/src/main/java/net/swofty/loader/Hypixel.java +++ b/loader/src/main/java/net/swofty/loader/Hypixel.java @@ -8,7 +8,6 @@ import net.kyori.adventure.translation.GlobalTranslator; import net.minestom.server.Auth; import net.minestom.server.MinecraftServer; -import net.minestom.server.adventure.MinestomAdventure; import net.minestom.server.timer.ExecutionType; import net.minestom.server.timer.Scheduler; import net.minestom.server.timer.TaskSchedule; @@ -64,6 +63,7 @@ public class Hypixel { @SneakyThrows static void main(String[] args) { + System.setProperty("minestom.automatic-component-translation", "true"); if (args.length == 0 || !ServerType.isServerType(args[0])) { Logger.error("Please specify a server type."); Arrays.stream(ServerType.values()).forEach(serverType -> Logger.error(serverType.name())); @@ -85,7 +85,7 @@ static void main(String[] args) { long startTime = System.currentTimeMillis(); Map options = parseOptionalArgs(args); - Integer maxPlayers = options.containsKey("--max-players") ? + int maxPlayers = options.containsKey("--max-players") ? Integer.parseInt(options.get("--max-players")) : 20; // Test flow configuration @@ -207,7 +207,6 @@ static void main(String[] args) { skyblockLoader.afterInitialize(); } - MinestomAdventure.AUTOMATIC_COMPONENT_TRANSLATION = true; HypixelTranslator translator = new HypixelTranslator(); I18n.init(translator); GlobalTranslator.translator().addSource(translator); diff --git a/loader/src/main/resources/META-INF/services/org.tinylog.writers.Writer b/loader/src/main/resources/META-INF/services/org.tinylog.writers.Writer deleted file mode 100644 index 53b1b7df5..000000000 --- a/loader/src/main/resources/META-INF/services/org.tinylog.writers.Writer +++ /dev/null @@ -1 +0,0 @@ -net.swofty.commons.SentryWriter \ No newline at end of file diff --git a/loader/src/main/resources/tinylog.properties b/loader/src/main/resources/tinylog.properties index 5eda4693f..817d3fe3e 100644 --- a/loader/src/main/resources/tinylog.properties +++ b/loader/src/main/resources/tinylog.properties @@ -1,5 +1,5 @@ # Set the global log level -writer = sentry +writer = console writer.level = info writer.format = {date:yyyy-MM-dd HH:mm:ss} [{thread}] {class}.{method}() {level}: {message} diff --git a/packer/build.gradle.kts b/packer/build.gradle.kts index 192644521..ef42a5037 100644 --- a/packer/build.gradle.kts +++ b/packer/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { `java-library` application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" @@ -21,6 +21,7 @@ dependencies { api(libs.creative.api) api(libs.creative.serializer.minecraft) api(libs.creative.server) + api(libs.examination.api) // kind of a legacy API } application { diff --git a/packer/resources.md b/packer/resources.md index bec285ad3..1c3c010b7 100644 --- a/packer/resources.md +++ b/packer/resources.md @@ -58,16 +58,17 @@ int vid = gl_VertexID % 4; - Inline linear_fog: guard with `if (vertexDistance <= FogStart) return color;` then `smoothstep` ### Pack format versions -| MC Version | Resource Pack Format | -|------------|---------------------| -| 1.21.0-1.21.1 | 34 | -| 1.21.2 | 42 | -| 1.21.4 | 46 | -| 1.21.5 | 55 | -| 1.21.6 | 63 | -| 1.21.7-1.21.8 | 64 | -| 1.21.9-1.21.10 | 69 | -| 1.21.11 | 75 | + +| MC Version | Resource Pack Format | +|----------------|----------------------| +| 1.21.0-1.21.1 | 34 | +| 1.21.2 | 42 | +| 1.21.4 | 46 | +| 1.21.5 | 55 | +| 1.21.6 | 63 | +| 1.21.7-1.21.8 | 64 | +| 1.21.9-1.21.10 | 69 | +| 1.21.11 | 75 | ### pack.mcmeta schema change (important) - Vanilla changed `pack.mcmeta` for newer versions: `min_format`/`max_format` are used instead of `pack_format`. diff --git a/packer/src/main/java/net/swofty/packer/HypixelPackBuilder.java b/packer/src/main/java/net/swofty/packer/HypixelPackBuilder.java index 327d3a33a..7de48ca23 100644 --- a/packer/src/main/java/net/swofty/packer/HypixelPackBuilder.java +++ b/packer/src/main/java/net/swofty/packer/HypixelPackBuilder.java @@ -1,46 +1,32 @@ package net.swofty.packer; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.google.gson.JsonElement; -import com.google.gson.JsonPrimitive; import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import org.intellij.lang.annotations.Subst; import team.unnamed.creative.BuiltResourcePack; import team.unnamed.creative.ResourcePack; import team.unnamed.creative.base.Writable; import team.unnamed.creative.font.Font; import team.unnamed.creative.font.FontProvider; import team.unnamed.creative.lang.Language; +import team.unnamed.creative.metadata.pack.FormatVersion; +import team.unnamed.creative.metadata.pack.PackFormat; +import team.unnamed.creative.metadata.pack.PackMeta; import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackReader; import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackWriter; import team.unnamed.creative.texture.Texture; import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HexFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import java.util.zip.ZipOutputStream; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; public class HypixelPackBuilder { - private static final int PACK_FORMAT = 75; - private static final int MIN_FORMAT = PACK_FORMAT; - private static final int MAX_FORMAT = PACK_FORMAT; - private static final int MODERN_FORMAT_THRESHOLD = 64; - private static final long ZIP_ENTRY_TIMESTAMP_MILLIS = 0L; + private static final FormatVersion FORMAT_VERSION = FormatVersion.of(FormatVersion.FORMAT_1_21_11); private final PackDefinition definition; @@ -56,27 +42,28 @@ public BuiltResourcePack build() { ResourcePack pack = MinecraftResourcePackReader.minecraft() .readFromDirectory(packDirectory); - pack.packMeta(PACK_FORMAT, "Hypixel"); + pack.packMeta(PackMeta.of(PackFormat.format(FORMAT_VERSION, FORMAT_VERSION), Component.text("Hypixel"))); addCustomTextures(pack); addCustomFontProviders(pack); applyLangOverrides(pack); - BuiltResourcePack built = MinecraftResourcePackWriter.minecraft().build(pack); - return ensureModernPackMeta(built); + return MinecraftResourcePackWriter.minecraft().build(pack); } private void addCustomTextures(ResourcePack pack) { File texturesDirFile = new File(definition.getTexturesDirectory()); if (!texturesDirFile.exists() || !texturesDirFile.isDirectory()) return; - File[] files = texturesDirFile.listFiles((dir, name) -> name.endsWith(".png")); + File[] files = texturesDirFile.listFiles((_, name) -> name.endsWith(".png")); if (files == null) return; - java.util.Arrays.sort(files, Comparator.comparing(File::getName)); + Arrays.sort(files, Comparator.comparing(File::getName)); for (File textureFile : files) { + if (!textureFile.exists() || !textureFile.isFile()) continue; + @Subst("fallback") String name = textureFile.getName(); pack.texture(Texture.texture( - Key.key("hypixel", textureFile.getName()), + Key.key("hypixel", name), Writable.file(textureFile) )); } @@ -116,175 +103,4 @@ private void applyLangOverrides(ResourcePack pack) { pack.language(Language.language(enUsKey, new LinkedHashMap<>(translations))); } - private BuiltResourcePack ensureModernPackMeta(BuiltResourcePack built) { - if (PACK_FORMAT <= MODERN_FORMAT_THRESHOLD) { - return built; - } - - byte[] rewritten = rewritePackMcmeta(built.bytes()); - return BuiltResourcePack.of(rewritten, sha1Hex(rewritten)); - } - - private byte[] rewritePackMcmeta(byte[] zipBytes) { - try ( - ByteArrayInputStream inputBuffer = new ByteArrayInputStream(zipBytes); - ZipInputStream zipInput = new ZipInputStream(inputBuffer); - ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream(); - ZipOutputStream zipOutput = new ZipOutputStream(outputBuffer) - ) { - ZipEntry entry; - boolean sawPackMeta = false; - List entries = new ArrayList<>(); - while ((entry = zipInput.getNextEntry()) != null) { - byte[] content = readAllBytes(zipInput); - String name = entry.getName(); - - if ("pack.mcmeta".equals(name)) { - sawPackMeta = true; - entries.add(new ZipContentEntry(name, rewritePackMetaJson(content))); - } else { - entries.add(new ZipContentEntry(name, content)); - } - zipInput.closeEntry(); - } - - if (!sawPackMeta) { - entries.add(new ZipContentEntry("pack.mcmeta", rewritePackMetaJson(new byte[0]))); - } - - entries.sort(Comparator.comparing(ZipContentEntry::name)); - - for (ZipContentEntry contentEntry : entries) { - ZipEntry outEntry = new ZipEntry(contentEntry.name()); - outEntry.setTime(ZIP_ENTRY_TIMESTAMP_MILLIS); - zipOutput.putNextEntry(outEntry); - zipOutput.write(contentEntry.content()); - zipOutput.closeEntry(); - } - - zipOutput.finish(); - return outputBuffer.toByteArray(); - } catch (IOException exception) { - throw new UncheckedIOException("Failed to rewrite pack.mcmeta in built resource pack", exception); - } - } - - private byte[] rewritePackMetaJson(byte[] existingContent) { - JsonObject root = parseRootObject(existingContent); - JsonObject packMeta = root.has("pack") && root.get("pack").isJsonObject() - ? root.getAsJsonObject("pack") - : new JsonObject(); - - packMeta.remove("supported_formats"); - packMeta.remove("pack_format"); - packMeta.addProperty("min_format", MIN_FORMAT); - packMeta.addProperty("max_format", MAX_FORMAT); - if (!packMeta.has("description")) { - packMeta.addProperty("description", "Hypixel"); - } - - root.add("pack", packMeta); - return toCanonicalJson(root).getBytes(StandardCharsets.UTF_8); - } - - private JsonObject parseRootObject(byte[] content) { - if (content.length == 0) { - return new JsonObject(); - } - try { - return JsonParser.parseString(new String(content, StandardCharsets.UTF_8)).getAsJsonObject(); - } catch (Exception ignored) { - return new JsonObject(); - } - } - - private byte[] readAllBytes(InputStream stream) throws IOException { - ByteArrayOutputStream output = new ByteArrayOutputStream(); - byte[] buffer = new byte[8192]; - int bytesRead; - while ((bytesRead = stream.read(buffer)) != -1) { - output.write(buffer, 0, bytesRead); - } - return output.toByteArray(); - } - - private String sha1Hex(byte[] data) { - try { - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - return HexFormat.of().formatHex(digest.digest(data)); - } catch (NoSuchAlgorithmException exception) { - throw new IllegalStateException("SHA-1 algorithm is unavailable", exception); - } - } - - private String toCanonicalJson(JsonElement element) { - if (element == null || element.isJsonNull()) { - return "null"; - } - - if (element.isJsonObject()) { - JsonObject object = element.getAsJsonObject(); - List keys = new ArrayList<>(object.keySet()); - keys.sort(String::compareTo); - - StringBuilder builder = new StringBuilder(); - builder.append('{'); - for (int i = 0; i < keys.size(); i++) { - String key = keys.get(i); - if (i > 0) { - builder.append(','); - } - builder.append('"').append(escapeJson(key)).append('"').append(':'); - builder.append(toCanonicalJson(object.get(key))); - } - builder.append('}'); - return builder.toString(); - } - - if (element.isJsonArray()) { - StringBuilder builder = new StringBuilder(); - builder.append('['); - int index = 0; - for (JsonElement entry : element.getAsJsonArray()) { - if (index++ > 0) { - builder.append(','); - } - builder.append(toCanonicalJson(entry)); - } - builder.append(']'); - return builder.toString(); - } - - JsonPrimitive primitive = element.getAsJsonPrimitive(); - if (primitive.isString()) { - return "\"" + escapeJson(primitive.getAsString()) + "\""; - } - return primitive.toString(); - } - - private String escapeJson(String input) { - StringBuilder builder = new StringBuilder(input.length() + 16); - for (int i = 0; i < input.length(); i++) { - char c = input.charAt(i); - switch (c) { - case '"' -> builder.append("\\\""); - case '\\' -> builder.append("\\\\"); - case '\b' -> builder.append("\\b"); - case '\f' -> builder.append("\\f"); - case '\n' -> builder.append("\\n"); - case '\r' -> builder.append("\\r"); - case '\t' -> builder.append("\\t"); - default -> { - if (c <= 0x1F) { - builder.append(String.format("\\u%04x", (int) c)); - } else { - builder.append(c); - } - } - } - } - return builder.toString(); - } - - private record ZipContentEntry(String name, byte[] content) {} } diff --git a/proxy.api/src/main/java/net/swofty/proxyapi/ProxyPlayer.java b/proxy.api/src/main/java/net/swofty/proxyapi/ProxyPlayer.java index ad03ebe62..e3565b62a 100644 --- a/proxy.api/src/main/java/net/swofty/proxyapi/ProxyPlayer.java +++ b/proxy.api/src/main/java/net/swofty/proxyapi/ProxyPlayer.java @@ -109,6 +109,18 @@ public void transferToLimbo() { response -> {}); } + public void transferToLimboFromAfk(ServerType originType) { + Map data = new java.util.HashMap<>(); + data.put("reason", "AFK"); + if (originType != null) { + data.put("origin-type", originType.name()); + } + + ServerOutboundMessage.sendToProxy(PLAYER_HANDLER, + new PlayerHandlerProtocol.Request(uuid.toString(), PlayerHandlerProtocol.Action.LIMBO, data), + response -> {}); + } + public CompletableFuture transferToWithIndication(ServerType serverType) { CompletableFuture future = new CompletableFuture<>(); ServerOutboundMessage.sendToProxy(PLAYER_HANDLER, diff --git a/pvp/src/main/java/net/swofty/pvp/MinestomPvP.java b/pvp/src/main/java/net/swofty/pvp/MinestomPvP.java index 64511729c..f59e07bba 100644 --- a/pvp/src/main/java/net/swofty/pvp/MinestomPvP.java +++ b/pvp/src/main/java/net/swofty/pvp/MinestomPvP.java @@ -1,12 +1,5 @@ package net.swofty.pvp; -import net.swofty.pvp.enchantment.CombatEnchantments; -import net.swofty.pvp.feature.CombatFeatures; -import net.swofty.pvp.feature.config.CombatFeatureRegistry; -import net.swofty.pvp.player.CombatPlayer; -import net.swofty.pvp.potion.effect.CombatPotionEffects; -import net.swofty.pvp.potion.item.CombatPotionTypes; -import net.swofty.pvp.utils.AccurateLatencyListener; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.entity.attribute.Attribute; @@ -15,6 +8,13 @@ import net.minestom.server.event.player.PlayerPacketOutEvent; import net.minestom.server.event.trait.EntityInstanceEvent; import net.minestom.server.network.packet.client.common.ClientKeepAlivePacket; +import net.swofty.pvp.enchantment.CombatEnchantments; +import net.swofty.pvp.feature.CombatFeatures; +import net.swofty.pvp.feature.config.CombatFeatureRegistry; +import net.swofty.pvp.player.CombatPlayer; +import net.swofty.pvp.potion.effect.CombatPotionEffects; +import net.swofty.pvp.potion.item.CombatPotionTypes; +import net.swofty.pvp.utils.AccurateLatencyListener; /** * The main class of MinestomPvP, which contains the {@link MinestomPvP#init()} method. @@ -57,36 +57,29 @@ public static void setLegacyAttack(Player player, boolean legacyAttack) { } /** - * Initializes the PvP library. This has a few side effects, for more details see {@link #init(boolean, boolean)}. + * Initializes the PvP library. This has a few side effects, for more details see {@link #init(boolean)}. */ public static void init() { - init(true, true); + init(true); } /** * Initializes the PvP library. * This method will always initialize the registries and register some global event handlers. + * You need to implement a player provider yourself if you want to use the {@link CombatPlayer} class, look for an example in BedWarsPlayer * Depending on the value of the parameters, it might also register:
- * - a custom player implementation
* - a custom packet listener for {@link ClientKeepAlivePacket}
* - * @param player When set to true, the custom player implementation will be registered * @param keepAlive When set to true, the custom packet listener will be registered */ - public static void init(boolean player, boolean keepAlive) { + public static void init(boolean keepAlive) { CombatEnchantments.registerAll(); CombatPotionEffects.registerAll(); CombatPotionTypes.registerAll(); CombatFeatureRegistry.init(); - CombatPlayer.init(MinecraftServer.getGlobalEventHandler()); - // You need to implement this yourself in a gamemode, look for an example in BedWarsPlayer - ArikSquad - /*if (player) { - MinecraftServer.getConnectionManager().setPlayerProvider(CombatPlayerImpl::new); - }*/ - if (keepAlive) { MinecraftServer.getPacketListenerManager().setPlayListener(ClientKeepAlivePacket.class, AccurateLatencyListener::listener); MinecraftServer.getGlobalEventHandler().addListener(PlayerPacketOutEvent.class, AccurateLatencyListener::onSend); diff --git a/pvp/src/main/java/net/swofty/pvp/damage/combat/CombatManager.java b/pvp/src/main/java/net/swofty/pvp/damage/combat/CombatManager.java index 1cca07524..a3d895279 100644 --- a/pvp/src/main/java/net/swofty/pvp/damage/combat/CombatManager.java +++ b/pvp/src/main/java/net/swofty/pvp/damage/combat/CombatManager.java @@ -1,5 +1,6 @@ package net.swofty.pvp.damage.combat; +import lombok.Getter; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; @@ -24,6 +25,7 @@ import java.util.ArrayList; import java.util.List; +@Getter public class CombatManager { private static final Component BAD_RESPAWN_POINT_MESSAGE = Component.text("[") .append(Component.translatable("death.attack.badRespawnPoint.link") @@ -31,14 +33,15 @@ public class CombatManager { .hoverEvent(HoverEvent.showText(Component.text("MCPE-28723")))) .append(Component.text("]")); + private final List entries = new ArrayList<>(); - private final Player player; + private final Player player; private int lastDamagedBy = -1; - private long lastDamageTime; - private long combatStartTime; - private long combatEndTime; - private boolean inCombat; - private boolean takingDamage; + private long lastDamageTime; + private long combatStartTime; + private long combatEndTime; + private boolean inCombat; + private boolean takingDamage; public CombatManager(Player player) { this.player = player; @@ -298,31 +301,4 @@ private void onLeaveCombat() { player.getPlayerConnection().sendPacket(new EndCombatEventPacket(duration)); } - public List getEntries() { - return entries; - } - - public Player getPlayer() { - return player; - } - - public long getLastDamageTime() { - return lastDamageTime; - } - - public long getCombatStartTime() { - return combatStartTime; - } - - public long getCombatEndTime() { - return combatEndTime; - } - - public boolean isInCombat() { - return inCombat; - } - - public boolean isTakingDamage() { - return takingDamage; - } } \ No newline at end of file diff --git a/pvp/src/main/java/net/swofty/pvp/enchantment/enchantments/ThornsEnchantment.java b/pvp/src/main/java/net/swofty/pvp/enchantment/enchantments/ThornsEnchantment.java index ab97293fe..6d145c3f7 100644 --- a/pvp/src/main/java/net/swofty/pvp/enchantment/enchantments/ThornsEnchantment.java +++ b/pvp/src/main/java/net/swofty/pvp/enchantment/enchantments/ThornsEnchantment.java @@ -1,15 +1,15 @@ package net.swofty.pvp.enchantment.enchantments; -import net.swofty.pvp.enchantment.CombatEnchantment; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.enchantment.EnchantmentFeature; import net.minestom.server.entity.EquipmentSlot; import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.damage.Damage; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.item.ItemStack; import net.minestom.server.item.enchant.Enchantment; +import net.swofty.pvp.enchantment.CombatEnchantment; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.enchantment.EnchantmentFeature; import java.util.Map; import java.util.Set; @@ -19,29 +19,29 @@ public class ThornsEnchantment extends CombatEnchantment { public ThornsEnchantment(EquipmentSlot... slotTypes) { super(Enchantment.THORNS, Set.of(FeatureType.ITEM_DAMAGE), slotTypes); } - + @Override public void onUserDamaged(LivingEntity user, LivingEntity attacker, int level, EnchantmentFeature feature, FeatureConfiguration configuration) { ThreadLocalRandom random = ThreadLocalRandom.current(); if (!shouldDamageAttacker(level, random)) return; - + Map.Entry entry = feature.pickRandom(user, Enchantment.THORNS); - + if (attacker != null) { attacker.damage(new Damage(DamageType.THORNS, user, user, null, getDamageAmount(level, random))); } - + if (entry != null) { configuration.get(FeatureType.ITEM_DAMAGE).damageEquipment(user, entry.getKey(), 2); } } - + private static boolean shouldDamageAttacker(int level, ThreadLocalRandom random) { if (level <= 0) return false; return random.nextFloat() < 0.15f * level; } - + private static int getDamageAmount(int level, ThreadLocalRandom random) { return level > 10 ? level - 10 : 1 + random.nextInt(4); } diff --git a/pvp/src/main/java/net/swofty/pvp/entity/AreaEffectCloud.java b/pvp/src/main/java/net/swofty/pvp/entity/AreaEffectCloud.java new file mode 100644 index 000000000..19eb84a8c --- /dev/null +++ b/pvp/src/main/java/net/swofty/pvp/entity/AreaEffectCloud.java @@ -0,0 +1,194 @@ +package net.swofty.pvp.entity; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.collision.Aerodynamics; +import net.minestom.server.color.AlphaColor; +import net.minestom.server.color.Color; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.metadata.other.AreaEffectCloudMeta; +import net.minestom.server.instance.EntityTracker; +import net.minestom.server.item.component.PotionContents; +import net.minestom.server.particle.Particle; +import net.swofty.pvp.feature.effect.EffectFeature; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +public class AreaEffectCloud extends Entity { + protected int duration; + protected final int durationOnUse; + protected final float radiusPerTick; + protected final float radiusOnUse; + protected final int reapplicationDelay; + protected final int waitTime; + private final AreaEffectCloudMeta meta; + + protected int age = 0; + private final Map<@NotNull LivingEntity, @NotNull Integer> affectedEntities = new HashMap<>(); + private final UUID ownerUuid; + private final PotionContents potionContents; + + private final EffectFeature effectFeature; + + private static final int DEFAULT_DURATION_ON_USE = 0; + private static final float DEFAULT_RADIUS_ON_USE = 0.0F; + private static final float DEFAULT_RADIUS_PER_TICK = 0.0F; + private static final float MINIMAL_RADIUS = 0.5F; + private static final float DEFAULT_RADIUS = 3.0F; + private static final float MAX_RADIUS = 32.0f; + public static final int INFINITE_DURATION = -1; + public static final int DEFAULT_LINGERING_DURATION = 600; + private static final int DEFAULT_WAIT_TIME = 20; + private static final int DEFAULT_REAPPLICATION_DELAY = 20; + private static final Particle.EntityEffect DEFAULT_PARTICLE = + new Particle.EntityEffect(Particle.ENTITY_EFFECT.key(), Particle.ENTITY_EFFECT.id(), new AlphaColor(-1)); + private final Set entitiesToAffect = new HashSet<>(); + + public AreaEffectCloud(int duration, float radius, Particle particle, float radiusPerTick, float radiusOnUse, int reapplicationDelay, + int durationOnUse, int waitTime, PotionContents potionContents, @Nullable UUID ownerUuid, + EffectFeature effectFeature) { + super(EntityType.AREA_EFFECT_CLOUD); + this.duration = duration; + this.radiusPerTick = radiusPerTick; + this.radiusOnUse = radiusOnUse; + this.reapplicationDelay = reapplicationDelay; + this.durationOnUse = durationOnUse; + this.waitTime = waitTime; + + meta = (AreaEffectCloudMeta) this.getEntityMeta(); + meta.setWaiting(age < waitTime); + meta.setRadius(Math.min(MAX_RADIUS, radius)); + meta.setParticle(particle); + + this.ownerUuid = ownerUuid; + this.effectFeature = effectFeature; + + this.potionContents = potionContents; + if (particle instanceof Particle.EntityEffect entityEffect && entityEffect.color().asARGB() == -1) + updateColor(this.potionContents); + + this.setNoGravity(true); + this.setAerodynamics(new Aerodynamics(0.0, 0.0, 0.0)); + } + + public AreaEffectCloud() { + this( + DEFAULT_LINGERING_DURATION, + DEFAULT_RADIUS, + DEFAULT_PARTICLE, + DEFAULT_RADIUS_PER_TICK, + DEFAULT_RADIUS_ON_USE, + DEFAULT_REAPPLICATION_DELAY, + DEFAULT_DURATION_ON_USE, + DEFAULT_WAIT_TIME, + PotionContents.EMPTY, + null, + EffectFeature.NO_OP + ); + } + + @Override + public void tick(long time) { + super.tick(time); + if (isRemoved()) return; + + age++; + meta.setWaiting(age < waitTime); + + if (age >= waitTime + duration && duration != INFINITE_DURATION) { + discard(); + return; + } + if (meta.isWaiting()) return; + + changeRadiusPerTick(); + + if (age % 5 == 0) { + affectedEntities.entrySet().removeIf(entry -> age >= entry.getValue()); + + if (potionContents == PotionContents.EMPTY) { + affectedEntities.clear(); + return; + } + + entitiesToAffect.clear(); + float radiusSquared = meta.getRadius() * meta.getRadius(); + instance.getEntityTracker().nearbyEntities(position, meta.getRadius(), + EntityTracker.Target.ENTITIES, entity -> { + if (get2DDistanceSquared(entity) <= radiusSquared && entity instanceof LivingEntity livingEntity) + entitiesToAffect.add(livingEntity); + }); + + Player attacker = MinecraftServer.getConnectionManager().getOnlinePlayerByUuid(ownerUuid); + entitiesToAffect.forEach(entity -> { + if (affectedEntities.containsKey(entity)) return; + + effectFeature.addLingeringPotionEffects(entity, potionContents, this, attacker); + changeRadiusOnUse(); + changeDurationOnUse(); + affectedEntities.put(entity, age + reapplicationDelay); + }); + + } + } + + private void discard() { + scheduler().scheduleEndOfTick(this::remove); + } + + private void changeRadiusPerTick() { + float calculatedRadius = meta.getRadius(); + if (radiusPerTick != DEFAULT_RADIUS_PER_TICK) { + calculatedRadius += radiusPerTick; + if (calculatedRadius < MINIMAL_RADIUS) { + discard(); + return; + } + meta.setRadius(Math.min(MAX_RADIUS, calculatedRadius)); + } + } + + private void changeRadiusOnUse() { + float calculatedRadius = meta.getRadius() + radiusOnUse; + if (calculatedRadius < MINIMAL_RADIUS) { + discard(); + return; + } + meta.setRadius(Math.min(MAX_RADIUS, calculatedRadius)); + } + + private void changeDurationOnUse() { + duration = duration + durationOnUse; + if (duration <= 0) discard(); + } + + private double get2DDistanceSquared(Entity entity) { + double dx = position.x() - entity.getPosition().x(); + double dz = position.z() - entity.getPosition().z(); + return (dx * dx) + (dz * dz); + } + + public void updateColor(PotionContents potionContents) { + if (meta.getParticle() instanceof Particle.EntityEffect particle) { + Color color = new Color(effectFeature.getPotionColor(potionContents)); + meta.setParticle( + new Particle.EntityEffect( + particle.key(), particle.id(), new AlphaColor(255, color))); + } + } + + public void updateColor(AlphaColor alphaColor) { + if (meta.getParticle() instanceof Particle.EntityEffect particle) { + meta.setParticle(new Particle.EntityEffect( + particle.key(), particle.id(), alphaColor)); + } + } +} \ No newline at end of file diff --git a/pvp/src/main/java/net/swofty/pvp/entity/projectile/AbstractArrow.java b/pvp/src/main/java/net/swofty/pvp/entity/projectile/AbstractArrow.java index 7fc8bb18f..a172d5952 100644 --- a/pvp/src/main/java/net/swofty/pvp/entity/projectile/AbstractArrow.java +++ b/pvp/src/main/java/net/swofty/pvp/entity/projectile/AbstractArrow.java @@ -1,13 +1,14 @@ package net.swofty.pvp.entity.projectile; -import net.swofty.pvp.events.PickupEntityEvent; -import net.swofty.pvp.feature.enchantment.EnchantmentFeature; -import net.swofty.pvp.utils.EntityUtil; import net.kyori.adventure.sound.Sound; import net.minestom.server.ServerFlag; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; -import net.minestom.server.entity.*; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; import net.minestom.server.entity.damage.Damage; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.metadata.projectile.AbstractArrowMeta; @@ -18,6 +19,10 @@ import net.minestom.server.network.packet.server.play.CollectItemPacket; import net.minestom.server.sound.SoundEvent; import net.minestom.server.utils.MathUtils; +import net.swofty.pvp.events.PickupEntityEvent; +import net.swofty.pvp.feature.enchantment.EnchantmentFeature; +import net.swofty.pvp.feature.provider.SoundProvider; +import net.swofty.pvp.utils.EntityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,7 +33,7 @@ public abstract class AbstractArrow extends CustomEntityProjectile { private static final double ARROW_BASE_DAMAGE = 2.0; - + protected int pickupDelay; protected int stuckTime; protected PickupMode pickupMode = PickupMode.DISALLOWED; @@ -36,22 +41,23 @@ public abstract class AbstractArrow extends CustomEntityProjectile { private double baseDamage = ARROW_BASE_DAMAGE; private int knockback; private SoundEvent soundEvent = getDefaultSound(); - + private SoundProvider soundProvider; + private final Set piercingIgnore = new HashSet<>(); private int fireTicksLeft = 0; - + protected final EnchantmentFeature enchantmentFeature; - + public AbstractArrow(@Nullable Entity shooter, @NotNull EntityType entityType, EnchantmentFeature enchantmentFeature) { super(shooter, entityType); this.enchantmentFeature = enchantmentFeature; - + if (shooter instanceof Player) { pickupMode = ((Player) shooter).getGameMode() == GameMode.CREATIVE ? PickupMode.CREATIVE_ONLY : PickupMode.ALLOWED; } } - + @Override public void update(long time) { if (onGround) { @@ -59,11 +65,11 @@ public void update(long time) { } else { stuckTime = 0; } - + if (pickupDelay > 0) { pickupDelay--; } - + if (fireTicksLeft > 0) { if (entityMeta.isOnFire()) { fireTicksLeft--; @@ -74,7 +80,7 @@ public void update(long time) { fireTicksLeft = 0; } } - + // Pickup if (canBePickedUp(null)) { instance.getEntityTracker().nearbyEntities(position, 5, EntityTracker.Target.PLAYERS, @@ -104,22 +110,22 @@ public void update(long time) { } //TODO water (also for other projectiles?) - + tickRemoval(); } - + public void setFireTicksLeft(int fireTicksLeft) { this.fireTicksLeft = fireTicksLeft; if (fireTicksLeft > 0) entityMeta.setOnFire(true); } - + protected void tickRemoval() { ticks++; if (ticks >= 1200) { remove(); } } - + @Override public void onUnstuck() { ((AbstractArrowMeta) getEntityMeta()).setInGround(false); @@ -131,104 +137,104 @@ public void onUnstuck() { )); ticks = 0; } - + @Override protected boolean canHit(Entity entity) { return super.canHit(entity) && !piercingIgnore.contains(entity.getEntityId()); } - + @Override public boolean onHit(@NotNull Entity entity) { if (piercingIgnore.contains(entity.getEntityId())) return false; if (!(entity instanceof LivingEntity living)) return false; - + ThreadLocalRandom random = ThreadLocalRandom.current(); - + double movementSpeed = getVelocity().length() / ServerFlag.SERVER_TICKS_PER_SECOND; int damage = (int) Math.ceil(MathUtils.clamp( movementSpeed * baseDamage, 0.0, 2.147483647E9D)); - + if (getPiercingLevel() > 0) { if (piercingIgnore.size() >= getPiercingLevel() + 1) { return true; } - + piercingIgnore.add(entity.getEntityId()); } - + if (isCritical()) { int randomDamage = random.nextInt(damage / 2 + 2); damage = (int) Math.min(randomDamage + damage, 2147483647L); } - + Entity shooter = getShooter(); Damage damageObj = new Damage( DamageType.ARROW, this, Objects.requireNonNullElse(shooter, this), null, damage ); - + + Pos position = getPosition(); if (living.damage(damageObj)) { if (entity.getEntityType() == EntityType.ENDERMAN) return false; - + if (isOnFire()) { living.setFireTicks(5 * ServerFlag.SERVER_TICKS_PER_SECOND); } - + if (getPiercingLevel() <= 0) { living.setArrowCount(living.getArrowCount() + 1); } - + if (knockback > 0) { Vec knockbackVec = getVelocity() .mul(1, 0, 1) .normalize().mul(knockback * 0.6); knockbackVec = knockbackVec.add(0, 0.1, 0) .mul(ServerFlag.SERVER_TICKS_PER_SECOND / 2.0); - + if (knockbackVec.lengthSquared() > 0) { Vec newVel = living.getVelocity().add(knockbackVec); living.setVelocity(newVel); } } - + if (shooter instanceof LivingEntity livingShooter) { enchantmentFeature.onUserDamaged(living, livingShooter); enchantmentFeature.onTargetDamaged(livingShooter, living); } - + onHurt(living); - + if (living != shooter && living instanceof Player && shooter instanceof Player shooterPlayer && !isSilent()) { shooterPlayer.sendPacket(new ChangeGameStatePacket(ChangeGameStatePacket.Reason.ARROW_HIT_PLAYER, 0.0F)); } - + if (!isSilent()) { getViewersAsAudience().playSound(Sound.sound( getSound(), Sound.Source.NEUTRAL, 1.0f, 1.2f / (random.nextFloat() * 0.2f + 0.9f) - ), this); + ), position.x(), position.y(), position.z()); } - + return getPiercingLevel() <= 0; } else { - Pos position = getPosition(); setVelocity(getVelocity().mul(-0.5 * 0.2)); refreshPosition(position.withYaw(position.yaw() + 170.0f + 20.0f * ThreadLocalRandom.current().nextFloat())); - + if (getVelocity().lengthSquared() < 1.0E-7D) { if (pickupMode == PickupMode.ALLOWED) { EntityUtil.spawnItemAtLocation(this, getPickupItem(), 0.1); } - + return true; } } - + return false; } - + @Override public boolean onStuck() { if (!isSilent()) { @@ -236,102 +242,102 @@ public boolean onStuck() { getViewersAsAudience().playSound(Sound.sound( getSound(), Sound.Source.NEUTRAL, 1.0f, 1.2f / (random.nextFloat() * 0.2f + 0.9f) - ), this); + ), position.x(), position.y(), position.z()); } - + pickupDelay = 7; ((AbstractArrowMeta) getEntityMeta()).setInGround(true); setCritical(false); setPiercingLevel((byte) 0); setSound(SoundEvent.ENTITY_ARROW_HIT); piercingIgnore.clear(); - + return false; } - + public boolean canBePickedUp(@Nullable Player player) { if (!(onGround || hasNoGravity()) || pickupDelay > 0) { return false; } - + return switch (pickupMode) { case ALLOWED -> true; case CREATIVE_ONLY -> player == null || player.getGameMode() == GameMode.CREATIVE; default -> false; }; } - + public boolean pickup(Player player) { return player.getGameMode() == GameMode.CREATIVE || player.getInventory().addItemStack(getPickupItem()); } - + protected abstract ItemStack getPickupItem(); - + protected void onHurt(LivingEntity entity) { } - + public SoundEvent getSound() { return soundEvent; } - + public void setSound(SoundEvent soundEvent) { this.soundEvent = soundEvent; } - + protected SoundEvent getDefaultSound() { return SoundEvent.ENTITY_ARROW_HIT; } - + public int getKnockback() { return knockback; } - + public void setKnockback(int knockback) { this.knockback = knockback; } - + public double getBaseDamage() { return baseDamage; } - + public void setBaseDamage(double baseDamage) { this.baseDamage = baseDamage; } - + public boolean isCritical() { return ((AbstractArrowMeta) getEntityMeta()).isCritical(); } - + public void setCritical(boolean critical) { ((AbstractArrowMeta) getEntityMeta()).setCritical(critical); } - + public byte getPiercingLevel() { return ((AbstractArrowMeta) getEntityMeta()).getPiercingLevel(); } - + public void setPiercingLevel(byte piercingLevel) { ((AbstractArrowMeta) getEntityMeta()).setPiercingLevel(piercingLevel); } - + public boolean isNoClip() { return ((AbstractArrowMeta) getEntityMeta()).isNoClip(); } - + public void setNoClip(boolean noClip) { ((AbstractArrowMeta) getEntityMeta()).setNoClip(noClip); super.hasPhysics = !noClip; super.noClip = noClip; } - + public PickupMode getPickupMode() { return pickupMode; } - + public void setPickupMode(PickupMode pickupMode) { this.pickupMode = pickupMode; } - + public enum PickupMode { DISALLOWED, ALLOWED, diff --git a/pvp/src/main/java/net/swofty/pvp/entity/projectile/CustomEntityProjectile.java b/pvp/src/main/java/net/swofty/pvp/entity/projectile/CustomEntityProjectile.java index 4878aa715..d5729c60b 100644 --- a/pvp/src/main/java/net/swofty/pvp/entity/projectile/CustomEntityProjectile.java +++ b/pvp/src/main/java/net/swofty/pvp/entity/projectile/CustomEntityProjectile.java @@ -1,13 +1,19 @@ package net.swofty.pvp.entity.projectile; -import net.swofty.pvp.utils.ProjectileUtil; import net.minestom.server.ServerFlag; -import net.minestom.server.collision.*; -import net.minestom.server.coordinate.BlockVec; +import net.minestom.server.collision.Aerodynamics; +import net.minestom.server.collision.BoundingBox; +import net.minestom.server.collision.CollisionUtils; +import net.minestom.server.collision.EntityCollisionResult; +import net.minestom.server.collision.PhysicsResult; import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; -import net.minestom.server.entity.*; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; import net.minestom.server.entity.metadata.projectile.ProjectileMeta; import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.entity.projectile.ProjectileCollideWithBlockEvent; @@ -17,6 +23,7 @@ import net.minestom.server.instance.block.Block; import net.minestom.server.utils.chunk.ChunkCache; import net.minestom.server.utils.chunk.ChunkUtils; +import net.swofty.pvp.utils.ProjectileUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,11 +38,11 @@ public class CustomEntityProjectile extends Entity { private final Entity shooter; protected boolean noClip; - + protected Vec collisionDirection; - + private PhysicsResult previousPhysicsResult = null; - + /** * Constructs new projectile. * @@ -47,7 +54,7 @@ public CustomEntityProjectile(@Nullable Entity shooter, @NotNull EntityType enti this.shooter = shooter; setup(); } - + private void setup() { collidesWithEntities = false; preventBlockPlacement = false; @@ -57,11 +64,11 @@ private void setup() { } setSynchronizationTicks(getUpdateInterval()); } - + public @Nullable Entity getShooter() { return shooter; } - + /** * Called when this projectile is stuck in blocks. * Probably you want to do nothing with arrows in such case and to remove other types of projectiles. @@ -71,40 +78,48 @@ private void setup() { public boolean onStuck() { return false; } - + /** * Called when this projectile unstucks. * Probably you want to add some random velocity to arrows in such case. */ public void onUnstuck() { - + } - + /** * @return Whether this entity should be removed */ public boolean onHit(Entity entity) { return false; } - + public void shootFrom(Pos from, double power, double spread) { Point to = from.add(shooter.getPosition().direction()); shoot(from, to, power, spread); } - + @Deprecated public void shootTo(Point to, double power, double spread) { final var from = this.shooter.getPosition().add(0D, shooter.getEyeHeight(), 0D); shoot(from, to, power, spread); } - - public void shootFromRotation(float pitch, float yaw, float yBias, double power, double spread) { + + public void shootFromRotation(float pitch, float yaw, float yBias, double power, double spread, double yawOffset) { double dx = -Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)); double dy = -Math.sin(Math.toRadians(pitch + yBias)); double dz = Math.cos(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)); - this.shoot(dx, dy, dz, power, spread); + + var direction = new Vec(dx, dy, dz).normalize(); + + var up = new Vec(0, 1, 0); + var rightVector = direction.cross(up); + var orbitalAxis = direction.cross(rightVector); + direction = direction.rotateAroundAxis(orbitalAxis, Math.toRadians(yawOffset)); + + this.shoot(direction.x(), direction.y(), direction.z(), power, spread); } - + private void shoot(double dx, double dy, double dz, double power, double spread) { //TODO custom shoot event // EntityShootEvent shootEvent = new EntityShootEvent(shooter == null ? this : shooter, this, from, power, spread); @@ -115,7 +130,7 @@ private void shoot(double dx, double dy, double dz, double power, double spread) // } // power = shootEvent.getPower(); // spread = shootEvent.getSpread(); - + double length = Math.sqrt(dx * dx + dy * dy + dz * dz); dx /= length; dy /= length; @@ -125,22 +140,22 @@ private void shoot(double dx, double dy, double dz, double power, double spread) dx += random.nextGaussian() * spread; dy += random.nextGaussian() * spread; dz += random.nextGaussian() * spread; - + final double mul = ServerFlag.SERVER_TICKS_PER_SECOND * power; this.velocity = new Vec(dx * mul, dy * mul, dz * mul); setView( - (float) Math.toDegrees(Math.atan2(dx, dz)), - (float) Math.toDegrees(Math.atan2(dy, Math.sqrt(dx * dx + dz * dz))) + (float) Math.toDegrees(Math.atan2(dx, dz)), + (float) Math.toDegrees(Math.atan2(dy, Math.sqrt(dx * dx + dz * dz))) ); } - + private void shoot(@NotNull Pos from, @NotNull Point to, double power, double spread) { // Mostly copied from Minestom PlayerProjectile float pitch = -from.pitch(); double pitchDiff = pitch - 45; if (pitchDiff == 0) pitchDiff = 0.0001; double pitchAdjust = pitchDiff * 0.002145329238474369D; - + double dx = to.x() - from.x(); double dy = to.y() - from.y() + pitchAdjust; double dz = to.z() - from.z(); @@ -148,20 +163,20 @@ private void shoot(@NotNull Pos from, @NotNull Point to, double power, double sp final double xzLength = Math.sqrt(dx * dx + dz * dz); dy += xzLength * 0.20000000298023224D; } - + shoot(dx, dy, dz, power, spread); } - + @Override public void remove() { super.remove(); } - + @Override public void tick(long time) { super.tick(time); if (isRemoved()) return; - + if (isStuck() && shouldUnstuck()) { EventDispatcher.call(new ProjectileUncollideEvent(this)); collisionDirection = null; @@ -169,41 +184,42 @@ public void tick(long time) { onUnstuck(); } } - + public boolean isStuck() { return collisionDirection != null; } - + private boolean shouldUnstuck() { Point collidedPoint = position.add(collisionDirection.mul(0.003)); // Move slightly inside the collided block - Point collidedBlockVec = new BlockVec(collidedPoint); + Point collidedBlockVec = collidedPoint.asBlockVec(); Block block = instance.getBlock(collidedPoint); - + return !block.registry().collisionShape().intersectBox(collidedPoint.sub(collidedBlockVec).sub(0, 0.6, 0), UNSTUCK_BOX); } - + protected boolean canHit(Entity entity) { return entity instanceof LivingEntity && !(entity instanceof Player player && player.getGameMode() == GameMode.SPECTATOR); } - + @Override protected void synchronizePosition() { // For some reason, sending a synchronization when stuck means the position of the arrow will change slightly // on the client even though the position on the server has not changed at all. Why? No clue. // This check does solve the issue though. if (isStuck()) return; - + super.synchronizePosition(); } - - private float prevYaw, prevPitch; - + + protected float prevYaw; + protected float prevPitch; + @Override protected void movementTick() { // Mostly copied from Minestom this.gravityTickCount = isStuck() ? 0 : gravityTickCount + 1; if (vehicle != null) return; - + if (!isStuck()) { Vec diff = velocity.div(ServerFlag.SERVER_TICKS_PER_SECOND); // Prevent entity infinitely in the void @@ -211,29 +227,29 @@ protected void movementTick() { scheduler().scheduleNextProcess(this::remove); return; } - - ChunkCache blockGetter = new ChunkCache(instance, currentChunk, Block.AIR); + + ChunkCache blockGetter = new ChunkCache(instance, currentChunk, Block.AIR); PhysicsResult physicsResult = ProjectileUtil.simulateMovement(position, diff, POINT_BOX, - instance.getWorldBorder(), blockGetter, hasPhysics, previousPhysicsResult, true); + instance.getWorldBorder(), blockGetter, hasPhysics, previousPhysicsResult, true); this.previousPhysicsResult = physicsResult; - + Pos newPosition = physicsResult.newPosition(); - + if (!noClip) { // We won't check collisions with self for first ticks of projectile's life, because it spawns in the // shooter and will immediately be triggered by him. boolean noCollideShooter = getAliveTicks() < 6; Collection entityResult = CollisionUtils.checkEntityCollisions(instance, boundingBox.expand(0.1, 0.3, 0.1), - position.add(0, -0.3, 0), diff, 3, e -> { - if (noCollideShooter && e == shooter) return false; - return e != this && canHit(e); - }, physicsResult); - + position.add(0, -0.3, 0), diff, 3, e -> { + if (noCollideShooter && e == shooter) return false; + return e != this && canHit(e); + }, physicsResult); + if (!entityResult.isEmpty()) { Vec prevVelocity = velocity; EntityCollisionResult collided = entityResult.stream().findFirst().orElse(null); - - var event = new ProjectileCollideWithEntityEvent(this, Pos.fromPoint(collided.collisionPoint()), collided.entity()); + + var event = new ProjectileCollideWithEntityEvent(this, collided.collisionPoint().asPos(), collided.entity()); EventDispatcher.call(event); if (!event.isCancelled()) { if (onHit(collided.entity())) { @@ -248,82 +264,82 @@ protected void movementTick() { } } } - + Chunk finalChunk = ChunkUtils.retrieve(instance, currentChunk, physicsResult.newPosition()); if (!ChunkUtils.isLoaded(finalChunk)) return; - + if (physicsResult.hasCollision() && !isStuck()) { double signumX = physicsResult.collisionX() ? Math.signum(velocity.x()) : 0; double signumY = physicsResult.collisionY() ? Math.signum(velocity.y()) : 0; double signumZ = physicsResult.collisionZ() ? Math.signum(velocity.z()) : 0; Vec collisionDirection = new Vec(signumX, signumY, signumZ); - + Point collidedPosition = collisionDirection.add(physicsResult.newPosition()).apply(Vec.Operator.FLOOR); Block block = instance.getBlock(collidedPosition); - + var event = new ProjectileCollideWithBlockEvent(this, physicsResult.newPosition().withCoord(collidedPosition), block); EventDispatcher.call(event); if (!event.isCancelled()) { setNoGravity(true); setVelocity(Vec.ZERO); this.collisionDirection = collisionDirection; - + if (onStuck()) { // Don't remove now because rest of Entity#tick might throw errors scheduler().scheduleNextProcess(this::remove); } } } - + Aerodynamics aerodynamics = getAerodynamics(); velocity = velocity.mul( - aerodynamics.horizontalAirResistance(), - aerodynamics.verticalAirResistance(), - aerodynamics.horizontalAirResistance() + aerodynamics.horizontalAirResistance(), + aerodynamics.verticalAirResistance(), + aerodynamics.horizontalAirResistance() ).sub(0, hasNoGravity() ? 0 : getAerodynamics().gravity() * ServerFlag.SERVER_TICKS_PER_SECOND, 0); onGround = physicsResult.isOnGround(); - + float yaw = position.yaw(); float pitch = position.pitch(); - + if (!noClip) { yaw = (float) Math.toDegrees(Math.atan2(diff.x(), diff.z())); pitch = (float) Math.toDegrees( - Math.atan2(diff.y(), Math.sqrt(diff.x() * diff.x() + diff.z() * diff.z()))); - + Math.atan2(diff.y(), Math.sqrt(diff.x() * diff.x() + diff.z() * diff.z()))); + // Vanilla really likes to use variables from the render code // on the server side in a way that does not make sense at all yaw = lerp(prevYaw, yaw); pitch = lerp(prevPitch, pitch); } - + this.prevYaw = yaw; this.prevPitch = pitch; - + refreshPosition(newPosition.withView(yaw, pitch), noClip, isStuck()); } } - - private static float lerp(float first, float second) { + + protected static float lerp(float first, float second) { return first + (second - first) * 0.2f; } - + @Override public void setView(float yaw, float pitch) { this.prevYaw = yaw; this.prevPitch = pitch; - + super.setView(yaw, pitch); } - + @Override public @NotNull CompletableFuture teleport(@NotNull Pos position) { this.prevYaw = position.yaw(); this.prevPitch = position.pitch(); - + return super.teleport(position); } - + protected int getUpdateInterval() { return 20; } diff --git a/pvp/src/main/java/net/swofty/pvp/entity/projectile/FireworkRocketEntity.java b/pvp/src/main/java/net/swofty/pvp/entity/projectile/FireworkRocketEntity.java new file mode 100644 index 000000000..81e32e05b --- /dev/null +++ b/pvp/src/main/java/net/swofty/pvp/entity/projectile/FireworkRocketEntity.java @@ -0,0 +1,361 @@ +package net.swofty.pvp.entity.projectile; + +import net.kyori.adventure.sound.Sound; +import net.minestom.server.ServerFlag; +import net.minestom.server.collision.Aerodynamics; +import net.minestom.server.collision.BoundingBox; +import net.minestom.server.collision.CollisionUtils; +import net.minestom.server.collision.EntityCollisionResult; +import net.minestom.server.collision.PhysicsResult; +import net.minestom.server.component.DataComponents; +import net.minestom.server.coordinate.Point; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.damage.Damage; +import net.minestom.server.entity.damage.DamageType; +import net.minestom.server.entity.metadata.projectile.FireworkRocketMeta; +import net.minestom.server.event.EventDispatcher; +import net.minestom.server.event.entity.projectile.ProjectileCollideWithBlockEvent; +import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent; +import net.minestom.server.instance.Chunk; +import net.minestom.server.instance.Instance; +import net.minestom.server.instance.block.Block; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.component.FireworkExplosion; +import net.minestom.server.item.component.FireworkList; +import net.minestom.server.network.packet.server.play.EntityStatusPacket; +import net.minestom.server.sound.SoundEvent; +import net.minestom.server.utils.PacketSendingUtils; +import net.minestom.server.utils.chunk.ChunkCache; +import net.minestom.server.utils.chunk.ChunkUtils; +import net.swofty.pvp.feature.block.BlockFeature; +import net.swofty.pvp.utils.ProjectileUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public class FireworkRocketEntity extends CustomEntityProjectile { + + private static final @NotNull BoundingBox POINT_BOX = new BoundingBox(0, 0, 0); + private static final double GRACE_PERIOD_METERS = 1.7; + + private int lifeTicks; + private final int lifeTimeTicks; + private final boolean shotAtAngle; + private PhysicsResult previousPhysicsResult; + private Point spawnPoint; + + private final BlockFeature blockFeature; + + public FireworkRocketEntity(Entity shooter, ItemStack itemStack, boolean shotAtAngle, BlockFeature blockFeature) { + super(shooter, EntityType.FIREWORK_ROCKET); + this.setNoGravity(true); + this.lifeTicks = 0; + this.shotAtAngle = shotAtAngle; + this.blockFeature = blockFeature; + + var meta = getFireworkRocketMeta(itemStack, shotAtAngle); + + // Firework duration calculation + ThreadLocalRandom random = ThreadLocalRandom.current(); + FireworkList fireworkComponent = meta.getFireworkInfo().get(DataComponents.FIREWORKS); + int flightDuration = 1; + + flightDuration += fireworkComponent != null ? fireworkComponent.flightDuration() : 0; + this.lifeTimeTicks = 10 * flightDuration + random.nextInt(6) + random.nextInt(7); + + if (!shotAtAngle) { + this.setVelocity(new Vec( + nextTriangular(0.0, 0.002297, random), + 0.05, + nextTriangular(0.0, 0.002297, random) + )); + } + } + + private @NotNull FireworkRocketMeta getFireworkRocketMeta(ItemStack itemStack, boolean shotAtAngle) { + var meta = (FireworkRocketMeta) this.getEntityMeta(); + + /* + The shooter in FireworkRocketMeta makes the firework particles follow the player and renders the rocket + invisible, which is used for elytra rocketing. + The shooter in FireworkRocketMeta does NOT mean the player who shot the firework from the crossbow, + that's the shooter inherited from CustomEntityProjectile + */ + // TODO add firework elytra functionality (need elytra first) + meta.setShooter(null); + meta.setShotAtAngle(shotAtAngle); + meta.setFireworkInfo(itemStack); + return meta; + } + + public double nextTriangular(double mean, double deviation, ThreadLocalRandom random) { + return ((random.nextDouble() - random.nextDouble()) * deviation) + mean; + } + + @Override + public void spawn() { + Pos pos = this.getPosition(); + this.spawnPoint = pos; + getViewersAsAudience().playSound(Sound.sound( + SoundEvent.ENTITY_FIREWORK_ROCKET_LAUNCH, + Sound.Source.AMBIENT, + 3.0f, + 1.0f + ), pos.x(), pos.y(), pos.z()); + } + + @Override + public boolean onHit(Entity entity) { + if (entity instanceof Player && entity.getDistanceSquared(spawnPoint) < GRACE_PERIOD_METERS * GRACE_PERIOD_METERS) + return false; + this.explode(); + return true; + } + + @Override + public boolean onStuck() { + if (this.canSlide()) return false; + this.explode(); + return true; + } + + // Sliding across the surface when the firework rocket has no explosions + @SuppressWarnings("UnstableApiUsage") // Marked unstable because either internal or experimental + @Override + protected void movementTick() { + this.gravityTickCount = isStuck() ? 0 : gravityTickCount + 1; + if (vehicle != null) return; + + if (!shotAtAngle) { + double horizontal = horizontalCollision() ? 1.0 : 1.15; + this.setVelocity(this.getVelocity().mul(horizontal, 1.0, horizontal) + .add(0.0, 0.04 * ServerFlag.SERVER_TICKS_PER_SECOND, 0.0)); + } + + if (!isStuck()) { + Vec diff = velocity.div(ServerFlag.SERVER_TICKS_PER_SECOND); + + if (instance.isInVoid(position)) { + scheduler().scheduleNextProcess(this::remove); + return; + } + + ChunkCache blockGetter = new ChunkCache(instance, currentChunk, Block.AIR); + PhysicsResult physicsResult = ProjectileUtil.simulateMovement(position, diff, POINT_BOX, + instance.getWorldBorder(), blockGetter, hasPhysics, previousPhysicsResult, true); + this.previousPhysicsResult = physicsResult; + + Pos newPosition = physicsResult.newPosition(); + + if (!noClip) { + boolean noCollideShooter = getAliveTicks() < 6; + Collection entityResult = CollisionUtils.checkEntityCollisions(instance, boundingBox.expand(0.1, 0.3, 0.1), + position.add(0, -0.3, 0), diff, 3, e -> { + if (noCollideShooter && e == getShooter()) return false; + return e != this && canHit(e); + }, physicsResult); + + if (!entityResult.isEmpty()) { + Vec prevVelocity = velocity; + EntityCollisionResult collided = entityResult.stream().findFirst().orElse(null); + + var event = new ProjectileCollideWithEntityEvent(this, (collided.collisionPoint()).asPos(), collided.entity()); + EventDispatcher.call(event); + if (!event.isCancelled()) { + if (onHit(collided.entity())) { + scheduler().scheduleNextProcess(this::remove); + return; + } else { + if (velocity != prevVelocity) newPosition = position; + } + } + } + } + + Chunk finalChunk = ChunkUtils.retrieve(instance, currentChunk, physicsResult.newPosition()); + if (!ChunkUtils.isLoaded(finalChunk)) return; + + if (physicsResult.hasCollision()) { + double signumX = physicsResult.collisionX() ? Math.signum(velocity.x()) : 0; + double signumY = physicsResult.collisionY() ? Math.signum(velocity.y()) : 0; + double signumZ = physicsResult.collisionZ() ? Math.signum(velocity.z()) : 0; + Vec blockCollisionDirection = new Vec(signumX, signumY, signumZ); + + Point collidedPosition = blockCollisionDirection.add(physicsResult.newPosition()).apply(Vec.Operator.FLOOR); + Block block = instance.getBlock(collidedPosition); + + var event = new ProjectileCollideWithBlockEvent(this, physicsResult.newPosition().withCoord(collidedPosition), block); + EventDispatcher.call(event); + if (!event.isCancelled()) { + if (canSlide()) { + double newX = physicsResult.collisionX() ? 0 : velocity.x(); + double newY = physicsResult.collisionY() ? 0 : velocity.y(); + double newZ = physicsResult.collisionZ() ? 0 : velocity.z(); + newX *= this.getAerodynamics().horizontalAirResistance(); + newY *= this.getAerodynamics().verticalAirResistance(); + newZ *= this.getAerodynamics().horizontalAirResistance(); + + velocity = new Vec(newX, newY, newZ); + } else { + setNoGravity(true); + setVelocity(Vec.ZERO); + this.collisionDirection = blockCollisionDirection; + if (onStuck()) { + scheduler().scheduleNextProcess(this::remove); + } + } + } + } + + Aerodynamics aerodynamics = getAerodynamics(); + velocity = velocity.mul( + aerodynamics.horizontalAirResistance(), + aerodynamics.verticalAirResistance(), + aerodynamics.horizontalAirResistance() + ).sub(0, hasNoGravity() ? 0 : getAerodynamics().gravity() * ServerFlag.SERVER_TICKS_PER_SECOND, 0); + onGround = physicsResult.isOnGround(); + + float yaw = position.yaw(); + float pitch = position.pitch(); + + if (!noClip) { + yaw = (float) Math.toDegrees(Math.atan2(diff.x(), diff.z())); + pitch = (float) Math.toDegrees( + Math.atan2(diff.y(), Math.sqrt(diff.x() * diff.x() + diff.z() * diff.z()))); + + yaw = lerp(prevYaw, yaw); + pitch = lerp(prevPitch, pitch); + } + + this.prevYaw = yaw; + this.prevPitch = pitch; + + refreshPosition(newPosition.withView(yaw, pitch), noClip, isStuck()); + } + } + + public boolean horizontalCollision() { + if (previousPhysicsResult != null) + return previousPhysicsResult.collisionX() || previousPhysicsResult.collisionZ(); + return false; + } + + @Override + public int getUpdateInterval() { + return 1; + } + + public boolean canSlide() { + FireworkList fireworkComponent = ((FireworkRocketMeta) this.getEntityMeta()).getFireworkInfo().get(DataComponents.FIREWORKS); + + if (fireworkComponent != null) + return fireworkComponent.explosions().isEmpty(); + return true; + } + + @Override + public void update(long time) { + this.lifeTicks += 1; + if (this.lifeTicks >= this.lifeTimeTicks) { + this.explode(); + this.remove(); + return; + } + super.update(time); + } + + public void explode() { + PacketSendingUtils.sendGroupedPacket(getViewers(), new EntityStatusPacket(this.getEntityId(), (byte) 17)); + + FireworkList fireworkComponent = ((FireworkRocketMeta) this.getEntityMeta()).getFireworkInfo().get(DataComponents.FIREWORKS); + List explosions = List.of(); + if (fireworkComponent != null) + explosions = fireworkComponent.explosions(); + + if (explosions.isEmpty()) return; + + FireworkRocketMeta meta = (FireworkRocketMeta) this.getEntityMeta(); + Entity shooter = this.getShooter(); + Damage damage = new Damage( + DamageType.EXPLOSION, + this, + shooter, + shooter == null ? null : shooter.getPosition(), + 5.0F + explosions.size() * 2.0f + ); + + if (!meta.isShotAtAngle() && meta.getShooter() instanceof LivingEntity elytraShooter) { + elytraShooter.damage(damage); + } + + this.getInstance().getNearbyEntities(this.getPosition(), 5) + .stream() + .filter(entity -> entity instanceof LivingEntity && entity != meta.getShooter()) + .map(entity -> (LivingEntity) entity) + .forEach(entity -> { + Vec knockback = this.getKnockBack(entity); + + if (this.getBoundingBox().expand(0.5, 0.5, 0.5) + .intersectEntity(this.getPosition(), entity)) { + + if (!blockFeature.isDamageBlocked(entity, damage)) + entity.takeKnockback(0.4f, knockback.x(), knockback.z()); + entity.damage(damage); + + } else if (this.hasConfigurableLineOfSight(entity, 0.0) + || this.hasConfigurableLineOfSight(entity, entity.getEyeHeight() / 2)) { + + double distance = this.getDistance(entity); + Damage calculatedDamage = new Damage( + damage.getType(), + damage.getSource(), + damage.getAttacker(), + damage.getSourcePosition(), + (float) (damage.getAmount() * Math.sqrt((5.0f - distance) / 5.0f)) + ); + if (!blockFeature.isDamageBlocked(entity, calculatedDamage)) + entity.takeKnockback(0.4f, knockback.x(), knockback.z()); + entity.damage(calculatedDamage); + } + }); + } + + protected Vec getKnockBack(LivingEntity target) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + double x = (this.getPosition().x() - target.getPosition().x()); + double z = this.getPosition().z() - target.getPosition().z(); + + while (x * x + z * z < 1.0E-5F) { // 1.0E-5F == 0.00001 + x = (random.nextDouble(-1.0, 1.0)) * 0.01; + z = (random.nextDouble(-1.0, 1.0)) * 0.01; + } + return new Vec(x, z); + } + + /* + The regular `hasLineOfSight()` method ray-casts to the target's eye level, while the firework for its explosion + damage check in vanilla ray-casts to the target's feet level and mid-body level, and if any of those ray-cast + checks pass, the target is dealt damage + */ + protected boolean hasConfigurableLineOfSight(Entity entity, double addedHeight) { + Instance instance = getInstance(); + if (instance == null) { + return false; + } + + final Pos start = position.withY(position.y() + getEyeHeight()); + final Pos end = entity.getPosition().withY(entity.getPosition().y() + addedHeight); + final Vec direction = end.sub(start).asVec().normalize(); + if (!entity.getBoundingBox().boundingBoxRayIntersectionCheck(start.asVec(), direction, entity.getPosition())) { + return false; + } + return CollisionUtils.isLineOfSightReachingShape(instance, currentChunk, start, end, entity.getBoundingBox(), entity.getPosition()); + } +} \ No newline at end of file diff --git a/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownEnderpearl.java b/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownEnderpearl.java index 4e8c48493..8c1a7d144 100644 --- a/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownEnderpearl.java +++ b/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownEnderpearl.java @@ -1,6 +1,5 @@ package net.swofty.pvp.entity.projectile; -import net.swofty.pvp.feature.fall.FallFeature; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Entity; import net.minestom.server.entity.EntityType; @@ -12,6 +11,8 @@ import net.minestom.server.item.ItemStack; import net.minestom.server.network.packet.server.play.ParticlePacket; import net.minestom.server.particle.Particle; +import net.swofty.pvp.feature.fall.FallFeature; +import net.swofty.pvp.feature.provider.PacketProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,66 +20,74 @@ public class ThrownEnderpearl extends CustomEntityProjectile implements ItemHoldingProjectile { private Pos prevPos = Pos.ZERO; - + private final FallFeature fallFeature; - + private final PacketProvider particleSender; + + public ThrownEnderpearl(@Nullable Entity shooter, FallFeature fallFeature, PacketProvider packetProvider) { + super(shooter, EntityType.ENDER_PEARL); + this.fallFeature = fallFeature; + this.particleSender = packetProvider; + } + public ThrownEnderpearl(@Nullable Entity shooter, FallFeature fallFeature) { super(shooter, EntityType.ENDER_PEARL); this.fallFeature = fallFeature; + this.particleSender = PacketProvider.DEFAULT; } - + private void teleportOwner() { Pos position = prevPos; ThreadLocalRandom random = ThreadLocalRandom.current(); - + for (int i = 0; i < 32; i++) { - sendPacketToViewersAndSelf(new ParticlePacket( + particleSender.sendPacket(this, new ParticlePacket( Particle.PORTAL, false, false, position.x(), position.y() + random.nextDouble() * 2, position.z(), (float) random.nextGaussian(), 0.0F, (float) random.nextGaussian(), 0, 1 )); } - + if (isRemoved()) return; - + Entity shooter = getShooter(); if (shooter != null) { Pos shooterPos = shooter.getPosition(); position = position.withPitch(shooterPos.pitch()).withYaw(shooterPos.yaw()); } - + if (shooter instanceof Player player) { if (player.isOnline() && player.getInstance() == getInstance() && player.getPlayerMeta().getBedInWhichSleepingPosition() == null) { if (player.getVehicle() != null) { player.getVehicle().removePassenger(player); } - + player.teleport(position); fallFeature.resetFallDistance(player); - + player.damage(DamageType.FALL, 5.0F); } } else if (shooter != null) { shooter.teleport(position); } } - + @Override public boolean onHit(Entity entity) { ((LivingEntity) entity).damage(new Damage(DamageType.THROWN, this, getShooter(), null, 0)); - + teleportOwner(); return true; } - + @Override public boolean onStuck() { teleportOwner(); return true; } - + @Override public void tick(long time) { Entity shooter = getShooter(); @@ -89,7 +98,7 @@ public void tick(long time) { super.tick(time); } } - + @Override public void setItem(@NotNull ItemStack item) { ((ThrownEnderPearlMeta) getEntityMeta()).setItem(item); diff --git a/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownPotion.java b/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownPotion.java index 7588a047d..308adac54 100644 --- a/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownPotion.java +++ b/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownPotion.java @@ -3,13 +3,19 @@ import net.minestom.server.collision.BoundingBox; import net.minestom.server.component.DataComponents; import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.*; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; import net.minestom.server.entity.metadata.item.LingeringPotionMeta; import net.minestom.server.entity.metadata.item.SplashPotionMeta; import net.minestom.server.item.ItemStack; import net.minestom.server.item.component.PotionContents; +import net.minestom.server.particle.Particle; import net.minestom.server.potion.Potion; import net.minestom.server.worldevent.WorldEvent; +import net.swofty.pvp.entity.AreaEffectCloud; import net.swofty.pvp.feature.effect.EffectFeature; import net.swofty.pvp.utils.EffectUtil; import org.jetbrains.annotations.NotNull; @@ -50,16 +56,17 @@ public void splash(@Nullable Entity entity) { PotionContents potionContents = item.get(DataComponents.POTION_CONTENTS); List potions = effectFeature.getAllPotions(potionContents); + Pos position = getPosition(); if (!potions.isEmpty()) { if (lingering) { - //TODO lingering + AreaEffectCloud areaEffectCloud = new AreaEffectCloud(600, 3.0f, Particle.ENTITY_EFFECT, -0.005f, -0.5f, + 20, 0, 10, potionContents, null, effectFeature); + areaEffectCloud.setInstance(getInstance(), position); } else { applySplash(potionContents, entity); } } - Pos position = getPosition(); - boolean instantEffect = false; for (Potion potion : potions) { if (potion.effect().registry().isInstantaneous()) { diff --git a/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownTrident.java b/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownTrident.java index c7f214a0b..caacde78c 100644 --- a/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownTrident.java +++ b/pvp/src/main/java/net/swofty/pvp/entity/projectile/ThrownTrident.java @@ -4,7 +4,11 @@ import net.minestom.server.ServerFlag; import net.minestom.server.component.DataComponents; import net.minestom.server.coordinate.Vec; -import net.minestom.server.entity.*; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; import net.minestom.server.entity.damage.Damage; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.entity.metadata.projectile.ThrownTridentMeta; @@ -13,6 +17,7 @@ import net.minestom.server.sound.SoundEvent; import net.swofty.pvp.enchantment.EntityGroup; import net.swofty.pvp.feature.enchantment.EnchantmentFeature; +import net.swofty.pvp.feature.provider.SoundProvider; import net.swofty.pvp.utils.EntityUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,6 +28,7 @@ public class ThrownTrident extends AbstractArrow { private final ItemStack tridentItem; private boolean damageDone; private boolean hasStartedReturning; + private SoundProvider soundProvider; public ThrownTrident(@Nullable Entity shooter, ItemStack tridentItem, EnchantmentFeature enchantmentFeature) { super(shooter, EntityType.TRIDENT, enchantmentFeature); @@ -33,6 +39,13 @@ public ThrownTrident(@Nullable Entity shooter, ItemStack tridentItem, Enchantmen meta.setHasEnchantmentGlint(!Objects.requireNonNull(tridentItem.get(DataComponents.ENCHANTMENTS)) .enchantments().isEmpty()); + + soundProvider = SoundProvider.DEFAULT; + } + + public ThrownTrident(@Nullable Entity shooter, ItemStack tridentItem, EnchantmentFeature enchantmentFeature, SoundProvider soundProvider) { + this(shooter, tridentItem, enchantmentFeature); + this.soundProvider = soundProvider; } @Override @@ -57,10 +70,13 @@ public void update(long time) { .mul(ServerFlag.SERVER_TICKS_PER_SECOND))); if (!hasStartedReturning) { - getViewersAsAudience().playSound(Sound.sound( + soundProvider.playSound( + getViewersAsAudience(), + Sound.sound( SoundEvent.ITEM_TRIDENT_RETURN, Sound.Source.NEUTRAL, 10.0f, 1.0f - ), position.x(), position.y(), position.z()); + ), position.x(), position.y(), position.z() + ); hasStartedReturning = true; } } diff --git a/pvp/src/main/java/net/swofty/pvp/events/FinalAttackEvent.java b/pvp/src/main/java/net/swofty/pvp/events/FinalAttackEvent.java index 34b829c7d..bb48edf27 100644 --- a/pvp/src/main/java/net/swofty/pvp/events/FinalAttackEvent.java +++ b/pvp/src/main/java/net/swofty/pvp/events/FinalAttackEvent.java @@ -1,5 +1,7 @@ package net.swofty.pvp.events; +import lombok.Getter; +import lombok.Setter; import net.minestom.server.entity.Entity; import net.minestom.server.event.trait.CancellableEvent; import net.minestom.server.event.trait.EntityInstanceEvent; @@ -20,12 +22,21 @@ public class FinalAttackEvent implements EntityInstanceEvent, CancellableEvent { private final Entity entity; private final Entity target; - private boolean sprint; - private boolean critical; - private boolean sweeping; - private float baseDamage; - private float enchantsExtraDamage; - private boolean attackSounds; + @Setter + @Getter + private boolean sprint; + @Setter + @Getter + private boolean critical; + @Getter + private boolean sweeping; + @Getter + private float baseDamage; + @Setter + @Getter + private float enchantsExtraDamage; + @Setter + private boolean attackSounds; private boolean playSoundsOnFail; private boolean cancelled; @@ -54,102 +65,8 @@ public FinalAttackEvent(@NotNull Entity entity, @NotNull Entity target, return target; } - /** - * Gets whether the attack was a sprint attack. - * - * @return whether the attack was a sprint attack or not - */ - public boolean isSprint() { - return sprint; - } - - /** - * Sets whether the attack was a sprint attack. - * - * @param sprint whether the attack was a sprint attack or not - */ - public void setSprint(boolean sprint) { - this.sprint = sprint; - } - - /** - * Gets whether the attack was critical. - * - * @return whether the attack was critical or not - */ - public boolean isCritical() { - return critical; - } - - /** - * Sets whether the attack was critical. - * - * @param crit whether the attack was critical or not - */ - public void setCritical(boolean crit) { - this.critical = crit; - } - - /** - * Gets whether the attack was sweeping. - * - * @return whether the attack as sweeping or not - */ - public boolean isSweeping() { - return sweeping; - } - - /** - * Sets whether the attack was sweeping. - * - * @param sweeping whether the attack was sweeping or not - */ - public void setSweeping(boolean sweeping) { - this.sweeping = sweeping; - } - - /** - * Gets the base damage of the attack. - * Tool enchantments are excluded, but attack cooldown strength (for 1.9+) is not. - * - * @return the base damage of the attack - */ - public float getBaseDamage() { - return baseDamage; - } - - /** - * Sets the base damage of the attack. - * Enchantment extra damage will be added to this to get the final damage. - * - * @param baseDamage the base damage of the attack - */ - public void setBaseDamage(float baseDamage) { - this.baseDamage = baseDamage; - } - - /** - * Gets the extra damage from enchantments of the attack - * (e.g. sharpness, but also mob based, e.g. impaling). - * This does not include the base damage. - * - * @return the extra damage from enchantments of the attack - */ - public float getEnchantsExtraDamage() { - return enchantsExtraDamage; - } - - /** - * Sets the extra damage of the attack. - * This will be added to the base damage to get the final damage. - * - * @param enchantsExtraDamage the extra damage of the attack - */ - public void setEnchantsExtraDamage(float enchantsExtraDamage) { - this.enchantsExtraDamage = enchantsExtraDamage; - } - /** + /** * Gets whether the 1.9+ attack sounds should be played. * * @return whether the attack sounds should be played @@ -158,17 +75,7 @@ public boolean hasAttackSounds() { return attackSounds; } - /** - * Sets whether the 1.9+ attack sounds should be played. - * This also works for legacy. - * - * @param attackSounds whether the attack sounds should be played - */ - public void setAttackSounds(boolean attackSounds) { - this.attackSounds = attackSounds; - } - - /** + /** * Gets whether the 1.9+ attack sounds should be played if the damage failed. * This only applies if hasAttackSounds() is true. *

@@ -180,18 +87,6 @@ public boolean playSoundsOnFail() { return playSoundsOnFail; } - /** - * Sets whether the 1.9+ attack sounds should be played if the damage failed. - * This only applies if hasAttackSounds() is true. - *

- * If this is true, the only sounds that may be played are knockback and nodamage. - * - * @param playSoundsOnFail whether the attack sounds should be played if the damage failed - */ - public void setPlaySoundsOnFail(boolean playSoundsOnFail) { - this.playSoundsOnFail = playSoundsOnFail; - } - @Override public boolean isCancelled() { return cancelled; diff --git a/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatureSet.java b/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatureSet.java index a81490c91..d470c4a1b 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatureSet.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatureSet.java @@ -1,15 +1,15 @@ package net.swofty.pvp.feature; -import net.swofty.pvp.feature.config.FeatureConfiguration; import net.minestom.server.event.EventNode; import net.minestom.server.event.trait.EntityInstanceEvent; +import net.swofty.pvp.feature.config.FeatureConfiguration; /** * A container for multiple {@link CombatFeature}s. Use {@link CombatFeatureSet#createNode()} to get an event node. */ public class CombatFeatureSet extends FeatureConfiguration implements RegistrableFeature { private boolean initialized = false; - + @Override public void init(EventNode node) { for (CombatFeature feature : listFeatures()) { @@ -17,7 +17,7 @@ public void init(EventNode node) { node.addChild(registrable.createNode()); } } - + @Override public void initDependencies() { for (CombatFeature feature : listFeatures()) { @@ -25,7 +25,7 @@ public void initDependencies() { } initialized = true; } - + @Override public FeatureConfiguration add(FeatureType type, CombatFeature feature) { if (initialized) throw new UnsupportedOperationException("Cannot add features after initialization"); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatures.java b/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatures.java index bfeebdd50..d12d22231 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatures.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/CombatFeatures.java @@ -25,7 +25,13 @@ import net.swofty.pvp.feature.knockback.FairKnockbackFeature; import net.swofty.pvp.feature.knockback.VanillaKnockbackFeature; import net.swofty.pvp.feature.potion.VanillaPotionFeature; -import net.swofty.pvp.feature.projectile.*; +import net.swofty.pvp.feature.projectile.VanillaBowFeature; +import net.swofty.pvp.feature.projectile.VanillaCrossbowFeature; +import net.swofty.pvp.feature.projectile.VanillaFireworkRocketFeature; +import net.swofty.pvp.feature.projectile.VanillaFishingRodFeature; +import net.swofty.pvp.feature.projectile.VanillaMiscProjectileFeature; +import net.swofty.pvp.feature.projectile.VanillaProjectileItemFeature; +import net.swofty.pvp.feature.projectile.VanillaTridentFeature; import net.swofty.pvp.feature.provider.DifficultyProvider; import net.swofty.pvp.feature.spectate.VanillaSpectateFeature; import net.swofty.pvp.feature.state.VanillaPlayerStateFeature; @@ -164,12 +170,12 @@ public class CombatFeatures { * @see VanillaDeathMessageFeature */ public static final DefinedFeature VANILLA_DEATH_MESSAGE = VanillaDeathMessageFeature.DEFINED; - + /** * @see LegacyVanillaBlockFeature */ public static final DefinedFeature LEGACY_VANILLA_BLOCK = LegacyVanillaBlockFeature.SHIELD; - + /** * @see FairKnockbackFeature */ @@ -178,7 +184,11 @@ public class CombatFeatures { * @see FairKnockbackFeature */ public static final DefinedFeature FAIR_RISING_FALLING_KNOCKBACK = FairKnockbackFeature.RISING_AND_FALLING; - + /** + * @see VanillaFireworkRocketFeature + */ + public static final DefinedFeature VANILLA_FIREWORK_ROCKET = VanillaFireworkRocketFeature.DEFINED; + private static final List> VANILLA = List.of( VANILLA_ARMOR, VANILLA_ATTACK, VANILLA_CRITICAL, VANILLA_SWEEPING, VANILLA_EQUIPMENT, VANILLA_BLOCK, VANILLA_ATTACK_COOLDOWN, VANILLA_ITEM_COOLDOWN, @@ -189,13 +199,13 @@ public class CombatFeatures { VANILLA_PROJECTILE_ITEM, VANILLA_TRIDENT, VANILLA_SPECTATE, VANILLA_PLAYER_STATE, VANILLA_TOTEM, VANILLA_DEATH_MESSAGE ); - + private static final CombatFeatureSet MODERN_VANILLA = getVanilla(CombatVersion.MODERN, DifficultyProvider.DEFAULT).build(); - + private static final CombatFeatureSet LEGACY_VANILLA = getVanilla(CombatVersion.LEGACY, DifficultyProvider.DEFAULT) .add(LEGACY_VANILLA_BLOCK) .build(); - + /** * Returns a feature set for the full modern vanilla experience. Use {@link CombatFeatureSet#createNode()} to get an event node. * @@ -204,7 +214,7 @@ public class CombatFeatures { public static CombatFeatureSet modernVanilla() { return MODERN_VANILLA; } - + /** * Returns a feature set for the full legacy (pre-1.9) vanilla experience. Use {@link CombatFeatureSet#createNode()} to get an event node. * @@ -213,7 +223,7 @@ public static CombatFeatureSet modernVanilla() { public static CombatFeatureSet legacyVanilla() { return LEGACY_VANILLA; } - + /** * Returns a feature set with all features for the given combat version and difficulty provider. * @@ -226,7 +236,7 @@ public static CombatConfiguration getVanilla(CombatVersion version, DifficultyPr .version(version).difficulty(difficultyProvider) .addAll(VANILLA); } - + /** * Utility method to get an empty {@link CombatConfiguration} to which features can be added. * @@ -235,7 +245,7 @@ public static CombatConfiguration getVanilla(CombatVersion version, DifficultyPr public static CombatConfiguration empty() { return new CombatConfiguration(); } - + /** * Utility method to construct a single feature without dependencies in a clean way. * diff --git a/pvp/src/main/java/net/swofty/pvp/feature/FeatureType.java b/pvp/src/main/java/net/swofty/pvp/feature/FeatureType.java index 7082fa025..751e2e129 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/FeatureType.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/FeatureType.java @@ -21,8 +21,16 @@ import net.swofty.pvp.feature.item.ItemDamageFeature; import net.swofty.pvp.feature.knockback.KnockbackFeature; import net.swofty.pvp.feature.potion.PotionFeature; -import net.swofty.pvp.feature.projectile.*; +import net.swofty.pvp.feature.projectile.BowFeature; +import net.swofty.pvp.feature.projectile.CrossbowFeature; +import net.swofty.pvp.feature.projectile.FireworkRocketFeature; +import net.swofty.pvp.feature.projectile.FishingRodFeature; +import net.swofty.pvp.feature.projectile.MiscProjectileFeature; +import net.swofty.pvp.feature.projectile.ProjectileItemFeature; +import net.swofty.pvp.feature.projectile.TridentFeature; import net.swofty.pvp.feature.provider.DifficultyProvider; +import net.swofty.pvp.feature.provider.PacketProvider; +import net.swofty.pvp.feature.provider.SoundProvider; import net.swofty.pvp.feature.spectate.SpectateFeature; import net.swofty.pvp.feature.state.PlayerStateFeature; import net.swofty.pvp.feature.totem.TotemFeature; @@ -66,11 +74,14 @@ public record FeatureType(String name, F defaultFeature public static final FeatureType PROJECTILE_ITEM = of("PROJECTILE_ITEM", ProjectileItemFeature.NO_OP); public static final FeatureType TRIDENT = of("TRIDENT", TridentFeature.NO_OP); public static final FeatureType DIFFICULTY = of("DIFFICULTY", DifficultyProvider.DEFAULT); + public static final FeatureType PACKET = of("PACKET", PacketProvider.DEFAULT); + public static final FeatureType SOUND = of("SOUND", SoundProvider.DEFAULT); public static final FeatureType SPECTATE = of("SPECTATE", SpectateFeature.NO_OP); public static final FeatureType PLAYER_STATE = of("PLAYER_STATE", PlayerStateFeature.NO_OP); public static final FeatureType TOTEM = of("TOTEM", TotemFeature.NO_OP); public static final FeatureType TRACKING = of("TRACKING", TrackingFeature.NO_OP); - + public static final FeatureType FIREWORK = of("FIREWORK", FireworkRocketFeature.NO_OP); + public static FeatureType of(String name, F noopFeature) { return new FeatureType<>(name, noopFeature); } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/armor/VanillaArmorFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/armor/VanillaArmorFeature.java index 3e535d8c0..0f2d8ee8a 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/armor/VanillaArmorFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/armor/VanillaArmorFeature.java @@ -1,11 +1,5 @@ package net.swofty.pvp.feature.armor; -import net.swofty.pvp.damage.DamageTypeInfo; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.enchantment.EnchantmentFeature; -import net.swofty.pvp.utils.CombatVersion; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.attribute.Attribute; @@ -13,6 +7,12 @@ import net.minestom.server.potion.PotionEffect; import net.minestom.server.potion.TimedPotion; import net.minestom.server.utils.MathUtils; +import net.swofty.pvp.damage.DamageTypeInfo; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.enchantment.EnchantmentFeature; +import net.swofty.pvp.utils.CombatVersion; /** * Vanilla implementation of {@link ArmorFeature} @@ -22,31 +22,31 @@ public class VanillaArmorFeature implements ArmorFeature { FeatureType.ARMOR, VanillaArmorFeature::new, FeatureType.ENCHANTMENT, FeatureType.VERSION ); - + private final FeatureConfiguration configuration; private EnchantmentFeature enchantmentFeature; private CombatVersion version; - + public VanillaArmorFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.enchantmentFeature = configuration.get(FeatureType.ENCHANTMENT); this.version = configuration.get(FeatureType.VERSION); } - + @Override public float getDamageWithProtection(LivingEntity entity, DamageType type, float amount) { DamageTypeInfo info = DamageTypeInfo.of(MinecraftServer.getDamageTypeRegistry().getKey(type)); amount = getDamageWithArmor(entity, info, amount); return getDamageWithEnchantments(entity, type, amount); } - + protected float getDamageWithArmor(LivingEntity entity, DamageTypeInfo typeInfo, float amount) { if (typeInfo.bypassesArmor()) return amount; - + double armorValue = entity.getAttributeValue(Attribute.ARMOR); if (version.legacy()) { int armorMultiplier = 25 - (int) armorValue; @@ -58,11 +58,11 @@ protected float getDamageWithArmor(LivingEntity entity, DamageTypeInfo typeInfo, ); } } - + protected float getDamageWithEnchantments(LivingEntity entity, DamageType damageType, float amount) { DamageTypeInfo damageTypeInfo = DamageTypeInfo.of(MinecraftServer.getDamageTypeRegistry().getKey(damageType)); if (damageTypeInfo.unblockable()) return amount; - + int k; TimedPotion effect = entity.getEffect(PotionEffect.RESISTANCE); if (effect != null) { @@ -71,7 +71,7 @@ protected float getDamageWithEnchantments(LivingEntity entity, DamageType damage float f = amount * (float) j; amount = Math.max(f / 25, 0); } - + if (amount <= 0) { return 0; } else { @@ -84,24 +84,24 @@ protected float getDamageWithEnchantments(LivingEntity entity, DamageType damage if (k > 20) { k = 20; } - + if (k > 0) { int j = 25 - k; float f = amount * (float) j; amount = f / 25; } } - + return amount; } } - + protected float getDamageLeft(float damage, float armor, float armorToughness) { float f = 2.0f + armorToughness / 4.0f; float g = MathUtils.clamp(armor - damage / f, armor * 0.2f, 20.0f); return damage * (1.0F - g / 25.0F); } - + protected float getDamageAfterProtectionEnchantment(float damageDealt, float protection) { float f = MathUtils.clamp(protection, 0.0f, 20.0f); return damageDealt * (1.0f - f / 25.0f); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaAttackFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaAttackFeature.java index bf401549d..2c432ef4e 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaAttackFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaAttackFeature.java @@ -1,5 +1,25 @@ package net.swofty.pvp.feature.attack; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.sound.Sound; +import net.minestom.server.ServerFlag; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EquipmentSlot; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.attribute.Attribute; +import net.minestom.server.entity.damage.Damage; +import net.minestom.server.entity.damage.DamageType; +import net.minestom.server.event.EventDispatcher; +import net.minestom.server.event.EventNode; +import net.minestom.server.event.entity.EntityAttackEvent; +import net.minestom.server.event.trait.EntityInstanceEvent; +import net.minestom.server.network.packet.server.play.EntityAnimationPacket; +import net.minestom.server.network.packet.server.play.ParticlePacket; +import net.minestom.server.particle.Particle; +import net.minestom.server.sound.SoundEvent; import net.swofty.pvp.enchantment.EntityGroup; import net.swofty.pvp.enums.Tool; import net.swofty.pvp.events.FinalAttackEvent; @@ -13,25 +33,11 @@ import net.swofty.pvp.feature.food.ExhaustionFeature; import net.swofty.pvp.feature.item.ItemDamageFeature; import net.swofty.pvp.feature.knockback.KnockbackFeature; +import net.swofty.pvp.feature.provider.PacketProvider; +import net.swofty.pvp.feature.provider.SoundProvider; import net.swofty.pvp.player.CombatPlayer; import net.swofty.pvp.utils.CombatVersion; import net.swofty.pvp.utils.ViewUtil; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.sound.Sound; -import net.minestom.server.ServerFlag; -import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.*; -import net.minestom.server.entity.attribute.Attribute; -import net.minestom.server.entity.damage.Damage; -import net.minestom.server.entity.damage.DamageType; -import net.minestom.server.event.EventDispatcher; -import net.minestom.server.event.EventNode; -import net.minestom.server.event.entity.EntityAttackEvent; -import net.minestom.server.event.trait.EntityInstanceEvent; -import net.minestom.server.network.packet.server.play.EntityAnimationPacket; -import net.minestom.server.network.packet.server.play.ParticlePacket; -import net.minestom.server.particle.Particle; -import net.minestom.server.sound.SoundEvent; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -43,235 +49,264 @@ * Listens on {@link EntityAttackEvent} */ public class VanillaAttackFeature implements AttackFeature, RegistrableFeature { - public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.ATTACK, VanillaAttackFeature::new, - FeatureType.ATTACK_COOLDOWN, FeatureType.EXHAUSTION, FeatureType.ITEM_DAMAGE, - FeatureType.ENCHANTMENT, FeatureType.CRITICAL, FeatureType.SWEEPING, FeatureType.KNOCKBACK, FeatureType.VERSION - ); - - private static final double ATTACK_RANGE_MARGIN = 3.0; - - private final FeatureConfiguration configuration; - - private AttackCooldownFeature cooldownFeature; - private ExhaustionFeature exhaustionFeature; - private ItemDamageFeature itemDamageFeature; - private EnchantmentFeature enchantmentFeature; - - private CriticalFeature criticalFeature; - private SweepingFeature sweepingFeature; - private KnockbackFeature knockbackFeature; - - private CombatVersion version; - - public VanillaAttackFeature(FeatureConfiguration configuration) { - this.configuration = configuration; - } - - @Override - public void initDependencies() { - this.cooldownFeature = configuration.get(FeatureType.ATTACK_COOLDOWN); - this.exhaustionFeature = configuration.get(FeatureType.EXHAUSTION); - this.itemDamageFeature = configuration.get(FeatureType.ITEM_DAMAGE); - this.enchantmentFeature = configuration.get(FeatureType.ENCHANTMENT); - this.criticalFeature = configuration.get(FeatureType.CRITICAL); - this.sweepingFeature = configuration.get(FeatureType.SWEEPING); - this.knockbackFeature = configuration.get(FeatureType.KNOCKBACK); - this.version = configuration.get(FeatureType.VERSION); - } - - @Override - public void init(EventNode node) { - node.addListener(EntityAttackEvent.class, event -> { - if (event.getEntity() instanceof Player player && player.getGameMode() != GameMode.SPECTATOR && !player.isDead()) { - Entity target = event.getTarget(); - double maxDistanceSquared = Math.pow(player.getAttributeValue(Attribute.ENTITY_INTERACTION_RANGE) + ATTACK_RANGE_MARGIN, 2); - if (player.getPosition().distanceSquared(target.getPosition().add(0, target.getEyeHeight(), 0)) < maxDistanceSquared) - performAttack(player, target); - } - }); - } - - @Override - public boolean performAttack(LivingEntity attacker, Entity target) { - PrepareAttackEvent prepareAttackEvent = new PrepareAttackEvent(attacker, target); - EventDispatcher.call(prepareAttackEvent); - if (prepareAttackEvent.isCancelled()) return false; - AttackValues.Final attack = prepareAttack(attacker, target); - if (attack == null) return false; // Event cancelled - - float originalHealth = 0; - boolean damageSucceeded = false; - if (target instanceof LivingEntity livingTarget) { - originalHealth = livingTarget.getHealth(); - damageSucceeded = livingTarget.damage(new Damage( - attacker instanceof Player ? DamageType.PLAYER_ATTACK : DamageType.MOB_ATTACK, - attacker, attacker, - null, attack.damage() - )); - } - - if (!damageSucceeded) { - // No damage sound - if (attack.sounds() && attack.playSoundsOnFail()) { - ViewUtil.viewersAndSelf(attacker).playSound(Sound.sound( - SoundEvent.ENTITY_PLAYER_ATTACK_NODAMAGE, Sound.Source.PLAYER, - 1.0f, 1.0f - ), attacker); - } - return false; - } - - // Target is always living now, because the damage would not have succeeded if it wasn't - LivingEntity living = (LivingEntity) target; - Collection affectedEntities = List.of(living); - - // Knockback and sweeping - knockbackFeature.applyAttackKnockback(attacker, living, attack.knockback()); - if (attack.sweeping()) { - affectedEntities = sweepingFeature.applySweeping(attacker, living, attack.damage()); - affectedEntities.add(living); - } - - if (target instanceof CombatPlayer custom) - custom.sendImmediateVelocityUpdate(); - - // Play attack sounds - if (attack.sounds()) { - Audience audience = attacker.getViewersAsAudience(); - if (attacker instanceof Player player) - audience = Audience.audience(audience, player); - - if (attack.sprint()) audience.playSound(Sound.sound( - SoundEvent.ENTITY_PLAYER_ATTACK_KNOCKBACK, Sound.Source.PLAYER, - 1.0f, 1.0f - ), attacker); - - if (attack.sweeping()) audience.playSound(Sound.sound( - SoundEvent.ENTITY_PLAYER_ATTACK_SWEEP, Sound.Source.PLAYER, - 1.0f, 1.0f - ), attacker); - - if (attack.critical()) audience.playSound(Sound.sound( - SoundEvent.ENTITY_PLAYER_ATTACK_CRIT, Sound.Source.PLAYER, - 1.0f, 1.0f - ), attacker); - - if (!attack.critical() && !attack.sweeping()) audience.playSound(Sound.sound( - attack.strong() ? - SoundEvent.ENTITY_PLAYER_ATTACK_STRONG : - SoundEvent.ENTITY_PLAYER_ATTACK_WEAK, - Sound.Source.PLAYER, 1.0f, 1.0f - ), attacker); - } - - // Play attack effects - if (attack.critical()) attacker.sendPacketToViewersAndSelf(new EntityAnimationPacket( - target.getEntityId(), - EntityAnimationPacket.Animation.CRITICAL_EFFECT - )); - if (attack.magical()) attacker.sendPacketToViewersAndSelf(new EntityAnimationPacket( - target.getEntityId(), - EntityAnimationPacket.Animation.MAGICAL_CRITICAL_EFFECT - )); - - for (LivingEntity affectedEntity : affectedEntities) { - // Thorns - enchantmentFeature.onUserDamaged(affectedEntity, attacker); - enchantmentFeature.onTargetDamaged(attacker, affectedEntity); - - if (attack.fireAspect() > 0) { - for (LivingEntity entity : affectedEntities) { - entity.setFireTicks(attack.fireAspect() * 4 * ServerFlag.SERVER_TICKS_PER_SECOND); - } - } - } - - // Damage item - Tool tool = Tool.fromMaterial(attacker.getItemInMainHand().material()); - if (tool != null) itemDamageFeature.damageEquipment(attacker, EquipmentSlot.MAIN_HAND, - (tool.isSword() || tool == Tool.TRIDENT) ? 1 : 2); - - // Damage indicator particles - float damageDone = originalHealth - living.getHealth(); - if (damageDone > 2) { - int particleCount = (int) (damageDone * 0.5); - Pos targetPosition = target.getPosition(); - target.sendPacketToViewersAndSelf(new ParticlePacket( - Particle.DAMAGE_INDICATOR, false, false, - targetPosition.x(), targetPosition.y() + target.getBoundingBox().height() * 0.5, targetPosition.z(), - 0.1f, 0, 0.1f, - 0.2F, particleCount - )); - } - - if (attacker instanceof Player player) - exhaustionFeature.addAttackExhaustion(player); - - return true; - } - - protected @Nullable AttackValues.Final prepareAttack(LivingEntity attacker, Entity target) { - float damage = (float) attacker.getAttributeValue(Attribute.ATTACK_DAMAGE); - float magicalDamage = enchantmentFeature.getAttackDamage( - attacker.getItemInMainHand(), - target instanceof LivingEntity living ? EntityGroup.ofEntity(living) : EntityGroup.DEFAULT - ); - - double cooldownProgress = 1; - if (attacker instanceof Player player) { - cooldownProgress = cooldownFeature.getAttackCooldownProgress(player); - cooldownFeature.resetCooldownProgress(player); - } - - // Apply cooldownProgress to damage - damage *= (float) (0.2 + cooldownProgress * cooldownProgress * 0.8); - magicalDamage *= (float) cooldownProgress; - - // Calculate attacks - boolean strongAttack = cooldownProgress > 0.9; - boolean sprintAttack = attacker.isSprinting() && strongAttack; - int knockback = enchantmentFeature.getKnockback(attacker); - int fireAspect = enchantmentFeature.getFireAspect(attacker); - - // Use features to determine critical and sweeping - AttackValues.PreCritical preCritical = new AttackValues.PreCritical( - damage, magicalDamage, cooldownProgress, - strongAttack, sprintAttack, knockback, fireAspect - ); - AttackValues.PreSweeping preSweeping = preCritical.withCritical(criticalFeature.shouldCrit(attacker, preCritical)); - AttackValues.PreSounds preSounds = preSweeping.withSweeping(sweepingFeature.shouldSweep(attacker, preSweeping)); - - boolean critical = preSounds.critical(); - boolean sweeping = preSounds.sweeping(); - - boolean sounds = version.modern(); - - // Call event which can modify attack values - FinalAttackEvent finalAttackEvent = new FinalAttackEvent( - attacker, target, sprintAttack, critical, sweeping, damage, - magicalDamage, sounds, sounds - ); - EventDispatcher.call(finalAttackEvent); - if (finalAttackEvent.isCancelled()) return null; - - sprintAttack = finalAttackEvent.isSprint(); - critical = finalAttackEvent.isCritical(); - sweeping = finalAttackEvent.isSweeping(); - damage = finalAttackEvent.getBaseDamage(); - magicalDamage = finalAttackEvent.getEnchantsExtraDamage(); - - // Apply critical damage and knockback - if (critical) damage = criticalFeature.applyToDamage(damage); - damage += magicalDamage; - - if (sprintAttack) knockback++; - - return new AttackValues.Final( - damage, strongAttack, sprintAttack, knockback, critical, - magicalDamage > 0, fireAspect, sweeping, - finalAttackEvent.hasAttackSounds(), - finalAttackEvent.playSoundsOnFail() - ); - } + public static final DefinedFeature DEFINED = new DefinedFeature<>( + FeatureType.ATTACK, VanillaAttackFeature::new, + FeatureType.ATTACK_COOLDOWN, FeatureType.EXHAUSTION, FeatureType.ITEM_DAMAGE, + FeatureType.ENCHANTMENT, FeatureType.CRITICAL, FeatureType.SWEEPING, FeatureType.KNOCKBACK, FeatureType.VERSION, + FeatureType.PACKET, FeatureType.SOUND + ); + + private static final double ATTACK_RANGE_MARGIN = 3.0; + + private final FeatureConfiguration configuration; + + private AttackCooldownFeature cooldownFeature; + private ExhaustionFeature exhaustionFeature; + private ItemDamageFeature itemDamageFeature; + private EnchantmentFeature enchantmentFeature; + + private CriticalFeature criticalFeature; + private SweepingFeature sweepingFeature; + private KnockbackFeature knockbackFeature; + private PacketProvider packetProvider; + private SoundProvider soundProvider; + + private CombatVersion version; + + public VanillaAttackFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void initDependencies() { + this.cooldownFeature = configuration.get(FeatureType.ATTACK_COOLDOWN); + this.exhaustionFeature = configuration.get(FeatureType.EXHAUSTION); + this.itemDamageFeature = configuration.get(FeatureType.ITEM_DAMAGE); + this.enchantmentFeature = configuration.get(FeatureType.ENCHANTMENT); + this.criticalFeature = configuration.get(FeatureType.CRITICAL); + this.sweepingFeature = configuration.get(FeatureType.SWEEPING); + this.knockbackFeature = configuration.get(FeatureType.KNOCKBACK); + this.version = configuration.get(FeatureType.VERSION); + this.packetProvider = configuration.get(FeatureType.PACKET); + this.soundProvider = configuration.get(FeatureType.SOUND); + } + + @Override + public void init(EventNode node) { + node.addListener(EntityAttackEvent.class, event -> { + if (event.getEntity() instanceof Player player && player.getGameMode() != GameMode.SPECTATOR && !player.isDead()) { + Entity target = event.getTarget(); + double maxDistanceSquared = Math.pow(player.getAttributeValue(Attribute.ENTITY_INTERACTION_RANGE) + ATTACK_RANGE_MARGIN, 2); + if (player.getPosition().distanceSquared(target.getPosition().add(0, target.getEyeHeight(), 0)) < maxDistanceSquared) + performAttack(player, target); + } + }); + } + + @Override + public boolean performAttack(LivingEntity attacker, Entity target) { + PrepareAttackEvent prepareAttackEvent = new PrepareAttackEvent(attacker, target); + EventDispatcher.call(prepareAttackEvent); + if (prepareAttackEvent.isCancelled()) return false; + AttackValues.Final attack = prepareAttack(attacker, target); + if (attack == null) return false; // Event cancelled + + float originalHealth = 0; + boolean damageSucceeded = false; + if (target instanceof LivingEntity livingTarget) { + originalHealth = livingTarget.getHealth(); + damageSucceeded = livingTarget.damage(new Damage( + attacker instanceof Player ? DamageType.PLAYER_ATTACK : DamageType.MOB_ATTACK, + attacker, attacker, + null, attack.damage() + )); + } + + if (!damageSucceeded) { + // No damage sound + if (attack.sounds() && attack.playSoundsOnFail()) { + Pos attackerPos = attacker.getPosition(); + soundProvider.playSound( + ViewUtil.viewersAndSelf(attacker), + Sound.sound( + SoundEvent.ENTITY_PLAYER_ATTACK_NODAMAGE, Sound.Source.PLAYER, + 1.0f, 1.0f + ), + attackerPos.x(), attackerPos.y(), attackerPos.z() + ); + } + return false; + } + + // Target is always living now, because the damage would not have succeeded if it wasn't + LivingEntity living = (LivingEntity) target; + Collection affectedEntities = List.of(living); + + // Knockback and sweeping + knockbackFeature.applyAttackKnockback(attacker, living, attack.knockback()); + if (attack.sweeping()) { + affectedEntities = sweepingFeature.applySweeping(attacker, living, attack.damage()); + affectedEntities.add(living); + } + + if (target instanceof CombatPlayer custom) + custom.sendImmediateVelocityUpdate(); + + // Play attack sounds + if (attack.sounds()) { + Audience audience = attacker.getViewersAsAudience(); + if (attacker instanceof Player player) + audience = Audience.audience(audience, player); + + if (attack.sprint()) soundProvider.playSound( + audience, + Sound.sound( + SoundEvent.ENTITY_PLAYER_ATTACK_KNOCKBACK, Sound.Source.PLAYER, + 1.0f, 1.0f + ), + attacker.getPosition().x(), attacker.getPosition().y(), attacker.getPosition().z() + ); + + if (attack.sweeping()) soundProvider.playSound( + audience, + Sound.sound( + SoundEvent.ENTITY_PLAYER_ATTACK_SWEEP, Sound.Source.PLAYER, + 1.0f, 1.0f + ), + attacker.getPosition().x(), attacker.getPosition().y(), attacker.getPosition().z() + ); + + if (attack.critical()) soundProvider.playSound(audience, + Sound.sound( + SoundEvent.ENTITY_PLAYER_ATTACK_CRIT, Sound.Source.PLAYER, + 1.0f, 1.0f + ), + attacker.getPosition().x(), attacker.getPosition().y(), attacker.getPosition().z() + ); + + if (!attack.critical() && !attack.sweeping()) soundProvider.playSound( + audience, + Sound.sound( + attack.strong() ? + SoundEvent.ENTITY_PLAYER_ATTACK_STRONG : + SoundEvent.ENTITY_PLAYER_ATTACK_WEAK, + Sound.Source.PLAYER, 1.0f, 1.0f + ), + attacker.getPosition().x(), attacker.getPosition().y(), attacker.getPosition().z() + ); + } + + // Play attack effects + if (attack.critical()) packetProvider.sendPacket(attacker, new EntityAnimationPacket( + target.getEntityId(), + EntityAnimationPacket.Animation.CRITICAL_EFFECT + ) + ); + if (attack.magical()) packetProvider.sendPacket(attacker, new EntityAnimationPacket( + target.getEntityId(), + EntityAnimationPacket.Animation.MAGICAL_CRITICAL_EFFECT + )); + + for (LivingEntity affectedEntity : affectedEntities) { + // Thorns + enchantmentFeature.onUserDamaged(affectedEntity, attacker); + enchantmentFeature.onTargetDamaged(attacker, affectedEntity); + + if (attack.fireAspect() > 0) { + for (LivingEntity entity : affectedEntities) { + entity.setFireTicks(attack.fireAspect() * 4 * ServerFlag.SERVER_TICKS_PER_SECOND); + } + } + } + + // Damage item + Tool tool = Tool.fromMaterial(attacker.getItemInMainHand().material()); + if (tool != null) itemDamageFeature.damageEquipment(attacker, EquipmentSlot.MAIN_HAND, + (tool.isSword() || tool == Tool.TRIDENT) ? 1 : 2); + + // Damage indicator particles + float damageDone = originalHealth - living.getHealth(); + if (damageDone > 2) { + int particleCount = (int) (damageDone * 0.5); + Pos targetPosition = target.getPosition(); + packetProvider.sendPacket( + target, + new ParticlePacket( + Particle.DAMAGE_INDICATOR, false, false, + targetPosition.x(), targetPosition.y() + target.getBoundingBox().height() * 0.5, targetPosition.z(), + 0.1f, 0, 0.1f, + 0.2F, particleCount + ) + ); + } + + if (attacker instanceof Player player) + exhaustionFeature.addAttackExhaustion(player); + + return true; + } + + protected @Nullable AttackValues.Final prepareAttack(LivingEntity attacker, Entity target) { + float damage = (float) attacker.getAttributeValue(Attribute.ATTACK_DAMAGE); + float magicalDamage = enchantmentFeature.getAttackDamage( + attacker.getItemInMainHand(), + target instanceof LivingEntity living ? EntityGroup.ofEntity(living) : EntityGroup.DEFAULT + ); + + double cooldownProgress = 1; + if (version.modern() && attacker instanceof Player player) { + cooldownProgress = cooldownFeature.getAttackCooldownProgress(player); + cooldownFeature.resetCooldownProgress(player); + } + + if (version.modern()) { + damage *= (float) (0.2 + cooldownProgress * cooldownProgress * 0.8); + magicalDamage *= (float) cooldownProgress; + } + + boolean strongAttack = version.legacy() || cooldownProgress > 0.9; + boolean sprintAttack = attacker.isSprinting() && strongAttack; + int knockback = enchantmentFeature.getKnockback(attacker); + int fireAspect = enchantmentFeature.getFireAspect(attacker); + + // Use features to determine critical and sweeping + AttackValues.PreCritical preCritical = new AttackValues.PreCritical( + damage, magicalDamage, cooldownProgress, + strongAttack, sprintAttack, knockback, fireAspect + ); + AttackValues.PreSweeping preSweeping = preCritical.withCritical(criticalFeature.shouldCrit(attacker, preCritical)); + AttackValues.PreSounds preSounds = preSweeping.withSweeping(sweepingFeature.shouldSweep(attacker, preSweeping)); + + boolean critical = preSounds.critical(); + boolean sweeping = preSounds.sweeping(); + + boolean sounds = version.modern(); + + // Call event which can modify attack values + FinalAttackEvent finalAttackEvent = new FinalAttackEvent( + attacker, target, sprintAttack, critical, sweeping, damage, + magicalDamage, sounds, sounds + ); + EventDispatcher.call(finalAttackEvent); + if (finalAttackEvent.isCancelled()) return null; + + sprintAttack = finalAttackEvent.isSprint(); + critical = finalAttackEvent.isCritical(); + sweeping = finalAttackEvent.isSweeping(); + damage = finalAttackEvent.getBaseDamage(); + magicalDamage = finalAttackEvent.getEnchantsExtraDamage(); + + // Apply critical damage and knockback + if (critical) damage = criticalFeature.applyToDamage(damage); + damage += magicalDamage; + + if (sprintAttack) knockback++; + + return new AttackValues.Final( + damage, strongAttack, sprintAttack, knockback, critical, + magicalDamage > 0, fireAspect, sweeping, + finalAttackEvent.hasAttackSounds(), + finalAttackEvent.playSoundsOnFail() + ); + } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaCriticalFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaCriticalFeature.java index 81695be37..93417c866 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaCriticalFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaCriticalFeature.java @@ -1,14 +1,14 @@ package net.swofty.pvp.feature.attack; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.potion.PotionEffect; import net.swofty.pvp.feature.FeatureType; import net.swofty.pvp.feature.config.DefinedFeature; import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.fall.FallFeature; import net.swofty.pvp.feature.state.PlayerStateFeature; import net.swofty.pvp.utils.CombatVersion; -import net.minestom.server.entity.LivingEntity; -import net.minestom.server.potion.PotionEffect; - -import java.util.concurrent.ThreadLocalRandom; +import net.swofty.pvp.utils.FluidUtil; /** * Vanilla implementation of {@link CriticalFeature} @@ -16,42 +16,49 @@ public class VanillaCriticalFeature implements CriticalFeature { public static final DefinedFeature DEFINED = new DefinedFeature<>( FeatureType.CRITICAL, VanillaCriticalFeature::new, - FeatureType.PLAYER_STATE, FeatureType.VERSION + FeatureType.PLAYER_STATE, FeatureType.VERSION, FeatureType.FALL ); - + private final FeatureConfiguration configuration; - + private PlayerStateFeature playerStateFeature; private CombatVersion version; - + private FallFeature fallFeature; + public VanillaCriticalFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.playerStateFeature = configuration.get(FeatureType.PLAYER_STATE); this.version = configuration.get(FeatureType.VERSION); + this.fallFeature = configuration.get(FeatureType.FALL); } - + @Override public boolean shouldCrit(LivingEntity attacker, AttackValues.PreCritical values) { - boolean critical = values.strong() && !playerStateFeature.isClimbing(attacker) - && attacker.getVelocity().y() < 0 && !attacker.isOnGround() + boolean isFalling = attacker.getVelocity().y() < 0; + + double fallDistance = fallFeature.getFallDistance(attacker); + boolean hasFallDistance = fallDistance > 0.0; + + boolean critical = values.strong() + && !attacker.isOnGround() + && (isFalling || hasFallDistance) + && !playerStateFeature.isClimbing(attacker) + && !FluidUtil.isTouchingWater(attacker) && !attacker.hasEffect(PotionEffect.BLINDNESS) && attacker.getVehicle() == null; + if (version.legacy()) return critical; - + // Not sprinting required for critical in 1.9+ return critical && !attacker.isSprinting(); } - + @Override public float applyToDamage(float damage) { - if (version.legacy()) { - return damage + ThreadLocalRandom.current().nextInt((int) (damage / 2 + 2)); - } else { - return damage * 1.5f; - } + return damage * 1.5f; } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaSweepingFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaSweepingFeature.java index d4615ea4e..d876dfaaa 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaSweepingFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/attack/VanillaSweepingFeature.java @@ -1,12 +1,5 @@ package net.swofty.pvp.feature.attack; -import net.swofty.pvp.enchantment.EntityGroup; -import net.swofty.pvp.enums.Tool; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.enchantment.EnchantmentFeature; -import net.swofty.pvp.feature.knockback.KnockbackFeature; import net.minestom.server.collision.BoundingBox; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Entity; @@ -18,6 +11,14 @@ import net.minestom.server.entity.damage.DamageType; import net.minestom.server.network.packet.server.play.ParticlePacket; import net.minestom.server.particle.Particle; +import net.swofty.pvp.enchantment.EntityGroup; +import net.swofty.pvp.enums.Tool; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.enchantment.EnchantmentFeature; +import net.swofty.pvp.feature.knockback.KnockbackFeature; +import net.swofty.pvp.feature.provider.PacketProvider; import java.util.ArrayList; import java.util.Collection; @@ -27,87 +28,93 @@ * Vanilla implementation of {@link SweepingFeature} */ public class VanillaSweepingFeature implements SweepingFeature { - public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.SWEEPING, VanillaSweepingFeature::new, - FeatureType.ENCHANTMENT, FeatureType.KNOCKBACK - ); - - private final FeatureConfiguration configuration; - - private EnchantmentFeature enchantmentFeature; - private KnockbackFeature knockbackFeature; - - public VanillaSweepingFeature(FeatureConfiguration configuration) { - this.configuration = configuration; - } - - @Override - public void initDependencies() { - this.enchantmentFeature = configuration.get(FeatureType.ENCHANTMENT); - this.knockbackFeature = configuration.get(FeatureType.KNOCKBACK); - } - - @Override - public boolean shouldSweep(LivingEntity attacker, AttackValues.PreSweeping values) { - if (!values.strong() || values.critical() || values.sprint() || !attacker.isOnGround()) return false; - - double lastMoveDistance = attacker.getPreviousPosition().distance(attacker.getPosition()) * 0.6; - if (lastMoveDistance >= attacker.getAttributeValue(Attribute.MOVEMENT_SPEED)) return false; - - Tool tool = Tool.fromMaterial(attacker.getItemInMainHand().material()); - return tool != null && tool.isSword(); - } - - @Override - public float getSweepingDamage(LivingEntity attacker, float damage) { - float sweepingMultiplier = 0; - int sweepingLevel = enchantmentFeature.getSweeping(attacker); - if (sweepingLevel > 0) sweepingMultiplier = 1.0f - (1.0f / (float) (sweepingLevel + 1)); - return 1.0f + sweepingMultiplier * damage; - } - - @Override - public Collection applySweeping(LivingEntity attacker, LivingEntity target, float damage) { - float sweepingDamage = getSweepingDamage(attacker, damage); - - // Loop and check for colliding entities - List affectedEntities = new ArrayList<>(); - BoundingBox boundingBox = target.getBoundingBox().expand(1.0, 0.25, 1.0); - assert target.getInstance() != null; - for (Entity nearbyEntity : target.getInstance().getNearbyEntities(target.getPosition(), 2)) { - if (nearbyEntity == target || nearbyEntity == attacker) continue; - if (!(nearbyEntity instanceof LivingEntity living)) continue; - if (nearbyEntity.getEntityType() == EntityType.ARMOR_STAND) continue; - if (!boundingBox.intersectEntity(target.getPosition(), nearbyEntity)) continue; - - // Apply sweeping knockback and damage to the entity - if (attacker.getPosition().distanceSquared(nearbyEntity.getPosition()) < 9.0) { - affectedEntities.add(living); - knockbackFeature.applySweepingKnockback(attacker, target); - - float currentDamage = sweepingDamage + enchantmentFeature.getAttackDamage( - attacker.getItemInMainHand(), EntityGroup.ofEntity(target)); - - living.damage(new Damage( - attacker instanceof Player ? DamageType.PLAYER_ATTACK : DamageType.MOB_ATTACK, - attacker, attacker, - null, currentDamage - )); - } - } - - // Spawn sweeping particles - Pos pos = attacker.getPosition(); - double x = -Math.sin(Math.toRadians(pos.yaw())); - double z = Math.cos(Math.toRadians(pos.yaw())); - - attacker.sendPacketToViewersAndSelf(new ParticlePacket( - Particle.SWEEP_ATTACK, false,false, - pos.x() + x, pos.y() + attacker.getBoundingBox().height() * 0.5, pos.z() + z, - (float) x, 0, (float) z, - 0, 0 - )); - - return affectedEntities; - } + public static final DefinedFeature DEFINED = new DefinedFeature<>( + FeatureType.SWEEPING, VanillaSweepingFeature::new, + FeatureType.ENCHANTMENT, FeatureType.KNOCKBACK, + FeatureType.PACKET + ); + + private final FeatureConfiguration configuration; + + private EnchantmentFeature enchantmentFeature; + private KnockbackFeature knockbackFeature; + private PacketProvider packetProvider; + + public VanillaSweepingFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void initDependencies() { + this.packetProvider = configuration.get(FeatureType.PACKET); + this.enchantmentFeature = configuration.get(FeatureType.ENCHANTMENT); + this.knockbackFeature = configuration.get(FeatureType.KNOCKBACK); + } + + @Override + public boolean shouldSweep(LivingEntity attacker, AttackValues.PreSweeping values) { + if (!values.strong() || values.critical() || values.sprint() || !attacker.isOnGround()) return false; + + double lastMoveDistance = attacker.getPreviousPosition().distance(attacker.getPosition()) * 0.6; + if (lastMoveDistance >= attacker.getAttributeValue(Attribute.MOVEMENT_SPEED)) return false; + + Tool tool = Tool.fromMaterial(attacker.getItemInMainHand().material()); + return tool != null && tool.isSword(); + } + + @Override + public float getSweepingDamage(LivingEntity attacker, float damage) { + float sweepingMultiplier = 0; + int sweepingLevel = enchantmentFeature.getSweeping(attacker); + if (sweepingLevel > 0) sweepingMultiplier = 1.0f - (1.0f / (float) (sweepingLevel + 1)); + return 1.0f + sweepingMultiplier * damage; + } + + @Override + public Collection applySweeping(LivingEntity attacker, LivingEntity target, float damage) { + float sweepingDamage = getSweepingDamage(attacker, damage); + + // Loop and check for colliding entities + List affectedEntities = new ArrayList<>(); + BoundingBox boundingBox = target.getBoundingBox().expand(1.0, 0.25, 1.0); + assert target.getInstance() != null; + for (Entity nearbyEntity : target.getInstance().getNearbyEntities(target.getPosition(), 2)) { + if (nearbyEntity == target || nearbyEntity == attacker) continue; + if (!(nearbyEntity instanceof LivingEntity living)) continue; + if (nearbyEntity.getEntityType() == EntityType.ARMOR_STAND) continue; + if (!boundingBox.intersectEntity(target.getPosition(), nearbyEntity)) continue; + + // Apply sweeping knockback and damage to the entity + if (attacker.getPosition().distanceSquared(nearbyEntity.getPosition()) < 9.0) { + affectedEntities.add(living); + knockbackFeature.applySweepingKnockback(attacker, target); + + float currentDamage = sweepingDamage + enchantmentFeature.getAttackDamage( + attacker.getItemInMainHand(), EntityGroup.ofEntity(target)); + + living.damage(new Damage( + attacker instanceof Player ? DamageType.PLAYER_ATTACK : DamageType.MOB_ATTACK, + attacker, attacker, + null, currentDamage + )); + } + } + + // Spawn sweeping particles + Pos pos = attacker.getPosition(); + double x = -Math.sin(Math.toRadians(pos.yaw())); + double z = Math.cos(Math.toRadians(pos.yaw())); + + packetProvider.sendPacket( + attacker, + new ParticlePacket( + Particle.SWEEP_ATTACK, false, false, + pos.x() + x, pos.y() + attacker.getBoundingBox().height() * 0.5, pos.z() + z, + (float) x, 0, (float) z, + 0, 0 + ) + ); + + return affectedEntities; + } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/attributes/VanillaEquipmentFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/attributes/VanillaEquipmentFeature.java index 37303b754..65960f701 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/attributes/VanillaEquipmentFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/attributes/VanillaEquipmentFeature.java @@ -1,12 +1,5 @@ package net.swofty.pvp.feature.attributes; -import net.swofty.pvp.enums.ArmorMaterial; -import net.swofty.pvp.enums.Tool; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.utils.CombatVersion; import net.minestom.server.entity.EquipmentSlot; import net.minestom.server.entity.LivingEntity; import net.minestom.server.event.EventNode; @@ -14,6 +7,13 @@ import net.minestom.server.event.player.PlayerChangeHeldSlotEvent; import net.minestom.server.event.trait.EntityInstanceEvent; import net.minestom.server.item.ItemStack; +import net.swofty.pvp.enums.ArmorMaterial; +import net.swofty.pvp.enums.Tool; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.utils.CombatVersion; /** * Vanilla implementation of {@link EquipmentFeature} @@ -23,22 +23,22 @@ public class VanillaEquipmentFeature implements EquipmentFeature, RegistrableFea FeatureType.EQUIPMENT, VanillaEquipmentFeature::new, FeatureType.VERSION ); - + private final FeatureConfiguration configuration; - + //TODO this probably shouldn't work this way // We probably want to store all the tools & armor separately per DataFeature private CombatVersion version; - + public VanillaEquipmentFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.version = configuration.get(FeatureType.VERSION); } - + @Override public void init(EventNode node) { node.addListener(EntityEquipEvent.class, this::onEquip); @@ -48,10 +48,10 @@ public void init(EventNode node) { Tool.updateEquipmentAttributes(entity, entity.getEquipment(EquipmentSlot.MAIN_HAND), newItem, EquipmentSlot.MAIN_HAND, version); }); } - + protected void onEquip(EntityEquipEvent event) { if (!(event.getEntity() instanceof LivingEntity entity)) return; - + EquipmentSlot slot = event.getSlot(); if (slot.isArmor()) { ArmorMaterial.updateEquipmentAttributes(entity, entity.getEquipment(slot), event.getEquippedItem(), slot, version); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/block/LegacyVanillaBlockFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/block/LegacyVanillaBlockFeature.java index 936b6353e..4bb642cc9 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/block/LegacyVanillaBlockFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/block/LegacyVanillaBlockFeature.java @@ -1,10 +1,5 @@ package net.swofty.pvp.feature.block; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.utils.CombatVersion; import net.minestom.server.entity.Player; import net.minestom.server.entity.PlayerHand; import net.minestom.server.event.EventNode; @@ -17,6 +12,11 @@ import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.tag.Tag; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.utils.CombatVersion; /** * Vanilla implementation of {@link LegacyBlockFeature} @@ -28,53 +28,53 @@ public class LegacyVanillaBlockFeature extends VanillaBlockFeature LegacyVanillaBlockFeature::initPlayer, FeatureType.ITEM_DAMAGE ); - + public static final Tag LAST_SWING_TIME = Tag.Long("lastSwingTime"); public static final Tag BLOCKING_SWORD = Tag.Boolean("blockingSword"); public static final Tag BLOCK_REPLACEMENT_ITEM = Tag.ItemStack("blockReplacementItem"); - + private final ItemStack blockingItem; - + public LegacyVanillaBlockFeature(FeatureConfiguration configuration, ItemStack blockingItem) { super(configuration.add(FeatureType.VERSION, CombatVersion.LEGACY)); this.blockingItem = blockingItem; } - + public static void initPlayer(Player player, boolean firstInit) { player.setTag(LAST_SWING_TIME, 0L); player.setTag(BLOCKING_SWORD, false); } - + @Override public void init(EventNode node) { node.addListener(PlayerUseItemEvent.class, this::handleUseItem); node.addListener(PlayerFinishItemUseEvent.class, this::handleUpdateState); node.addListener(PlayerSwapItemEvent.class, this::handleSwapItem); node.addListener(PlayerChangeHeldSlotEvent.class, this::handleChangeSlot); - + node.addListener(PlayerHandAnimationEvent.class, event -> { if (event.getHand() == PlayerHand.MAIN) event.getPlayer().setTag(LAST_SWING_TIME, System.currentTimeMillis()); }); } - + @Override public boolean isBlocking(Player player) { return player.getTag(BLOCKING_SWORD); } - + @Override public void block(Player player) { if (!isBlocking(player)) { player.setTag(BLOCK_REPLACEMENT_ITEM, player.getItemInOffHand()); player.setTag(BLOCKING_SWORD, true); - + player.setItemInOffHand(blockingItem); player.refreshActiveHand(true, true, false); player.sendPacketToViewersAndSelf(player.getMetadataPacket()); } } - + @Override public void unblock(Player player) { if (isBlocking(player)) { @@ -83,37 +83,37 @@ public void unblock(Player player) { player.removeTag(BLOCK_REPLACEMENT_ITEM); } } - + private void handleUseItem(PlayerUseItemEvent event) { Player player = event.getPlayer(); - + if (event.getHand() == PlayerHand.MAIN && !isBlocking(player) && canBlockWith(player, event.getItemStack())) { long elapsedSwingTime = System.currentTimeMillis() - player.getTag(LAST_SWING_TIME); if (elapsedSwingTime < 50) { return; } - + block(player); } } - + protected void handleUpdateState(PlayerFinishItemUseEvent event) { if (event.getHand() == PlayerHand.OFF && event.getItemStack().isSimilar(blockingItem)) unblock(event.getPlayer()); } - + protected void handleSwapItem(PlayerSwapItemEvent event) { Player player = event.getPlayer(); if (player.getItemInOffHand().isSimilar(blockingItem) && isBlocking(player)) event.setCancelled(true); } - + protected void handleChangeSlot(PlayerChangeHeldSlotEvent event) { Player player = event.getPlayer(); if (player.getItemInOffHand().isSimilar(blockingItem) && isBlocking(player)) unblock(player); } - + @Override public boolean canBlockWith(Player player, ItemStack stack) { return stack.material().registry().key().value().contains("sword"); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/block/VanillaBlockFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/block/VanillaBlockFeature.java index c60c2bffc..f94fcd637 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/block/VanillaBlockFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/block/VanillaBlockFeature.java @@ -1,16 +1,5 @@ package net.swofty.pvp.feature.block; -import java.util.concurrent.ThreadLocalRandom; - -import net.swofty.pvp.damage.DamageTypeInfo; -import net.swofty.pvp.enums.Tool; -import net.swofty.pvp.events.DamageBlockEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.cooldown.ItemCooldownFeature; -import net.swofty.pvp.feature.item.ItemDamageFeature; -import net.swofty.pvp.utils.CombatVersion; import net.kyori.adventure.sound.Sound; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; @@ -25,6 +14,17 @@ import net.minestom.server.event.EventDispatcher; import net.minestom.server.item.Material; import net.minestom.server.sound.SoundEvent; +import net.swofty.pvp.damage.DamageTypeInfo; +import net.swofty.pvp.enums.Tool; +import net.swofty.pvp.events.DamageBlockEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.cooldown.ItemCooldownFeature; +import net.swofty.pvp.feature.item.ItemDamageFeature; +import net.swofty.pvp.utils.CombatVersion; + +import java.util.concurrent.ThreadLocalRandom; /** * Vanilla implementation of {@link BlockFeature} @@ -34,71 +34,71 @@ public class VanillaBlockFeature implements BlockFeature { FeatureType.BLOCK, VanillaBlockFeature::new, FeatureType.ITEM_DAMAGE, FeatureType.ITEM_COOLDOWN, FeatureType.VERSION ); - + private final FeatureConfiguration configuration; - + private ItemDamageFeature itemDamageFeature; private ItemCooldownFeature itemCooldownFeature; private CombatVersion version; - + public VanillaBlockFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.itemDamageFeature = configuration.get(FeatureType.ITEM_DAMAGE); this.itemCooldownFeature = configuration.get(FeatureType.ITEM_COOLDOWN); this.version = configuration.get(FeatureType.VERSION); } - + protected boolean isPiercing(Damage damage) { Entity source = damage.getSource(); if (source != null && source.getEntityMeta() instanceof AbstractArrowMeta) { return ((AbstractArrowMeta) source.getEntityMeta()).getPiercingLevel() > 0; } - + return false; } - + @Override public boolean isDamageBlocked(LivingEntity entity, Damage damage) { if (damage.getAmount() <= 0) return false; DamageTypeInfo info = DamageTypeInfo.of(damage.getType()); - + // If damage doesn't bypass armor, no piercing, and a shield is active if (!info.bypassesArmor() && !isPiercing(damage) && entity.getEntityMeta() instanceof LivingEntityMeta meta && meta.isHandActive() && entity.getItemInHand(meta.getActiveHand()).material() == Material.SHIELD) { if (version.legacy()) return true; - + if (damage.getSource() != null) { Pos attackerPos = damage.getSource().getPosition(); Pos entityPos = entity.getPosition(); - + Vec attackerPosVector = attackerPos.asVec(); Vec entityRotation = entityPos.direction(); Vec attackerDirection = entityPos.asVec().sub(attackerPosVector).normalize(); attackerDirection = attackerDirection.withY(0); - + // Dot product is lower than zero when the angle between the vectors is >90 degrees return attackerDirection.dot(entityRotation) < 0.0; } } - + return false; } - + @Override public boolean applyBlock(LivingEntity entity, Damage damage) { float amount = damage.getAmount(); float resultingDamage = version.legacy() ? Math.max(0, (amount + 1) * 0.5f) : 0; - + DamageBlockEvent damageBlockEvent = new DamageBlockEvent(entity, amount, resultingDamage, false); EventDispatcher.call(damageBlockEvent); if (damageBlockEvent.isCancelled()) return false; damage.setAmount(damageBlockEvent.getResultingDamage()); - + if (amount >= 3) { int shieldDamage = 1 + (int) Math.floor(amount); PlayerHand hand = ((LivingEntityMeta) entity.getEntityMeta()).getActiveHand(); @@ -108,7 +108,7 @@ public boolean applyBlock(LivingEntity entity, Damage damage) { EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND, shieldDamage ); - + if (entity.getItemInHand(hand).isAir()) { ((LivingEntityMeta) entity.getEntityMeta()).setHandActive(false); entity.getViewersAsAudience().playSound(Sound.sound( @@ -117,15 +117,15 @@ public boolean applyBlock(LivingEntity entity, Damage damage) { )); } } - + // Take shield hit (knockback and disabling) DamageTypeInfo info = DamageTypeInfo.of(damage.getType()); if (!info.projectile() && damage.getAttacker() instanceof LivingEntity attacker) takeShieldHit(entity, attacker, damageBlockEvent.knockbackAttacker()); - + return resultingDamage == 0; } - + protected void takeShieldHit(LivingEntity entity, LivingEntity attacker, boolean applyKnockback) { if (applyKnockback) { Pos entityPos = entity.getPosition(); @@ -135,21 +135,21 @@ protected void takeShieldHit(LivingEntity entity, LivingEntity attacker, boolean attackerPos.z() - entityPos.z() ); } - + if (!(entity instanceof Player)) return; Tool tool = Tool.fromMaterial(attacker.getItemInMainHand().material()); if (tool != null && tool.isAxe()) { disableShield((Player) entity); } } - + protected void disableShield(Player player) { - itemCooldownFeature.setCooldown(player, Material.SHIELD, 100); - + itemCooldownFeature.setCooldown(player, Material.SHIELD.name(), 100); + // Shield disable status player.triggerStatus((byte) 30); player.triggerStatus((byte) 9); - + PlayerHand hand = player.getPlayerMeta().getActiveHand(); player.refreshActiveHand(false, hand == PlayerHand.OFF, false); } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/config/CombatConfiguration.java b/pvp/src/main/java/net/swofty/pvp/feature/config/CombatConfiguration.java index 69eb1f9ec..051239d82 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/config/CombatConfiguration.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/config/CombatConfiguration.java @@ -5,10 +5,16 @@ import net.swofty.pvp.feature.CombatFeatures; import net.swofty.pvp.feature.FeatureType; import net.swofty.pvp.feature.provider.DifficultyProvider; +import net.swofty.pvp.feature.provider.PacketProvider; +import net.swofty.pvp.feature.provider.SoundProvider; import net.swofty.pvp.utils.CombatVersion; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * A configuration of combat features which can be used to easily resolve dependencies to other combat features. @@ -25,25 +31,25 @@ */ public class CombatConfiguration { private final Map, ConstructableFeature> features = new HashMap<>(); - + public final CombatConfiguration addAll(Collection> constructors) { for (DefinedFeature constructor : constructors) { add(constructor); } return this; } - + public final CombatConfiguration addAll(DefinedFeature... constructors) { for (DefinedFeature constructor : constructors) { add(constructor); } return this; } - + public CombatConfiguration version(CombatVersion version) { return add(FeatureType.VERSION, version); } - + /** * @deprecated use {@link #version(CombatVersion)} instead */ @@ -51,11 +57,19 @@ public CombatConfiguration version(CombatVersion version) { public CombatConfiguration legacy(boolean legacy) { return version(CombatVersion.fromLegacy(legacy)); } - + public CombatConfiguration difficulty(DifficultyProvider difficulty) { return add(FeatureType.DIFFICULTY, difficulty); } - + + public CombatConfiguration packetProvider(PacketProvider packetProvider) { + return add(FeatureType.PACKET, packetProvider); + } + + public CombatConfiguration soundProvider(SoundProvider soundProvider) { + return add(FeatureType.SOUND, soundProvider); + } + /** * Adds a feature to the configuration. This will overwrite any existing feature of this type. * @@ -66,7 +80,7 @@ public CombatConfiguration add(ConstructableFeature feature) { features.put(feature.type, feature); return this; } - + /** * Adds a feature to the configuration. This will overwrite any existing feature of this type. * @@ -77,7 +91,7 @@ public CombatConfiguration add(ConstructableFeature feature) { public CombatConfiguration add(FeatureType type, CombatFeature feature) { return add(wrap(type, feature)); } - + /** * Adds a feature to the configuration. This will overwrite any existing feature of this type. * Any dependencies the feature might have will first be looked up inside the override configuration. @@ -89,7 +103,7 @@ public CombatConfiguration add(FeatureType type, CombatFeature feature) { public CombatConfiguration add(DefinedFeature constructor, FeatureConfiguration override) { return add(wrap(constructor, override)); } - + /** * Adds a feature to the configuration. This will overwrite any existing feature of this type. * Any dependencies the feature might have will first be looked up inside the override configuration. @@ -101,45 +115,45 @@ public CombatConfiguration add(DefinedFeature constructor, FeatureConfigurati public CombatConfiguration add(DefinedFeature constructor, DefinedFeature... override) { return add(wrap(constructor, override)); } - + public CombatConfiguration remove(FeatureType type) { features.remove(type); return this; } - + public static ConstructableFeature wrap(FeatureType type, CombatFeature feature) { return new ConstructedFeature(type, feature); } - + public static ConstructableFeature wrap(DefinedFeature constructor, FeatureConfiguration override) { Set overrideSet = new HashSet<>(); override.forEach((k, v) -> overrideSet.add(wrap(k, v))); return wrap(constructor, overrideSet); } - + public static ConstructableFeature wrap(DefinedFeature constructor, DefinedFeature... override) { Set overrideSet = new HashSet<>(); for (DefinedFeature overrideFeature : override) { overrideSet.add(wrap(overrideFeature)); } - + return wrap(constructor, overrideSet); } - + public static ConstructableFeature wrap(DefinedFeature constructor, Set override) { Map, ConstructableFeature> overrideMap = new HashMap<>(); - + for (ConstructableFeature overrideFeature : override) { overrideMap.put(overrideFeature.type, overrideFeature); - + if (!constructor.dependencies().contains(overrideFeature.type)) throw new RuntimeException("Feature " + constructor.featureType().name() + " does not require a " + overrideFeature.type.name() + " feature"); } - + return new LazyFeatureInit(constructor, overrideMap); } - + /** * Resolves all the dependencies and turns this configuration into a {@link CombatFeatureSet}. * @@ -147,66 +161,66 @@ public static ConstructableFeature wrap(DefinedFeature constructor, Set buildOrder = getBuildOrder(); - + for (ConstructableFeature feature : features.values()) { CombatFeature currentResult = feature.construct(result); result.add(feature.type, currentResult); } - + result.initDependencies(); - + return result; } - + private @Nullable ConstructableFeature getFeatureOf(FeatureType type) { return features.get(type); } - + public sealed abstract static class ConstructableFeature { private final FeatureType type; - + public ConstructableFeature(FeatureType type) { this.type = type; } - + abstract CombatFeature construct(FeatureConfiguration configuration); } - + private static final class ConstructedFeature extends ConstructableFeature { private final CombatFeature feature; - + private ConstructedFeature(FeatureType type, CombatFeature feature) { super(type); this.feature = feature; } - + @Override CombatFeature construct(FeatureConfiguration configuration) { return feature; } } - + private static final class LazyFeatureInit extends ConstructableFeature { private final DefinedFeature constructor; private final Map, ConstructableFeature> override; - + public LazyFeatureInit(DefinedFeature constructor, Map, ConstructableFeature> override) { super(constructor.featureType()); this.constructor = constructor; this.override = override; } - + public @Nullable ConstructableFeature getOverrideOf(FeatureType featureType) { return override.get(featureType); } - + @Override CombatFeature construct(FeatureConfiguration configuration) { FeatureConfiguration local = configuration.overlay(); override.forEach((k, v) -> local.add(k, v.construct(configuration))); - + return constructor.construct(local); } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/config/DefinedFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/config/DefinedFeature.java index daaf2dd88..2959a5449 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/config/DefinedFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/config/DefinedFeature.java @@ -1,8 +1,8 @@ package net.swofty.pvp.feature.config; +import net.minestom.server.entity.Player; import net.swofty.pvp.feature.CombatFeature; import net.swofty.pvp.feature.FeatureType; -import net.minestom.server.entity.Player; import org.jetbrains.annotations.Nullable; import java.util.Set; @@ -26,12 +26,12 @@ public class DefinedFeature { private final Set> dependencies; private final Constructor constructor; private final PlayerInit playerInit; - + public DefinedFeature(FeatureType featureType, Constructor constructor, FeatureType... dependencies) { this(featureType, constructor, null, dependencies); } - + public DefinedFeature(FeatureType featureType, Constructor constructor, @Nullable PlayerInit playerInit, FeatureType... dependencies) { this.featureType = featureType; @@ -39,30 +39,30 @@ public DefinedFeature(FeatureType featureType, Constructor constru this.constructor = constructor; this.playerInit = playerInit; } - + public F construct(FeatureConfiguration configuration) { // Registers player init CombatFeatureRegistry.init(this); return constructor.construct(configuration); } - + public FeatureType featureType() { return featureType; } - + public Set> dependencies() { return dependencies; } - + @Nullable PlayerInit playerInit() { return playerInit; } - + @FunctionalInterface public interface Constructor { F construct(FeatureConfiguration configuration); } - + @FunctionalInterface public interface PlayerInit { void init(Player player, boolean firstInit); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/config/FeatureConfiguration.java b/pvp/src/main/java/net/swofty/pvp/feature/config/FeatureConfiguration.java index ac616f4f9..5ce041697 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/config/FeatureConfiguration.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/config/FeatureConfiguration.java @@ -18,9 +18,9 @@ */ public class FeatureConfiguration { protected final Map, CombatFeature> combatFeatures = new HashMap<>(); - + public FeatureConfiguration() {} - + /** * Adds the specified feature as the specified type to this configuration. * This WILL overwrite any previous feature associated with the specified type. @@ -36,7 +36,7 @@ public FeatureConfiguration add(FeatureType type, CombatFeature feature) { combatFeatures.put(type, feature); return this; } - + /** * Gets the feature which has been associated with the specified type in this configuration. * If there is none present, the default feature for this type will be returned. @@ -49,7 +49,7 @@ public FeatureConfiguration add(FeatureType type, CombatFeature feature) { public @NotNull T get(FeatureType type) { return (T) combatFeatures.getOrDefault(type, type.defaultFeature()); } - + /** * Gets the feature which has been associated with the specified type in this configuration. * Will yield null if there is no associated feature. @@ -62,34 +62,34 @@ public FeatureConfiguration add(FeatureType type, CombatFeature feature) { @Nullable T getDirect(FeatureType type) { return (T) combatFeatures.get(type); } - + public Collection listFeatures() { return combatFeatures.values(); } - + public Set> listTypes() { return combatFeatures.keySet(); } - + public int size() { return combatFeatures.size(); } - + void forEach(BiConsumer, CombatFeature> consumer) { combatFeatures.forEach(consumer); } - + FeatureConfiguration overlay() { return new Overlay(this); } - + private static class Overlay extends FeatureConfiguration { private final FeatureConfiguration backing; - + public Overlay(FeatureConfiguration backing) { this.backing = backing; } - + @Override public @NotNull T get(FeatureType type) { if (super.combatFeatures.containsKey(type)) { @@ -99,19 +99,19 @@ public Overlay(FeatureConfiguration backing) { } } } - + public static FeatureConfiguration of(FeatureType type1, CombatFeature feature1) { return new FeatureConfiguration() .add(type1, feature1); } - + public static FeatureConfiguration of(FeatureType type1, CombatFeature feature1, FeatureType type2, CombatFeature feature2) { return new FeatureConfiguration() .add(type1, feature1) .add(type2, feature2); } - + public static FeatureConfiguration of(FeatureType type1, CombatFeature feature1, FeatureType type2, CombatFeature feature2, FeatureType type3, CombatFeature feature3) { @@ -120,7 +120,7 @@ public static FeatureConfiguration of(FeatureType type1, CombatFeature featur .add(type2, feature2) .add(type3, feature3); } - + public static FeatureConfiguration of(FeatureType type1, CombatFeature feature1, FeatureType type2, CombatFeature feature2, FeatureType type3, CombatFeature feature3, diff --git a/pvp/src/main/java/net/swofty/pvp/feature/cooldown/ItemCooldownFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/cooldown/ItemCooldownFeature.java index 2a0c47945..19a46efc9 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/cooldown/ItemCooldownFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/cooldown/ItemCooldownFeature.java @@ -1,8 +1,8 @@ package net.swofty.pvp.feature.cooldown; -import net.swofty.pvp.feature.CombatFeature; import net.minestom.server.entity.Player; -import net.minestom.server.item.Material; +import net.minestom.server.item.ItemStack; +import net.swofty.pvp.feature.CombatFeature; /** * Combat feature to manage a players item cooldown animation. @@ -10,15 +10,37 @@ public interface ItemCooldownFeature extends CombatFeature { ItemCooldownFeature NO_OP = new ItemCooldownFeature() { @Override - public boolean hasCooldown(Player player, Material material) { + public boolean hasCooldown(Player player, String cooldownGroup) { return false; } - + @Override - public void setCooldown(Player player, Material material, int ticks) {} + public boolean hasCooldown(Player player, ItemStack itemStack) { + return false; + } + + @Override + public void setCooldown(Player player, String cooldownGroup, int ticks) { + } + + @Override + public void setCooldown(Player player, ItemStack itemStack, int ticks) { + + } + + @Override + public void setCooldown(Player player, ItemStack itemStack) { + + } }; - - boolean hasCooldown(Player player, Material material); - - void setCooldown(Player player, Material material, int ticks); + + boolean hasCooldown(Player player, String cooldownGroup); + + boolean hasCooldown(Player player, ItemStack itemStack); + + void setCooldown(Player player, String cooldownGroup, int ticks); + + void setCooldown(Player player, ItemStack itemStack, int ticks); + + void setCooldown(Player player, ItemStack itemStack); } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaAttackCooldownFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaAttackCooldownFeature.java index fb36aa538..a3fe29882 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaAttackCooldownFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaAttackCooldownFeature.java @@ -1,10 +1,5 @@ package net.swofty.pvp.feature.cooldown; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.utils.CombatVersion; import net.minestom.server.entity.Player; import net.minestom.server.entity.attribute.Attribute; import net.minestom.server.event.EventListener; @@ -14,6 +9,11 @@ import net.minestom.server.event.trait.EntityInstanceEvent; import net.minestom.server.tag.Tag; import net.minestom.server.utils.MathUtils; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.utils.CombatVersion; /** * Vanilla implementation of {@link AttackCooldownFeature} @@ -23,26 +23,26 @@ public class VanillaAttackCooldownFeature implements AttackCooldownFeature, Regi FeatureType.ATTACK_COOLDOWN, VanillaAttackCooldownFeature::new, FeatureType.VERSION ); - + public static final Tag LAST_ATTACKED_TICKS = Tag.Long("lastAttackedTicks"); - + private final FeatureConfiguration configuration; private CombatVersion version; - + public VanillaAttackCooldownFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.version = configuration.get(FeatureType.VERSION); } - + @Override public void init(EventNode node) { node.addListener(EventListener.builder(PlayerHandAnimationEvent.class).handler(event -> resetCooldownProgress(event.getPlayer())).build()); - + node.addListener(EventListener.builder(PlayerChangeHeldSlotEvent.class).handler(event -> { if (!event.getPlayer().getItemInMainHand() .isSimilar(event.getPlayer().getInventory().getItemStack(event.getNewSlot()))) { @@ -50,26 +50,26 @@ public void init(EventNode node) { } }).build()); } - + @Override public void resetCooldownProgress(Player player) { player.setTag(LAST_ATTACKED_TICKS, player.getAliveTicks()); } - + @Override public double getAttackCooldownProgress(Player player) { if (version.legacy()) return 1.0; - + Long lastAttacked = player.getTag(LAST_ATTACKED_TICKS); if (lastAttacked == null) return 1.0; - + long timeSinceLastAttacked = player.getAliveTicks() - lastAttacked; return MathUtils.clamp( (timeSinceLastAttacked + 0.5) / getAttackCooldownProgressPerTick(player), 0, 1 ); } - + protected double getAttackCooldownProgressPerTick(Player player) { return (1 / player.getAttributeValue(Attribute.ATTACK_SPEED)) * 20; } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaItemCooldownFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaItemCooldownFeature.java index 04ac4d573..c0403c482 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaItemCooldownFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/cooldown/VanillaItemCooldownFeature.java @@ -1,17 +1,19 @@ package net.swofty.pvp.feature.cooldown; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; import net.minestom.server.MinecraftServer; +import net.minestom.server.component.DataComponents; import net.minestom.server.entity.Player; import net.minestom.server.event.EventNode; import net.minestom.server.event.player.PlayerTickEvent; import net.minestom.server.event.player.PlayerUseItemEvent; import net.minestom.server.event.trait.EntityInstanceEvent; -import net.minestom.server.item.Material; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.component.UseCooldown; import net.minestom.server.network.packet.server.play.SetCooldownPacket; import net.minestom.server.tag.Tag; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; import java.util.HashMap; import java.util.Iterator; @@ -22,11 +24,11 @@ */ public class VanillaItemCooldownFeature implements ItemCooldownFeature, RegistrableFeature { public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.ITEM_COOLDOWN, configuration -> new VanillaItemCooldownFeature(), + FeatureType.ITEM_COOLDOWN, _ -> new VanillaItemCooldownFeature(), VanillaItemCooldownFeature::initPlayer ); - public static final Tag> COOLDOWN_END = Tag.Transient("cooldownEnd"); + public static final Tag> COOLDOWN_END = Tag.Transient("cooldownEnd"); private static void initPlayer(Player player, boolean firstInit) { player.setTag(COOLDOWN_END, new HashMap<>()); @@ -42,14 +44,14 @@ public int getPriority() { public void init(EventNode node) { node.addListener(PlayerTickEvent.class, event -> { Player player = event.getPlayer(); - Map cooldown = player.getTag(COOLDOWN_END); + Map cooldown = player.getTag(COOLDOWN_END); if (cooldown == null || cooldown.isEmpty()) return; long time = System.currentTimeMillis(); - Iterator> iterator = cooldown.entrySet().iterator(); + Iterator> iterator = cooldown.entrySet().iterator(); while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); + Map.Entry entry = iterator.next(); if (entry.getValue() <= time) { iterator.remove(); sendCooldownPacket(player, entry.getKey(), 0); @@ -58,25 +60,57 @@ public void init(EventNode node) { }); node.addListener(PlayerUseItemEvent.class, event -> { - if (hasCooldown(event.getPlayer(), event.getItemStack().material())) + ItemStack stack = event.getItemStack(); + UseCooldown useCooldown = stack.get(DataComponents.USE_COOLDOWN); + + String cooldownGroup = useCooldown != null && useCooldown.cooldownGroup() != null + ? useCooldown.cooldownGroup() + : stack.material().name(); + + if (hasCooldown(event.getPlayer(), cooldownGroup)) event.setCancelled(true); }); } @Override - public boolean hasCooldown(Player player, Material material) { - Map cooldown = player.getTag(COOLDOWN_END); - return cooldown.containsKey(material) && cooldown.get(material) > System.currentTimeMillis(); + public boolean hasCooldown(Player player, String cooldownGroup) { + Map cooldown = player.getTag(COOLDOWN_END); + return cooldown.containsKey(cooldownGroup) && cooldown.get(cooldownGroup) > System.currentTimeMillis(); + } + + @Override + public boolean hasCooldown(Player player, ItemStack itemStack) { + UseCooldown useCooldown = itemStack.get(DataComponents.USE_COOLDOWN); + String cooldownGroup = useCooldown != null && useCooldown.cooldownGroup() != null + ? useCooldown.cooldownGroup() + : itemStack.material().name(); + return hasCooldown(player, cooldownGroup); + } + + @Override + public void setCooldown(Player player, String cooldownGroup, int ticks) { + Map cooldown = player.getTag(COOLDOWN_END); + cooldown.put(cooldownGroup, System.currentTimeMillis() + (long) ticks * MinecraftServer.TICK_MS); + sendCooldownPacket(player, cooldownGroup, ticks); + } + + @Override + public void setCooldown(Player player, ItemStack itemStack, int ticks) { + UseCooldown useCooldown = itemStack.get(DataComponents.USE_COOLDOWN); + String cooldownGroup = useCooldown != null && useCooldown.cooldownGroup() != null + ? useCooldown.cooldownGroup() + : itemStack.material().name(); + setCooldown(player, cooldownGroup, ticks); } @Override - public void setCooldown(Player player, Material material, int ticks) { - Map cooldown = player.getTag(COOLDOWN_END); - cooldown.put(material, System.currentTimeMillis() + (long) ticks * MinecraftServer.TICK_MS); - sendCooldownPacket(player, material, ticks); + public void setCooldown(Player player, ItemStack itemStack) { + UseCooldown useCooldown = itemStack.get(DataComponents.USE_COOLDOWN); + int ticks = useCooldown != null ? (int) useCooldown.seconds() * 20 : 0; + setCooldown(player, itemStack, ticks); } - protected void sendCooldownPacket(Player player, Material material, int ticks) { - player.getPlayerConnection().sendPacket(new SetCooldownPacket(material.key().asString(), ticks)); + protected void sendCooldownPacket(Player player, String cooldownGroup, int ticks) { + player.getPlayerConnection().sendPacket(new SetCooldownPacket(cooldownGroup, ticks)); } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/effect/EffectFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/effect/EffectFeature.java index ad64e32e2..1808c6c5a 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/effect/EffectFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/effect/EffectFeature.java @@ -1,13 +1,13 @@ package net.swofty.pvp.feature.effect; -import net.swofty.pvp.entity.projectile.Arrow; -import net.swofty.pvp.feature.CombatFeature; import net.minestom.server.entity.Entity; import net.minestom.server.entity.LivingEntity; import net.minestom.server.item.component.PotionContents; import net.minestom.server.potion.CustomPotionEffect; import net.minestom.server.potion.Potion; import net.minestom.server.potion.PotionType; +import net.swofty.pvp.entity.projectile.Arrow; +import net.swofty.pvp.feature.CombatFeature; import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -22,34 +22,39 @@ public interface EffectFeature extends CombatFeature { public int getPotionColor(PotionContents contents) { return 0; } - + @Override public List getAllPotions(PotionType potionType, Collection customEffects) { return List.of(); } - + @Override public void updatePotionVisibility(LivingEntity entity) {} @Override public void addArrowEffects(LivingEntity entity, Arrow arrow) {} @Override public void addSplashPotionEffects(LivingEntity entity, PotionContents potionContents, double proximity, @Nullable Entity source, @Nullable Entity attacker) {} + + @Override + public void addLingeringPotionEffects(LivingEntity entity, PotionContents potionContents, + @Nullable Entity source, @Nullable Entity attacker) { + } }; - + int getPotionColor(PotionContents contents); - + default List getAllPotions(@Nullable PotionContents potionContents) { if (potionContents == null) return List.of(); return getAllPotions(potionContents.potion(), potionContents.customEffects()); } - + List getAllPotions(PotionType potionType, Collection customEffects); - + /** * Updates the potion visibility of an entity. This includes particles and invisibility status. * * @param entity the entity to update the potion visibility of */ void updatePotionVisibility(LivingEntity entity); - + /** * Applies the effects of a (tipped) arrow to an entity. * @@ -57,7 +62,7 @@ default List getAllPotions(@Nullable PotionContents potionContents) { * @param arrow the arrow */ void addArrowEffects(LivingEntity entity, Arrow arrow); - + /** * Applies the effects of a splash potion to an entity. * The proximity is usually calculated following: {@code 1.0 - Math.sqrt(distanceSquared) / 4.0} @@ -70,4 +75,15 @@ default List getAllPotions(@Nullable PotionContents potionContents) { */ void addSplashPotionEffects(LivingEntity entity, PotionContents potionContents, double proximity, @Nullable Entity source, @Nullable Entity attacker); + + /** + * Applies the effects of a lingering potion to an entity. + * + * @param entity the entity which is in the area effect cloud + * @param potionContents the potion contents of the lingering potion + * @param source the direct source of the area effect cloud (usually the area effect cloud) + * @param attacker the attacker of the area effect cloud (usually the thrower) + */ + void addLingeringPotionEffects(LivingEntity entity, PotionContents potionContents, @Nullable Entity source, + @Nullable Entity attacker); } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/effect/VanillaEffectFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/effect/VanillaEffectFeature.java index aeab05221..165d0423f 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/effect/VanillaEffectFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/effect/VanillaEffectFeature.java @@ -1,19 +1,5 @@ package net.swofty.pvp.feature.effect; -import net.swofty.pvp.entity.projectile.Arrow; -import net.swofty.pvp.events.PotionVisibilityEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.food.ExhaustionFeature; -import net.swofty.pvp.feature.food.FoodFeature; -import net.swofty.pvp.potion.effect.CombatPotionEffect; -import net.swofty.pvp.potion.effect.CombatPotionEffects; -import net.swofty.pvp.potion.item.CombatPotionType; -import net.swofty.pvp.potion.item.CombatPotionTypes; -import net.swofty.pvp.utils.CombatVersion; -import net.swofty.pvp.utils.PotionFlags; import net.kyori.adventure.util.RGBLike; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Entity; @@ -36,9 +22,27 @@ import net.minestom.server.potion.TimedPotion; import net.minestom.server.tag.Tag; import net.minestom.server.utils.time.TimeUnit; +import net.swofty.pvp.entity.projectile.Arrow; +import net.swofty.pvp.events.PotionVisibilityEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.food.ExhaustionFeature; +import net.swofty.pvp.feature.food.FoodFeature; +import net.swofty.pvp.potion.effect.CombatPotionEffect; +import net.swofty.pvp.potion.effect.CombatPotionEffects; +import net.swofty.pvp.potion.item.CombatPotionType; +import net.swofty.pvp.potion.item.CombatPotionTypes; +import net.swofty.pvp.utils.CombatVersion; +import net.swofty.pvp.utils.PotionFlags; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; /** @@ -49,80 +53,80 @@ public class VanillaEffectFeature implements EffectFeature, RegistrableFeature { FeatureType.EFFECT, VanillaEffectFeature::new, FeatureType.EXHAUSTION, FeatureType.FOOD, FeatureType.VERSION ); - + public static final Tag> DURATION_LEFT = Tag.Transient("effectDurationLeft"); public static final int DEFAULT_POTION_COLOR = 0xff385dc6; - + private final FeatureConfiguration configuration; - + private ExhaustionFeature exhaustionFeature; private FoodFeature foodFeature; private CombatVersion version; - + public VanillaEffectFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.exhaustionFeature = configuration.get(FeatureType.EXHAUSTION); this.foodFeature = configuration.get(FeatureType.FOOD); this.version = configuration.get(FeatureType.VERSION); } - + @Override public void init(EventNode node) { node.addListener(EntityDeathEvent.class, event -> event.getEntity().clearEffects()); - + node.addListener(EntityTickEvent.class, event -> { if (!(event.getEntity() instanceof LivingEntity entity)) return; Map potionMap = getDurationLeftMap(entity); - + for (TimedPotion potion : entity.getActiveEffects()) { potionMap.putIfAbsent(potion.potion().effect(), potion.potion().duration() - 1); int durationLeft = potionMap.get(potion.potion().effect()); - + if (durationLeft > 0) { CombatPotionEffect combatPotionEffect = CombatPotionEffects.get(potion.potion().effect()); int amplifier = potion.potion().amplifier(); - + if (combatPotionEffect.canApplyUpdateEffect(durationLeft, amplifier)) { combatPotionEffect.applyUpdateEffect(entity, amplifier, exhaustionFeature, foodFeature); } - + potionMap.put(potion.potion().effect(), durationLeft - 1); } } - + if (entity instanceof Player player && player.hasEffect(PotionEffect.ABSORPTION) && player.getAdditionalHearts() <= 0) { player.removeEffect(PotionEffect.ABSORPTION); } - + //TODO keep track of underlying potions with longer duration if (potionMap.size() != entity.getActiveEffects().size()) { potionMap.keySet().removeIf(effect -> !entity.hasEffect(effect)); } }); - + node.addListener(EntityPotionAddEvent.class, event -> { if (!(event.getEntity() instanceof LivingEntity entity)) return; Map potionMap = getDurationLeftMap(entity); boolean infinite = event.getPotion().duration() == Potion.INFINITE_DURATION; potionMap.put(event.getPotion().effect(), infinite ? Integer.MAX_VALUE : event.getPotion().duration()); - + CombatPotionEffect combatPotionEffect = CombatPotionEffects.get(event.getPotion().effect()); combatPotionEffect.onApplied(entity, event.getPotion().amplifier(), version); - + updatePotionVisibility(entity); }); - + node.addListener(EntityPotionRemoveEvent.class, event -> { if (!(event.getEntity() instanceof LivingEntity entity)) return; - + CombatPotionEffect combatPotionEffect = CombatPotionEffects.get(event.getPotion().effect()); combatPotionEffect.onRemoved(entity, event.getPotion().amplifier(), version); - + //Delay update 1 tick because we need to have the removing effect removed MinecraftServer.getSchedulerManager() .buildTask(() -> updatePotionVisibility(entity)) @@ -130,7 +134,7 @@ public void init(EventNode node) { .schedule(); }); } - + private Map getDurationLeftMap(Entity entity) { Map potionMap = entity.getTag(DURATION_LEFT); if (potionMap == null) { @@ -139,7 +143,7 @@ private Map getDurationLeftMap(Entity entity) { } return potionMap; } - + @Override public int getPotionColor(PotionContents contents) { if (contents.customColor() != null) { @@ -153,16 +157,16 @@ public int getPotionColor(PotionContents contents) { return color == -1 ? DEFAULT_POTION_COLOR : color; } } - + @Override public List getAllPotions(PotionType potionType, Collection customEffects) { // PotionType effects plus custom effects List potions = new ArrayList<>(); - + CombatPotionType combatPotionType = CombatPotionTypes.get(potionType); if (combatPotionType != null) potions.addAll(combatPotionType.getEffects(version)); - + potions.addAll(customEffects.stream().map((customPotion) -> new Potion(Objects.requireNonNull(customPotion.id()), (byte)customPotion.amplifier(), customPotion.duration(), @@ -171,16 +175,16 @@ public List getAllPotions(PotionType potionType, customPotion.showParticles(), customPotion.showIcon() ))).toList()); - + return potions; } - + @Override public void updatePotionVisibility(LivingEntity entity) { boolean ambient; List particles; boolean invisible; - + if (entity instanceof Player player && player.getGameMode() == GameMode.SPECTATOR) { ambient = false; particles = List.of(); @@ -194,36 +198,36 @@ public void updatePotionVisibility(LivingEntity entity) { } else { ambient = true; particles = new ArrayList<>(); - + for (TimedPotion potion : effects) { if (!potion.potion().isAmbient()) { ambient = false; } - + if (potion.potion().hasParticles()) { CombatPotionEffect effect = CombatPotionEffects.get(potion.potion().effect()); particles.add(effect.getParticle(potion.potion())); } } - + invisible = entity.hasEffect(PotionEffect.INVISIBILITY); } } - + PotionVisibilityEvent potionVisibilityEvent = new PotionVisibilityEvent(entity, ambient, particles, invisible); EventDispatcher.callCancellable(potionVisibilityEvent, () -> { LivingEntityMeta meta = (LivingEntityMeta) entity.getEntityMeta(); - + meta.setPotionEffectAmbient(potionVisibilityEvent.isAmbient()); meta.setEffectParticles(potionVisibilityEvent.getParticles()); meta.setInvisible(potionVisibilityEvent.isInvisible()); }); } - + @Override public void addArrowEffects(LivingEntity entity, Arrow arrow) { PotionContents potionContents = arrow.getPotion(); - + CombatPotionType combatPotionType = CombatPotionTypes.get(potionContents.potion()); if (combatPotionType != null) { for (Potion potion : combatPotionType.getEffects(version)) { @@ -237,9 +241,9 @@ public void addArrowEffects(LivingEntity entity, Arrow arrow) { } } } - + if (potionContents.customEffects().isEmpty()) return; - + potionContents.customEffects().stream().map(customPotion -> new Potion(Objects.requireNonNull(customPotion.id()), (byte)customPotion.amplifier(), customPotion.duration(), @@ -254,12 +258,13 @@ public void addArrowEffects(LivingEntity entity, Arrow arrow) { combatPotionEffect.applyInstantEffect(arrow, null, entity, potion.amplifier(), 1.0, exhaustionFeature, foodFeature); } else { + int duration = Math.max(potion.duration() / 8, 1); entity.addEffect(new Potion(potion.effect(), potion.amplifier(), - potion.duration(), potion.flags())); + duration, potion.flags())); } }); } - + @Override public void addSplashPotionEffects(LivingEntity entity, PotionContents potionContents, double proximity, @Nullable Entity source, @Nullable Entity attacker) { @@ -272,11 +277,25 @@ public void addSplashPotionEffects(LivingEntity entity, PotionContents potionCon int duration = potion.duration(); if (version.legacy()) duration = (int) Math.floor(duration * 0.75); duration = (int) (proximity * (double) duration + 0.5); - + if (duration > 20) { entity.addEffect(new Potion(potion.effect(), potion.amplifier(), duration, potion.flags())); } } } } + + @Override + public void addLingeringPotionEffects(LivingEntity entity, PotionContents potionContents, @Nullable Entity source, @Nullable Entity attacker) { + for (Potion potion : getAllPotions(potionContents)) { + CombatPotionEffect combatPotionEffect = CombatPotionEffects.get(potion.effect()); + if (combatPotionEffect.isInstant()) { + combatPotionEffect.applyInstantEffect(source, attacker, + entity, potion.amplifier(), 0.5, exhaustionFeature, foodFeature); + } else { + int duration = potion.duration() / 4; + entity.addEffect(new Potion(potion.effect(), potion.amplifier(), duration, potion.flags())); + } + } + } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosionFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosionFeature.java index e4e7bf586..6b5e8d69c 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosionFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosionFeature.java @@ -1,15 +1,15 @@ package net.swofty.pvp.feature.explosion; -import net.swofty.pvp.entity.explosion.TntEntity; -import net.swofty.pvp.events.ExplosivePrimeEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; import net.kyori.adventure.sound.Sound; import net.minestom.server.coordinate.Point; import net.minestom.server.event.EventDispatcher; import net.minestom.server.instance.Instance; import net.minestom.server.sound.SoundEvent; +import net.swofty.pvp.entity.explosion.TntEntity; +import net.swofty.pvp.events.ExplosivePrimeEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; import org.jetbrains.annotations.NotNull; /** @@ -23,25 +23,25 @@ public class VanillaExplosionFeature implements ExplosionFeature { FeatureType.EXPLOSION, VanillaExplosionFeature::new, FeatureType.ENCHANTMENT ); - + private final FeatureConfiguration configuration; - + private VanillaExplosionSupplier explosionSupplier; - + public VanillaExplosionFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.explosionSupplier = new VanillaExplosionSupplier(this, configuration.get(FeatureType.ENCHANTMENT)); } - + @Override public VanillaExplosionSupplier getExplosionSupplier() { return explosionSupplier; } - + @Override public void primeExplosive(Instance instance, Point blockPosition, @NotNull IgnitionCause cause, int fuse) { ExplosivePrimeEvent event = new ExplosivePrimeEvent(instance, blockPosition, cause, fuse); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosiveFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosiveFeature.java index 04cc0e366..e081766b4 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosiveFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/explosion/VanillaExplosiveFeature.java @@ -4,7 +4,11 @@ import net.kyori.adventure.sound.Sound; import net.minestom.server.collision.BoundingBox; import net.minestom.server.coordinate.Point; -import net.minestom.server.entity.*; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EquipmentSlot; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.PlayerHand; import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.EventNode; import net.minestom.server.event.player.PlayerBlockInteractEvent; @@ -34,22 +38,22 @@ public class VanillaExplosiveFeature implements ExplosiveFeature, RegistrableFea FeatureType.EXPLOSIVE, VanillaExplosiveFeature::new, FeatureType.EXPLOSION, FeatureType.ITEM_DAMAGE ); - + private final FeatureConfiguration configuration; - + private ExplosionFeature explosionFeature; private ItemDamageFeature itemDamageFeature; - + public VanillaExplosiveFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.explosionFeature = configuration.get(FeatureType.EXPLOSION); this.itemDamageFeature = configuration.get(FeatureType.ITEM_DAMAGE); } - + @Override public void init(EventNode node) { node.addListener(PlayerUseItemOnBlockEvent.class, event -> { @@ -57,14 +61,14 @@ public void init(EventNode node) { Instance instance = event.getInstance(); Point position = event.getPosition(); Player player = event.getPlayer(); - + if (stack.material() != Material.FLINT_AND_STEEL && stack.material() != Material.FIRE_CHARGE) return; Block block = instance.getBlock(position); if (!block.compare(Block.TNT)) return; - + explosionFeature.primeExplosive(instance, position, new ExplosionFeature.IgnitionCause.ByPlayer(player), 80); instance.setBlock(position, Block.AIR); - + if (player.getGameMode() != GameMode.CREATIVE) { if (stack.material() == Material.FLINT_AND_STEEL) { itemDamageFeature.damageEquipment(player, event.getHand() == PlayerHand.MAIN @@ -74,51 +78,51 @@ public void init(EventNode node) { } } }); - + node.addListener(PlayerUseItemOnBlockEvent.class, event -> { if (event.getItemStack().material() != Material.END_CRYSTAL) return; Instance instance = event.getInstance(); Block block = instance.getBlock(event.getPosition()); if (!block.compare(Block.OBSIDIAN) && !block.compare(Block.BEDROCK)) return; - + Point above = event.getPosition().add(0, 1, 0); if (!instance.getBlock(above).isAir()) return; - + BoundingBox checkIntersect = new BoundingBox(1, 2, 1); for (Entity entity : instance.getNearbyEntities(above, 3)) { if (entity.getBoundingBox().intersectBox(above.sub(entity.getPosition()), checkIntersect)) return; } - + Point spawnPosition = above.add(0.5, 0, 0.5); var crystalPlaceEvent = new CrystalPlaceEvent(event.getPlayer(), spawnPosition); - + EventDispatcher.callCancellable(crystalPlaceEvent, () -> { CrystalEntity entity = new CrystalEntity(); entity.setInstance(instance, crystalPlaceEvent.getSpawnPosition()); - + if (event.getPlayer().getGameMode() != GameMode.CREATIVE) event.getPlayer().setItemInHand(event.getHand(), event.getItemStack().consume(1)); }); }); - + node.addListener(PlayerBlockInteractEvent.class, event -> { Instance instance = event.getInstance(); Block block = instance.getBlock(event.getBlockPosition()); Player player = event.getPlayer(); if (!block.compare(Block.RESPAWN_ANCHOR)) return; - + // Exit if offhand has glowstone but current hand is main, to prevent exploding when it should be charged instead if (event.getHand() == PlayerHand.MAIN && player.getItemInMainHand().material() != Material.GLOWSTONE && player.getItemInOffHand().material() == Material.GLOWSTONE) return; - + ItemStack stack = player.getItemInHand(event.getHand()); int charges = Integer.parseInt(block.getProperty("charges")); if (stack.material() == Material.GLOWSTONE && charges < 4) { var anchorChargeEvent = new AnchorChargeEvent(player, event.getBlockPosition()); EventDispatcher.call(anchorChargeEvent); - + if (!anchorChargeEvent.isCancelled()) { instance.setBlock(event.getBlockPosition(), block.withProperty("charges", String.valueOf(charges + 1))); @@ -126,17 +130,17 @@ public void init(EventNode node) { SoundEvent.BLOCK_RESPAWN_ANCHOR_CHARGE, Sound.Source.BLOCK, 1.0f, 1.0f ), event.getBlockPosition().add(0.5, 0.5, 0.5)); - + if (player.getGameMode() != GameMode.CREATIVE) player.setItemInHand(event.getHand(), player.getItemInHand(event.getHand()).consume(1)); - + event.setBlockingItemUse(true); return; } } - + if (charges == 0) return; - + if (instance.getExplosionSupplier() != null) { var anchorExplodeEvent = new AnchorExplodeEvent(player, event.getBlockPosition()); EventDispatcher.callCancellable(anchorExplodeEvent, () -> { @@ -151,9 +155,14 @@ public void init(EventNode node) { .putBoolean("anchor", true) .build() ); + if (event.getHand() == PlayerHand.MAIN) { + player.swingMainHand(); + } else { + player.swingOffHand(); + } }); } - + event.setBlockingItemUse(true); }); } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/fall/VanillaFallFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/fall/VanillaFallFeature.java index 98e704bc8..26c5d88e1 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/fall/VanillaFallFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/fall/VanillaFallFeature.java @@ -26,187 +26,204 @@ import net.swofty.pvp.feature.RegistrableFeature; import net.swofty.pvp.feature.config.DefinedFeature; import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.provider.PacketProvider; +import net.swofty.pvp.feature.provider.SoundProvider; import net.swofty.pvp.feature.state.PlayerStateFeature; /** * Vanilla implementation of {@link FallFeature} */ public class VanillaFallFeature implements FallFeature, RegistrableFeature { - public static final Tag FALL_DISTANCE = Tag.Transient("fallDistance"); - public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.FALL, VanillaFallFeature::new, - VanillaFallFeature::initPlayer, - FeatureType.PLAYER_STATE - ); - public static final Tag EXTRA_FALL_PARTICLES = Tag.Transient("extraFallParticles"); - - private final FeatureConfiguration configuration; - - private PlayerStateFeature playerStateFeature; - - public VanillaFallFeature(FeatureConfiguration configuration) { - this.configuration = configuration; - } - - public static void initPlayer(Player player, boolean firstInit) { - player.setTag(FALL_DISTANCE, 0.0); - } - - @Override - public void initDependencies() { - this.playerStateFeature = configuration.get(FeatureType.PLAYER_STATE); - } - - @Override - public void init(EventNode node) { - // For living non-player entities, handle fall damage every tick - node.addListener(EntityTickEvent.class, event -> { - if (!(event.getEntity() instanceof LivingEntity livingEntity)) return; - if (livingEntity instanceof Player) return; - - Pos previousPosition = livingEntity.getPreviousPosition(); - handleFallDamage(livingEntity, previousPosition, livingEntity.getPosition(), livingEntity.isOnGround()); - }); - - // For players, handle fall damage on move event - node.addListener(PlayerMoveEvent.class, event -> { - Player player = event.getPlayer(); - if (playerStateFeature.isClimbing(player)) player.setTag(FALL_DISTANCE, 0.0); - - handleFallDamage( - player, player.getPosition(), - event.getNewPosition(), event.isOnGround() - ); - }); - } - - public void handleFallDamage(LivingEntity entity, Pos currPos, Pos newPos, boolean onGround) { - double dy = newPos.y() - currPos.y(); - double fallDistance = getFallDistance(entity); - - if ((entity instanceof Player player && player.isFlying()) - || entity.hasEffect(PotionEffect.LEVITATION) - || entity.hasEffect(PotionEffect.SLOW_FALLING) || dy > 0) { - entity.setTag(FALL_DISTANCE, 0.0); - return; - } - - if (entity.isFlyingWithElytra() && entity.getVelocity().y() > -0.5) { - entity.setTag(FALL_DISTANCE, 1.0); - return; - } - - if (!onGround) { - if (dy < 0) entity.setTag(FALL_DISTANCE, fallDistance - dy); - return; - } - - Point landingPos = getLandingPos(entity, newPos); - Block block = entity.getInstance().getBlock(landingPos); - - if (entity.hasTag(EXTRA_FALL_PARTICLES) && entity.getTag(EXTRA_FALL_PARTICLES) && fallDistance > 0.0) { - Vec position = Vec.fromPoint(landingPos).apply(Vec.Operator.FLOOR).add(0.5, 1, 0.5); - int particleCount = (int) Math.max(0, Math.min(200, 50 * fallDistance)); - - entity.sendPacketToViewersAndSelf(new ParticlePacket( - Particle.BLOCK.withBlock(block), - position.x(), position.y(), position.z(), - 0.3f, 0.3f, 0.3f, - 0.15f, particleCount - )); - - entity.removeTag(EXTRA_FALL_PARTICLES); - } - - double safeFallDistance = entity.getAttributeValue(Attribute.SAFE_FALL_DISTANCE); - if (fallDistance > safeFallDistance) { - if (!block.isAir()) { - double damageDistance = Math.ceil(fallDistance - safeFallDistance); - double particleMultiplier = Math.min(0.2 + damageDistance / 15.0, 2.5); - int particleCount = (int) (150 * particleMultiplier); - - entity.sendPacketToViewersAndSelf(new ParticlePacket( - Particle.BLOCK.withBlock(block), false, - false, - newPos.x(), newPos.y(), newPos.z(), - 0, 0, 0, - 0.15f, particleCount - )); - } - } - - entity.setTag(FALL_DISTANCE, 0.0); - - if (entity instanceof Player player && player.getGameMode().invulnerable()) return; - int damage = getFallDamage(entity, fallDistance); - if (damage > 0) { - playFallSound(entity, damage); - entity.damage(DamageType.FALL, damage); - } - } - - public void playFallSound(LivingEntity entity, int damage) { - boolean bigFall = damage > 4; - - entity.getViewersAsAudience().playSound(Sound.sound( - bigFall ? - SoundEvent.ENTITY_PLAYER_BIG_FALL : - SoundEvent.ENTITY_PLAYER_SMALL_FALL, - entity instanceof Player ? Sound.Source.PLAYER : Sound.Source.HOSTILE, - 1.0f, 1.0f - ), entity); - } - - @Override - public int getFallDamage(LivingEntity entity, double fallDistance) { - double safeFallDistance = entity.getAttributeValue(Attribute.SAFE_FALL_DISTANCE); - return (int) Math.ceil((fallDistance - safeFallDistance) * entity.getAttributeValue(Attribute.FALL_DAMAGE_MULTIPLIER)); - } - - @Override - public double getFallDistance(LivingEntity entity) { - return entity.hasTag(FALL_DISTANCE) ? entity.getTag(FALL_DISTANCE) : 0.0; - } - - @Override - public void resetFallDistance(LivingEntity entity) { - entity.setTag(FALL_DISTANCE, 0.0); - } - - @Override - public void setExtraFallParticles(LivingEntity entity, boolean extraFallParticles) { - if (extraFallParticles) entity.setTag(EXTRA_FALL_PARTICLES, true); - else entity.removeTag(EXTRA_FALL_PARTICLES); - } - - protected Point getLandingPos(LivingEntity livingEntity, Pos position) { - Point offset = position.add(0, -0.2, 0); - Instance instance = livingEntity.getInstance(); - - if (instance == null) return offset; - if (!instance.getBlock(offset).isAir()) return offset; - - Point offsetDown = offset.add(0, -1, 0); - Block block = instance.getBlock(offsetDown); - - Registries registries = MinecraftServer.process(); - var fences = registries.blocks().getTag(Key.key("minecraft:fences")); - var walls = registries.blocks().getTag(Key.key("minecraft:walls")); - var fenceGates = registries.blocks().getTag(Key.key("minecraft:fence_gates")); - - var key = block.asKey(); - - assert fences != null; - assert walls != null; - assert fenceGates != null; - assert key != null; - - if (fences.contains(key) - || walls.contains(key) - || fenceGates.contains(key)) { - return offsetDown; - } - - return offset; - } + public static final Tag FALL_DISTANCE = Tag.Transient("fallDistance"); + public static final DefinedFeature DEFINED = new DefinedFeature<>( + FeatureType.FALL, VanillaFallFeature::new, + VanillaFallFeature::initPlayer, + FeatureType.PLAYER_STATE, + FeatureType.PACKET, + FeatureType.SOUND + ); + public static final Tag EXTRA_FALL_PARTICLES = Tag.Transient("extraFallParticles"); + private final FeatureConfiguration configuration; + + private PacketProvider packetProvider; + private PlayerStateFeature playerStateFeature; + private SoundProvider soundProvider; + + public VanillaFallFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + public static void initPlayer(Player player, boolean firstInit) { + player.setTag(FALL_DISTANCE, 0.0); + } + + @Override + public void initDependencies() { + this.packetProvider = configuration.get(FeatureType.PACKET); + this.playerStateFeature = configuration.get(FeatureType.PLAYER_STATE); + this.soundProvider = configuration.get(FeatureType.SOUND); + } + + @Override + public void init(EventNode node) { + // For living non-player entities, handle fall damage every tick + node.addListener(EntityTickEvent.class, event -> { + if (!(event.getEntity() instanceof LivingEntity livingEntity)) return; + if (livingEntity instanceof Player) return; + + Pos previousPosition = livingEntity.getPreviousPosition(); + handleFallDamage(livingEntity, previousPosition, livingEntity.getPosition(), livingEntity.isOnGround()); + }); + + // For players, handle fall damage on move event + node.addListener(PlayerMoveEvent.class, event -> { + Player player = event.getPlayer(); + if (playerStateFeature.isClimbing(player)) player.setTag(FALL_DISTANCE, 0.0); + + handleFallDamage( + player, player.getPosition(), + event.getNewPosition(), event.isOnGround() + ); + }); + } + + public void handleFallDamage(LivingEntity entity, Pos currPos, Pos newPos, boolean onGround) { + double dy = newPos.y() - currPos.y(); + double newFallDistance = getFallDistance(entity) - dy; + + if ((entity instanceof Player player && player.isFlying()) + || entity.hasEffect(PotionEffect.LEVITATION) + || entity.hasEffect(PotionEffect.SLOW_FALLING) || dy > 0) { + entity.setTag(FALL_DISTANCE, 0.0); + return; + } + + if (entity.isFlyingWithElytra() && entity.getVelocity().y() > -0.5) { + entity.setTag(FALL_DISTANCE, 1.0); + return; + } + + if (!onGround) { + if (dy < 0) entity.setTag(FALL_DISTANCE, newFallDistance); + return; + } + + Point landingPos = getLandingPos(entity, newPos); + Block block = entity.getInstance().getBlock(landingPos); + + if (entity.hasTag(EXTRA_FALL_PARTICLES) && entity.getTag(EXTRA_FALL_PARTICLES) && newFallDistance > 0.0) { + Vec position = landingPos.asVec().apply(Vec.Operator.FLOOR).add(0.5, 1, 0.5); + int particleCount = (int) Math.clamp(50 * newFallDistance, 0, 200); + + packetProvider.sendPacket( + entity, + new ParticlePacket( + Particle.BLOCK.withBlock(block), + position.x(), position.y(), position.z(), + 0.3f, 0.3f, 0.3f, + 0.15f, particleCount + ) + ); + + entity.removeTag(EXTRA_FALL_PARTICLES); + } + + double safeFallDistance = entity.getAttributeValue(Attribute.SAFE_FALL_DISTANCE); + if (newFallDistance > safeFallDistance) { + if (!block.isAir()) { + double damageDistance = Math.ceil(newFallDistance - safeFallDistance); + double particleMultiplier = Math.min(0.2 + damageDistance / 15.0, 2.5); + int particleCount = (int) (150 * particleMultiplier); + + packetProvider.sendPacket( + entity, + new ParticlePacket( + Particle.BLOCK.withBlock(block), false, + false, + newPos.x(), newPos.y(), newPos.z(), + 0, 0, 0, + 0.15f, particleCount + ) + ); + } + } + + entity.setTag(FALL_DISTANCE, 0.0); + + if (entity instanceof Player player && player.getGameMode().invulnerable()) return; + int damage = getFallDamage(entity, newFallDistance); + if (damage > 0) { + playFallSound(entity, damage); + entity.damage(DamageType.FALL, damage); + } + } + + public void playFallSound(LivingEntity entity, int damage) { + boolean bigFall = damage > 4; + + soundProvider.playSound( + entity.getViewersAsAudience(), + Sound.sound( + bigFall ? + SoundEvent.ENTITY_PLAYER_BIG_FALL : + SoundEvent.ENTITY_PLAYER_SMALL_FALL, + entity instanceof Player ? Sound.Source.PLAYER : Sound.Source.HOSTILE, + 1.0f, 1.0f + ), + entity.getPosition().x(), entity.getPosition().y(), entity.getPosition().z() + ); + } + + @Override + public int getFallDamage(LivingEntity entity, double fallDistance) { + double safeFallDistance = entity.getAttributeValue(Attribute.SAFE_FALL_DISTANCE); + return (int) Math.floor((fallDistance + 1.0e-6 - safeFallDistance) * entity.getAttributeValue(Attribute.FALL_DAMAGE_MULTIPLIER)); + } + + @Override + public double getFallDistance(LivingEntity entity) { + return entity.hasTag(FALL_DISTANCE) ? entity.getTag(FALL_DISTANCE) : 0.0; + } + + @Override + public void resetFallDistance(LivingEntity entity) { + entity.setTag(FALL_DISTANCE, 0.0); + } + + @Override + public void setExtraFallParticles(LivingEntity entity, boolean extraFallParticles) { + if (extraFallParticles) entity.setTag(EXTRA_FALL_PARTICLES, true); + else entity.removeTag(EXTRA_FALL_PARTICLES); + } + + protected Point getLandingPos(LivingEntity livingEntity, Pos position) { + Point offset = position.add(0, -0.2, 0); + Instance instance = livingEntity.getInstance(); + + if (instance == null) return offset; + if (!instance.getBlock(offset).isAir()) return offset; + + Point offsetDown = offset.add(0, -1, 0); + Block block = instance.getBlock(offsetDown); + + Registries registries = MinecraftServer.process(); + var fences = registries.blocks().getTag(Key.key("minecraft:fences")); + var walls = registries.blocks().getTag(Key.key("minecraft:walls")); + var fenceGates = registries.blocks().getTag(Key.key("minecraft:fence_gates")); + + var key = block.asKey(); + + assert fences != null; + assert walls != null; + assert fenceGates != null; + assert key != null; + + if (fences.contains(key) + || walls.contains(key) + || fenceGates.contains(key)) { + return offsetDown; + } + + return offset; + } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaExhaustionFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaExhaustionFeature.java index 923224fb1..1cab34c2d 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaExhaustionFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaExhaustionFeature.java @@ -1,12 +1,5 @@ package net.swofty.pvp.feature.food; -import net.swofty.pvp.events.PlayerExhaustEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.provider.DifficultyProvider; -import net.swofty.pvp.utils.CombatVersion; import net.minestom.server.entity.Player; import net.minestom.server.entity.damage.DamageType; import net.minestom.server.event.EventDispatcher; @@ -18,6 +11,13 @@ import net.minestom.server.instance.block.Block; import net.minestom.server.tag.Tag; import net.minestom.server.world.Difficulty; +import net.swofty.pvp.events.PlayerExhaustEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.provider.DifficultyProvider; +import net.swofty.pvp.utils.CombatVersion; import java.util.Objects; @@ -30,41 +30,41 @@ public class VanillaExhaustionFeature implements ExhaustionFeature, RegistrableF VanillaExhaustionFeature::initPlayer, FeatureType.DIFFICULTY, FeatureType.VERSION ); - + public static final Tag EXHAUSTION = Tag.Float("exhaustion"); - + private final FeatureConfiguration configuration; - + private DifficultyProvider difficultyFeature; private CombatVersion version; - + public VanillaExhaustionFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.difficultyFeature = configuration.get(FeatureType.DIFFICULTY); this.version = configuration.get(FeatureType.VERSION); } - + public static void initPlayer(Player player, boolean firstInit) { player.setTag(EXHAUSTION, 0.0f); } - + @Override public void init(EventNode node) { node.addListener(PlayerTickEvent.class, event -> onTick(event.getPlayer())); - + node.addListener(PlayerBlockBreakEvent.class, event -> addExhaustion(event.getPlayer(), version.legacy() ? 0.025f : 0.005f)); - + node.addListener(PlayerMoveEvent.class, this::onMove); } - + protected void onTick(Player player) { if (player.getGameMode().invulnerable()) return; - + float exhaustion = player.getTag(EXHAUSTION); if (exhaustion > 4) { player.setTag(EXHAUSTION, exhaustion - 4); @@ -75,14 +75,14 @@ protected void onTick(Player player) { } } } - + protected void onMove(PlayerMoveEvent event) { Player player = event.getPlayer(); - + double xDiff = event.getNewPosition().x() - player.getPosition().x(); double yDiff = event.getNewPosition().y() - player.getPosition().y(); double zDiff = event.getNewPosition().z() - player.getPosition().z(); - + // Check if movement was a jump if (yDiff > 0.0D && player.isOnGround()) { if (player.isSprinting()) { @@ -91,7 +91,7 @@ protected void onMove(PlayerMoveEvent event) { addExhaustion(player, version.legacy() ? 0.2f : 0.05f); } } - + if (player.isOnGround()) { int l = (int) Math.round(Math.sqrt(xDiff * xDiff + zDiff * zDiff) * 100.0f); if (l > 0) addExhaustion(player, (player.isSprinting() ? 0.1f : 0.0f) * (float) l * 0.01f); @@ -102,7 +102,7 @@ protected void onMove(PlayerMoveEvent event) { } } } - + @Override public void addExhaustion(Player player, float exhaustion) { if (player.getGameMode().invulnerable()) return; @@ -110,17 +110,17 @@ public void addExhaustion(Player player, float exhaustion) { EventDispatcher.callCancellable(playerExhaustEvent, () -> player.setTag(EXHAUSTION, Math.min(player.getTag(EXHAUSTION) + playerExhaustEvent.getAmount(), 40))); } - + @Override public void addAttackExhaustion(Player player) { addExhaustion(player, version.legacy() ? 0.3f: 0.1f); } - + @Override public void addDamageExhaustion(Player player, DamageType type) { addExhaustion(player, type.exhaustion() * (version.legacy() ? 3 : 1)); } - + @Override public void applyHungerEffect(Player player, int amplifier) { addExhaustion(player, (version.legacy() ? 0.025f : 0.005f) * (float) (amplifier + 1)); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaFoodFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaFoodFeature.java index 9164cd277..405ddd0a8 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaFoodFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaFoodFeature.java @@ -33,6 +33,7 @@ import net.swofty.pvp.feature.config.DefinedFeature; import net.swofty.pvp.feature.config.FeatureConfiguration; import net.swofty.pvp.feature.cooldown.ItemCooldownFeature; +import net.swofty.pvp.feature.provider.SoundProvider; import net.swofty.pvp.utils.PotionFlags; import net.swofty.pvp.utils.ViewUtil; import org.jetbrains.annotations.Nullable; @@ -50,18 +51,19 @@ public class VanillaFoodFeature implements FoodFeature, RegistrableFeature { public static final DefinedFeature DEFINED = new DefinedFeature<>( FeatureType.FOOD, VanillaFoodFeature::new, - FeatureType.ITEM_COOLDOWN + FeatureType.ITEM_COOLDOWN, FeatureType.SOUND ); private final FeatureConfiguration configuration; private ItemCooldownFeature itemCooldownFeature; + private SoundProvider soundProvider; public VanillaFoodFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - public static void applyConsumeEffect(Entity entity, ConsumeEffect effect, Random random) { + public static void applyConsumeEffect(Entity entity, ConsumeEffect effect, Random random, SoundProvider soundProvider) { switch (effect) { case ApplyEffects(List effects, float probability) -> { if (random.nextFloat() >= probability) return; @@ -84,10 +86,14 @@ case RemoveEffects(RegistryTag potionEffects) -> entity.getActiveE .forEach(entity::removeEffect); case ClearAllEffects ignored -> entity.clearEffects(); case TeleportRandomly(float diameter) -> ChorusFruitUtil.tryChorusTeleport(entity, diameter); - case PlaySound(SoundEvent sound) -> ViewUtil.viewersAndSelf(entity).playSound(Sound.sound( - sound, Sound.Source.PLAYER, - 1.0f, 1.0f - ), entity); + case PlaySound(SoundEvent sound) -> soundProvider.playSound( + ViewUtil.viewersAndSelf(entity), + Sound.sound( + sound, Sound.Source.PLAYER, + 1.0f, 1.0f + ), + entity.getPosition().x(), entity.getPosition().y(), entity.getPosition().z() // TODO: emitter + ); default -> throw new IllegalArgumentException("Unexpected value: " + effect); } } @@ -95,6 +101,7 @@ case PlaySound(SoundEvent sound) -> ViewUtil.viewersAndSelf(entity).playSound(So @Override public void initDependencies() { this.itemCooldownFeature = configuration.get(FeatureType.ITEM_COOLDOWN); + this.soundProvider = configuration.get(FeatureType.SOUND); } @Override @@ -144,16 +151,20 @@ protected void onFinishEating(Player player, ItemStack stack, PlayerHand hand) { triggerEatingSound(player, consumable); if (food != null) { - ViewUtil.viewersAndSelf(player).playSound(Sound.sound( + soundProvider.playSound( + ViewUtil.viewersAndSelf(player), + Sound.sound( SoundEvent.ENTITY_PLAYER_BURP, Sound.Source.PLAYER, 0.5f, random.nextFloat() * 0.1f + 0.9f - ), player); + ), + player.getPosition().x(), player.getPosition().y(), player.getPosition().z() // TODO: emitter + ); } List effectList = consumable.effects(); for (ConsumeEffect effect : effectList) { - applyConsumeEffect(player, effect, random); + applyConsumeEffect(player, effect, random, soundProvider); } if (stack.has(DataComponents.SUSPICIOUS_STEW_EFFECTS)) { @@ -222,10 +233,14 @@ protected void tickEatingSounds(Player player) { protected void triggerEatingSound(Player player, Consumable consumable) { ThreadLocalRandom random = ThreadLocalRandom.current(); - player.getViewersAsAudience().playSound(Sound.sound( + soundProvider.playSound( + player.getViewersAsAudience(), + Sound.sound( consumable.sound(), Sound.Source.PLAYER, 0.5f + 0.5f * random.nextInt(2), (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f - ), player); + ), + player.getPosition().x(), player.getPosition().y(), player.getPosition().z() + ); } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaRegenerationFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaRegenerationFeature.java index 000d6730f..f9e16a433 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaRegenerationFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/food/VanillaRegenerationFeature.java @@ -1,12 +1,5 @@ package net.swofty.pvp.feature.food; -import net.swofty.pvp.events.PlayerRegenerateEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.provider.DifficultyProvider; -import net.swofty.pvp.utils.CombatVersion; import net.minestom.server.entity.Player; import net.minestom.server.entity.attribute.Attribute; import net.minestom.server.entity.damage.DamageType; @@ -16,6 +9,13 @@ import net.minestom.server.event.trait.EntityInstanceEvent; import net.minestom.server.tag.Tag; import net.minestom.server.world.Difficulty; +import net.swofty.pvp.events.PlayerRegenerateEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.provider.DifficultyProvider; +import net.swofty.pvp.utils.CombatVersion; /** * Vanilla implementation of {@link RegenerationFeature} @@ -26,43 +26,43 @@ public class VanillaRegenerationFeature implements RegenerationFeature, Registra VanillaRegenerationFeature::initPlayer, FeatureType.EXHAUSTION, FeatureType.DIFFICULTY, FeatureType.VERSION ); - + public static final Tag STARVATION_TICKS = Tag.Integer("starvationTicks"); - + private final FeatureConfiguration configuration; - + private ExhaustionFeature exhaustionFeature; private DifficultyProvider difficultyFeature; private CombatVersion version; - + public VanillaRegenerationFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.exhaustionFeature = configuration.get(FeatureType.EXHAUSTION); this.difficultyFeature = configuration.get(FeatureType.DIFFICULTY); this.version = configuration.get(FeatureType.VERSION); } - + public static void initPlayer(Player player, boolean firstInit) { player.setTag(STARVATION_TICKS, 0); } - + @Override public void init(EventNode node) { node.addListener(PlayerTickEvent.class, event -> onTick(event.getPlayer())); } - + protected void onTick(Player player) { if (player.getGameMode().invulnerable()) return; Difficulty difficulty = difficultyFeature.getValue(player); - + int food = player.getFood(); float health = player.getHealth(); int starvationTicks = player.getTag(STARVATION_TICKS); - + if (version.modern() && player.getFoodSaturation() > 0 && health > 0 && health < player.getAttributeValue(Attribute.MAX_HEALTH) && food >= 20) { starvationTicks++; @@ -85,16 +85,16 @@ protected void onTick(Player player) { || ((health > 1) && (difficulty == Difficulty.NORMAL))) { player.damage(DamageType.STARVE, 1); } - + starvationTicks = 0; } } else { starvationTicks = 0; } - + player.setTag(STARVATION_TICKS, starvationTicks); } - + @Override public void regenerate(Player player, float health, float exhaustion) { PlayerRegenerateEvent event = new PlayerRegenerateEvent(player, health, exhaustion); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/knockback/FairKnockbackFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/knockback/FairKnockbackFeature.java index fde0ba1f6..994e1c859 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/knockback/FairKnockbackFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/knockback/FairKnockbackFeature.java @@ -1,10 +1,5 @@ package net.swofty.pvp.feature.knockback; -import net.swofty.pvp.events.EntityKnockbackEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.player.CombatPlayer; import net.minestom.server.ServerFlag; import net.minestom.server.collision.Aerodynamics; import net.minestom.server.coordinate.Vec; @@ -12,6 +7,11 @@ import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.Player; import net.minestom.server.instance.block.Block; +import net.swofty.pvp.events.EntityKnockbackEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.player.CombatPlayer; import org.jetbrains.annotations.Nullable; /** @@ -42,26 +42,26 @@ public class FairKnockbackFeature extends VanillaKnockbackFeature { FeatureType.KNOCKBACK, configuration -> new FairKnockbackFeature(configuration, true), FeatureType.VERSION ); - + private static final int PING_OFFSET = 25; - + protected final boolean compensateFallKnockback; - + public FairKnockbackFeature(FeatureConfiguration configuration, boolean compensateFallKnockback) { super(configuration); this.compensateFallKnockback = compensateFallKnockback; } - + @Override protected boolean applyKnockback(LivingEntity target, Entity attacker, @Nullable Entity source, EntityKnockbackEvent.KnockbackType type, int extraKnockback, double dx, double dz, boolean legacy) { if (!(target instanceof Player player) || player.getLatency() < PING_OFFSET) return super.applyKnockback(target, attacker, source, type, extraKnockback, dx, dz, legacy); - + KnockbackValues values = prepareKnockback(target, attacker, source, type, extraKnockback, dx, dz, legacy); if (values == null) return false; - + Vec velocity = target.getVelocity(); if (legacy && type == EntityKnockbackEvent.KnockbackType.ATTACK) { // For legacy versions, extra knockback is added directly on top of the original velocity @@ -72,7 +72,7 @@ protected boolean applyKnockback(LivingEntity target, Entity attacker, @Nullable )); } else { // For modern versions and legacy non-attack knockback, the velocity is first divided by 2 - + int latencyTicks = getLatencyTicks(player.getLatency()); double vertical; if (isOnGroundClientSide(player, latencyTicks)) { @@ -82,7 +82,7 @@ protected boolean applyKnockback(LivingEntity target, Entity attacker, @Nullable } else { vertical = velocity.y(); } - + target.setVelocity(new Vec( velocity.x() / 2d - values.horizontalModifier().x(), vertical, @@ -97,11 +97,11 @@ protected boolean applyKnockback(LivingEntity target, Entity attacker, @Nullable return true; } - + protected boolean isOnGroundClientSide(Player player, int latencyTicks) { if (player.isOnGround() || !(player instanceof CombatPlayer combatPlayer)) return true; if (player.getGravityTickCount() > 30) return false; // Very uncertain, default to false - + // These are all cases in which isOnGroundAfterTicks() will not be accurate Block block = player.getInstance().getBlock(player.getPosition()); if (player.isFlyingWithElytra() @@ -110,10 +110,10 @@ protected boolean isOnGroundClientSide(Player player, int latencyTicks) { || block.compare(Block.COBWEB) || block.compare(Block.SCAFFOLDING)) return false; - + return combatPlayer.isOnGroundAfterTicks(latencyTicks); } - + /** * Compensates the given vertical velocity for gravity calculations for a given amount of ticks. * This means for every tick, it will be affected by gravity and vertical air resistance. @@ -128,10 +128,10 @@ protected static double getCompensatedVerticalVelocity(Aerodynamics aerodynamics velocity -= aerodynamics.gravity(); velocity *= aerodynamics.verticalAirResistance(); } - + return velocity; } - + private static int getLatencyTicks(int latencyMillis) { return Math.ceilDiv(latencyMillis * ServerFlag.SERVER_TICKS_PER_SECOND, 1000) + 2; } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/knockback/VanillaKnockbackFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/knockback/VanillaKnockbackFeature.java index 9a9b51e2c..a93f910fa 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/knockback/VanillaKnockbackFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/knockback/VanillaKnockbackFeature.java @@ -1,11 +1,5 @@ package net.swofty.pvp.feature.knockback; -import net.swofty.pvp.events.EntityKnockbackEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.player.CombatPlayer; -import net.swofty.pvp.utils.CombatVersion; import net.minestom.server.coordinate.Vec; import net.minestom.server.entity.Entity; import net.minestom.server.entity.LivingEntity; @@ -14,6 +8,12 @@ import net.minestom.server.entity.damage.Damage; import net.minestom.server.event.EventDispatcher; import net.minestom.server.network.packet.server.play.HitAnimationPacket; +import net.swofty.pvp.events.EntityKnockbackEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.player.CombatPlayer; +import net.swofty.pvp.utils.CombatVersion; import org.jetbrains.annotations.Nullable; import java.util.concurrent.ThreadLocalRandom; @@ -23,8 +23,8 @@ */ public class VanillaKnockbackFeature implements KnockbackFeature { public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.KNOCKBACK, VanillaKnockbackFeature::new, - FeatureType.VERSION + FeatureType.KNOCKBACK, VanillaKnockbackFeature::new, + FeatureType.VERSION ); private final FeatureConfiguration configuration; @@ -57,9 +57,9 @@ public boolean applyDamageKnockback(Damage damage, LivingEntity target) { // Set the velocity return applyKnockback( - target, attacker, source, - EntityKnockbackEvent.KnockbackType.DAMAGE, 0, - dx, dz, version.legacy() + target, attacker, source, + EntityKnockbackEvent.KnockbackType.DAMAGE, 0, + dx, dz, version.legacy() ); } @@ -67,21 +67,17 @@ public boolean applyDamageKnockback(Damage damage, LivingEntity target) { public boolean applyAttackKnockback(LivingEntity attacker, LivingEntity target, int knockback) { if (knockback <= 0) return false; - // If legacy, attacker velocity is reduced before the knockback - if (version.legacy() && attacker instanceof CombatPlayer custom) - custom.afterSprintAttack(); - double dx = Math.sin(Math.toRadians(attacker.getPosition().yaw())); double dz = -Math.cos(Math.toRadians(attacker.getPosition().yaw())); if (!applyKnockback( - target, attacker, attacker, - EntityKnockbackEvent.KnockbackType.ATTACK, knockback, - dx, dz, version.legacy() + target, attacker, attacker, + EntityKnockbackEvent.KnockbackType.ATTACK, knockback, + dx, dz, version.legacy() )) return false; - // If not legacy, attacker velocity is reduced after the knockback - if (version.modern() && attacker instanceof CombatPlayer custom) + // In vanilla, attacker sprint momentum is reduced after a successful sprint/knockback hit + if (attacker instanceof CombatPlayer custom) custom.afterSprintAttack(); attacker.setSprinting(false); @@ -94,26 +90,27 @@ public boolean applySweepingKnockback(LivingEntity attacker, LivingEntity target double dz = -Math.cos(Math.toRadians(attacker.getPosition().yaw())); return applyKnockback( - target, attacker, null, - EntityKnockbackEvent.KnockbackType.SWEEPING, 0, - dx, dz, version.legacy() + target, attacker, null, + EntityKnockbackEvent.KnockbackType.SWEEPING, 0, + dx, dz, version.legacy() ); } public record KnockbackValues( - Vec horizontalModifier, - double vertical, double verticalLimit, - EntityKnockbackEvent.AnimationType animationType - ) {} + Vec horizontalModifier, + double vertical, double verticalLimit, + EntityKnockbackEvent.AnimationType animationType + ) { + } protected @Nullable KnockbackValues prepareKnockback(LivingEntity target, Entity attacker, @Nullable Entity source, EntityKnockbackEvent.KnockbackType type, int extraKnockback, double dx, double dz, boolean legacy) { var animationType = legacy - ? EntityKnockbackEvent.AnimationType.FIXED - : type == EntityKnockbackEvent.KnockbackType.DAMAGE - ? EntityKnockbackEvent.AnimationType.DIRECTIONAL - : EntityKnockbackEvent.AnimationType.FIXED; + ? EntityKnockbackEvent.AnimationType.FIXED + : type == EntityKnockbackEvent.KnockbackType.DAMAGE + ? EntityKnockbackEvent.AnimationType.DIRECTIONAL + : EntityKnockbackEvent.AnimationType.FIXED; EntityKnockbackEvent knockbackEvent = new EntityKnockbackEvent(target, source == null ? attacker : source, type, animationType); EventDispatcher.call(knockbackEvent); if (knockbackEvent.isCancelled()) return null; @@ -129,8 +126,8 @@ public record KnockbackValues( } else { // Extra knockback double baseVertical = legacy ? - settings.extraVertical() : // Legacy: defaults to 0.1 - settings.vertical() + settings.extraVertical(); // Modern: defaults to 0.1 + 0.4 = 0.5 + settings.extraVertical() : // Legacy: defaults to 0.1 + settings.vertical() + settings.extraVertical(); // Modern: defaults to 0.1 + 0.4 = 0.5 horizontal = settings.extraHorizontal() * extraKnockback; vertical = baseVertical * extraKnockback; @@ -151,19 +148,19 @@ protected boolean applyKnockback(LivingEntity target, Entity attacker, @Nullable if (values == null) return false; Vec velocity = target.getVelocity(); - if (legacy && type == EntityKnockbackEvent.KnockbackType.ATTACK) { - // For legacy versions, extra knockback is added directly on top of the original velocity + + if (legacy && type == EntityKnockbackEvent.KnockbackType.ATTACK && extraKnockback > 0) { target.setVelocity(velocity.add( - -values.horizontalModifier().x(), - values.vertical(), - -values.horizontalModifier().z() + -values.horizontalModifier().x(), + values.vertical(), + -values.horizontalModifier().z() )); } else { - // For modern versions and legacy non-attack knockback, the velocity is first divided by 2 + // Base knockback halves current velocity first (matches legacy entity knockBack behavior). target.setVelocity(new Vec( - velocity.x() / 2d - values.horizontalModifier().x(), - target.isOnGround() ? Math.min(values.verticalLimit(), velocity.y() / 2d + values.vertical()) : velocity.y(), - velocity.z() / 2d - values.horizontalModifier().z() + velocity.x() / 2d - values.horizontalModifier().x(), + target.isOnGround() ? Math.min(values.verticalLimit(), velocity.y() / 2d + values.vertical()) : velocity.y(), + velocity.z() / 2d - values.horizontalModifier().z() )); } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/potion/VanillaPotionFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/potion/VanillaPotionFeature.java index a45cbde3e..946713f32 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/potion/VanillaPotionFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/potion/VanillaPotionFeature.java @@ -24,6 +24,7 @@ import net.swofty.pvp.feature.effect.EffectFeature; import net.swofty.pvp.feature.food.ExhaustionFeature; import net.swofty.pvp.feature.food.FoodFeature; +import net.swofty.pvp.feature.provider.SoundProvider; import net.swofty.pvp.potion.effect.CombatPotionEffect; import net.swofty.pvp.potion.effect.CombatPotionEffects; import net.swofty.pvp.utils.ViewUtil; @@ -36,145 +37,161 @@ * Vanilla implementation of {@link PotionFeature} */ public class VanillaPotionFeature implements PotionFeature, RegistrableFeature { - public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.POTION, VanillaPotionFeature::new, - FeatureType.EFFECT, FeatureType.EXHAUSTION, FeatureType.FOOD - ); - - private static final int USE_TICKS = 32; - - private final FeatureConfiguration configuration; - - private EffectFeature effectFeature; - private ExhaustionFeature exhaustionFeature; - private FoodFeature foodFeature; - - public VanillaPotionFeature(FeatureConfiguration configuration) { - this.configuration = configuration; - } - - @Override - public void initDependencies() { - this.effectFeature = configuration.get(FeatureType.EFFECT); - this.exhaustionFeature = configuration.get(FeatureType.EXHAUSTION); - this.foodFeature = configuration.get(FeatureType.FOOD); - } - - @Override - public void init(EventNode node) { - node.addListener(PlayerUseItemEvent.class, event -> { - if (event.getItemStack().material() == Material.POTION) { - event.setItemUseTime(USE_TICKS); // Potion use time is always 32 ticks - } - }); - - node.addListener(PlayerFinishItemUseEvent.class, event -> { - if (event.getItemStack().material() != Material.POTION) return; - - Player player = event.getPlayer(); - ItemStack stack = event.getItemStack(); - - triggerDrinkingSound(player); - - List potions = effectFeature.getAllPotions(stack.get(DataComponents.POTION_CONTENTS)); - - // Apply the potions - for (Potion potion : potions) { - CombatPotionEffect combatPotionEffect = CombatPotionEffects.get(potion.effect()); - - if (combatPotionEffect.isInstant()) { - combatPotionEffect.applyInstantEffect(player, player, player, potion.amplifier(), - 1.0, exhaustionFeature, foodFeature); - } else { - player.addEffect(potion); - } - } - - if (player.getGameMode() != GameMode.CREATIVE) { - ItemStack remainder = stack.get(DataComponents.USE_REMAINDER); - - if (remainder != null && !remainder.isAir()) { - if (stack.amount() == 1) { - player.setItemInHand(event.getHand(), remainder); - } else { - player.setItemInHand(event.getHand(), stack.withAmount(stack.amount() - 1)); - player.getInventory().addItemStack(remainder); - } - } else { - player.setItemInHand(event.getHand(), stack.withAmount(stack.amount() - 1)); - } - } - }); - - node.addListener(PlayerTickEvent.class, event -> { - Player player = event.getPlayer(); - if (player.isSilent() || !player.isEating()) return; - - tickDrinkingSounds(player); - }); - - node.addListener(PlayerUseItemEvent.class, event -> { - if (event.getItemStack().material() != Material.SPLASH_POTION) return; - - ThreadLocalRandom random = ThreadLocalRandom.current(); - ViewUtil.viewersAndSelf(event.getPlayer()).playSound(Sound.sound( - SoundEvent.ENTITY_SPLASH_POTION_THROW, Sound.Source.PLAYER, - 0.5f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) - ), event.getPlayer()); - - throwPotion(event.getPlayer(), event.getItemStack(), event.getHand()); - }); - - node.addListener(PlayerUseItemEvent.class, event -> { - if (event.getItemStack().material() != Material.LINGERING_POTION) return; - - ThreadLocalRandom random = ThreadLocalRandom.current(); - ViewUtil.viewersAndSelf(event.getPlayer()).playSound(Sound.sound( - SoundEvent.ENTITY_LINGERING_POTION_THROW, Sound.Source.NEUTRAL, - 0.5f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) - ), event.getPlayer()); - - throwPotion(event.getPlayer(), event.getItemStack(), event.getHand()); - }); - } - - protected void throwPotion(Player player, ItemStack stack, PlayerHand hand) { - ThrownPotion thrownPotion = new ThrownPotion(player, effectFeature, false); - thrownPotion.setItem(stack); - - Pos position = player.getPosition().add(0, player.getEyeHeight(), 0); - thrownPotion.shootFromRotation(position.pitch(), position.yaw(), -20, 0.5, 1.0); - thrownPotion.setInstance(Objects.requireNonNull(player.getInstance()), position.withView(thrownPotion.getPosition())); - - Vec playerVel = player.getVelocity(); - thrownPotion.setVelocity(thrownPotion.getVelocity().add(playerVel.x(), - player.isOnGround() ? 0.0 : playerVel.y(), playerVel.z())); - - if (player.getGameMode() != GameMode.CREATIVE) { - player.setItemInHand(hand, stack.withAmount(stack.amount() - 1)); - } - } - - protected void tickDrinkingSounds(Player player) { - ItemStack stack = player.getItemInHand(Objects.requireNonNull(player.getItemUseHand())); - if (stack.material() != Material.POTION) return; - - long usedTicks = player.getCurrentItemUseTime(); - long remainingUseTicks = USE_TICKS - usedTicks; - - boolean canTrigger = remainingUseTicks <= USE_TICKS - 7; - boolean shouldTrigger = canTrigger && remainingUseTicks % 4 == 0; - if (!shouldTrigger) return; - - triggerDrinkingSound(player); - } - - protected void triggerDrinkingSound(Player player) { - ThreadLocalRandom random = ThreadLocalRandom.current(); - - player.getViewersAsAudience().playSound(Sound.sound( - SoundEvent.ENTITY_GENERIC_DRINK, Sound.Source.PLAYER, - 0.5f, random.nextFloat() * 0.1f + 0.9f - ), player); - } + public static final DefinedFeature DEFINED = new DefinedFeature<>( + FeatureType.POTION, VanillaPotionFeature::new, + FeatureType.EFFECT, FeatureType.EXHAUSTION, FeatureType.FOOD, + FeatureType.SOUND + ); + + private static final int USE_TICKS = 32; + + private final FeatureConfiguration configuration; + + private EffectFeature effectFeature; + private ExhaustionFeature exhaustionFeature; + private FoodFeature foodFeature; + private SoundProvider soundProvider; + + public VanillaPotionFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void initDependencies() { + this.effectFeature = configuration.get(FeatureType.EFFECT); + this.exhaustionFeature = configuration.get(FeatureType.EXHAUSTION); + this.foodFeature = configuration.get(FeatureType.FOOD); + this.soundProvider = configuration.get(FeatureType.SOUND); + } + + @Override + public void init(EventNode node) { + node.addListener(PlayerUseItemEvent.class, event -> { + if (event.getItemStack().material() == Material.POTION) { + event.setItemUseTime(USE_TICKS); // Potion use time is always 32 ticks + } + }); + + node.addListener(PlayerFinishItemUseEvent.class, event -> { + if (event.getItemStack().material() != Material.POTION) return; + + Player player = event.getPlayer(); + ItemStack stack = event.getItemStack(); + + triggerDrinkingSound(player); + + List potions = effectFeature.getAllPotions(stack.get(DataComponents.POTION_CONTENTS)); + + // Apply the potions + for (Potion potion : potions) { + CombatPotionEffect combatPotionEffect = CombatPotionEffects.get(potion.effect()); + + if (combatPotionEffect.isInstant()) { + combatPotionEffect.applyInstantEffect(player, player, player, potion.amplifier(), + 1.0, exhaustionFeature, foodFeature); + } else { + player.addEffect(potion); + } + } + + if (player.getGameMode() != GameMode.CREATIVE) { + ItemStack remainder = stack.get(DataComponents.USE_REMAINDER); + + if (remainder != null && !remainder.isAir()) { + if (stack.amount() == 1) { + player.setItemInHand(event.getHand(), remainder); + } else { + player.setItemInHand(event.getHand(), stack.withAmount(stack.amount() - 1)); + player.getInventory().addItemStack(remainder); + } + } else { + player.setItemInHand(event.getHand(), stack.withAmount(stack.amount() - 1)); + } + } + }); + + node.addListener(PlayerTickEvent.class, event -> { + Player player = event.getPlayer(); + if (player.isSilent() || !player.isEating()) return; + + tickDrinkingSounds(player); + }); + + node.addListener(PlayerUseItemEvent.class, event -> { + if (event.getItemStack().material() != Material.SPLASH_POTION) return; + + ThreadLocalRandom random = ThreadLocalRandom.current(); + Pos position = event.getPlayer().getPosition(); + soundProvider.playSound( + ViewUtil.viewersAndSelf(event.getPlayer()), + Sound.sound( + SoundEvent.ENTITY_SPLASH_POTION_THROW, Sound.Source.PLAYER, + 0.5f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) + ), + position.x(), position.y(), position.z() + ); + + throwPotion(event.getPlayer(), event.getItemStack(), event.getHand(), false); + }); + + node.addListener(PlayerUseItemEvent.class, event -> { + if (event.getItemStack().material() != Material.LINGERING_POTION) return; + + ThreadLocalRandom random = ThreadLocalRandom.current(); + soundProvider.playSound( + ViewUtil.viewersAndSelf(event.getPlayer()), + Sound.sound( + SoundEvent.ENTITY_LINGERING_POTION_THROW, Sound.Source.NEUTRAL, + 0.5f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) + ), + event.getPlayer().getPosition().x(), event.getPlayer().getPosition().y(), event.getPlayer().getPosition().z() + ); + + throwPotion(event.getPlayer(), event.getItemStack(), event.getHand(), true); + }); + } + + protected void throwPotion(Player player, ItemStack stack, PlayerHand hand, boolean lingering) { + ThrownPotion thrownPotion = new ThrownPotion(player, effectFeature, lingering); + thrownPotion.setItem(stack); + + Pos position = player.getPosition().add(0, player.getEyeHeight(), 0); + thrownPotion.shootFromRotation(position.pitch(), position.yaw(), -20, 0.5, 1.0, 0.0); + thrownPotion.setInstance(Objects.requireNonNull(player.getInstance()), position.withView(thrownPotion.getPosition())); + + Vec playerVel = player.getVelocity(); + thrownPotion.setVelocity(thrownPotion.getVelocity().add(playerVel.x(), + player.isOnGround() ? 0.0 : playerVel.y(), playerVel.z())); + + if (player.getGameMode() != GameMode.CREATIVE) { + player.setItemInHand(hand, stack.withAmount(stack.amount() - 1)); + } + } + + protected void tickDrinkingSounds(Player player) { + ItemStack stack = player.getItemInHand(Objects.requireNonNull(player.getItemUseHand())); + if (stack.material() != Material.POTION) return; + + long usedTicks = player.getCurrentItemUseTime(); + long remainingUseTicks = USE_TICKS - usedTicks; + + boolean canTrigger = remainingUseTicks <= USE_TICKS - 7; + boolean shouldTrigger = canTrigger && remainingUseTicks % 4 == 0; + if (!shouldTrigger) return; + + triggerDrinkingSound(player); + } + + protected void triggerDrinkingSound(Player player) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + Pos position = player.getPosition(); + soundProvider.playSound( + player.getViewersAsAudience(), + Sound.sound( + SoundEvent.ENTITY_GENERIC_DRINK, Sound.Source.PLAYER, + 0.5f, random.nextFloat() * 0.1f + 0.9f + ), + position.x(), position.y(), position.z() + ); + } } \ No newline at end of file diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/FireworkRocketFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/FireworkRocketFeature.java new file mode 100644 index 000000000..8f30e7026 --- /dev/null +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/FireworkRocketFeature.java @@ -0,0 +1,11 @@ +package net.swofty.pvp.feature.projectile; + +import net.swofty.pvp.feature.CombatFeature; + +/** + * Combat feature which handles using fireworks. + */ +public interface FireworkRocketFeature extends CombatFeature { + FireworkRocketFeature NO_OP = new FireworkRocketFeature() { + }; +} \ No newline at end of file diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaBowFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaBowFeature.java index 225b9c135..c7e96f162 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaBowFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaBowFeature.java @@ -5,7 +5,11 @@ import net.minestom.server.component.DataComponents; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; -import net.minestom.server.entity.*; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EquipmentSlot; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.PlayerHand; import net.minestom.server.event.EventNode; import net.minestom.server.event.item.PlayerBeginItemUseEvent; import net.minestom.server.event.item.PlayerCancelItemUseEvent; @@ -126,7 +130,7 @@ public void init(EventNode node) { // Arrow shooting Pos position = player.getPosition().add(0D, player.getEyeHeight() - 0.1, 0D); - arrow.shootFromRotation(position.pitch(), position.yaw(), 0, power * 3, 1.0); + arrow.shootFromRotation(position.pitch(), position.yaw(), 0, power * 3, 1.0, 0.0); Vec playerVel = player.getVelocity(); arrow.setVelocity(arrow.getVelocity().add(playerVel.x(), player.isOnGround() ? 0.0D : playerVel.y(), playerVel.z())); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaCrossbowFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaCrossbowFeature.java index 580a66d40..6fbbf626d 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaCrossbowFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaCrossbowFeature.java @@ -3,10 +3,15 @@ import net.kyori.adventure.sound.Sound; import net.minestom.server.component.DataComponents; import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.*; +import net.minestom.server.entity.Entity; +import net.minestom.server.entity.EquipmentSlot; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.PlayerHand; import net.minestom.server.entity.metadata.LivingEntityMeta; import net.minestom.server.event.EventNode; -import net.minestom.server.event.item.PlayerFinishItemUseEvent; +import net.minestom.server.event.item.PlayerBeginItemUseEvent; +import net.minestom.server.event.item.PlayerCancelItemUseEvent; import net.minestom.server.event.player.PlayerTickEvent; import net.minestom.server.event.player.PlayerUseItemEvent; import net.minestom.server.event.trait.EntityInstanceEvent; @@ -17,17 +22,21 @@ import net.minestom.server.tag.Tag; import net.swofty.pvp.entity.projectile.AbstractArrow; import net.swofty.pvp.entity.projectile.Arrow; +import net.swofty.pvp.entity.projectile.FireworkRocketEntity; import net.swofty.pvp.entity.projectile.SpectralArrow; import net.swofty.pvp.feature.FeatureType; import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.block.BlockFeature; import net.swofty.pvp.feature.config.DefinedFeature; import net.swofty.pvp.feature.config.FeatureConfiguration; import net.swofty.pvp.feature.effect.EffectFeature; import net.swofty.pvp.feature.enchantment.EnchantmentFeature; import net.swofty.pvp.feature.item.ItemDamageFeature; import net.swofty.pvp.utils.ViewUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; @@ -36,299 +45,309 @@ * Vanilla implementation of {@link CrossbowFeature} */ public class VanillaCrossbowFeature implements CrossbowFeature, RegistrableFeature { - public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.CROSSBOW, VanillaCrossbowFeature::new, - FeatureType.ITEM_DAMAGE, FeatureType.EFFECT, FeatureType.ENCHANTMENT, FeatureType.PROJECTILE_ITEM - ); - - private static final Tag START_SOUND_PLAYED = Tag.Transient("StartSoundPlayed"); - private static final Tag MID_LOAD_SOUND_PLAYED = Tag.Transient("MidLoadSoundPlayed"); - - private final FeatureConfiguration configuration; - - private ItemDamageFeature itemDamageFeature; - private EffectFeature effectFeature; - private EnchantmentFeature enchantmentFeature; - private ProjectileItemFeature projectileItemFeature; - - public VanillaCrossbowFeature(FeatureConfiguration configuration) { - this.configuration = configuration; - } - - @Override - public void initDependencies() { - this.itemDamageFeature = configuration.get(FeatureType.ITEM_DAMAGE); - this.effectFeature = configuration.get(FeatureType.EFFECT); - this.enchantmentFeature = configuration.get(FeatureType.ENCHANTMENT); - this.projectileItemFeature = configuration.get(FeatureType.PROJECTILE_ITEM); - } - - @Override - public void init(EventNode node) { - node.addListener(PlayerUseItemEvent.class, event -> { - ItemStack stack = event.getItemStack(); - if (stack.material() != Material.CROSSBOW) return; - Player player = event.getPlayer(); - - if (isCrossbowCharged(stack)) { - // Make sure the animation event is not called, because this is not an animation - event.setCancelled(true); - - stack = performCrossbowShooting(player, event.getHand(), stack, getCrossbowPower(stack), 1.0); - player.setItemInHand(event.getHand(), setCrossbowProjectile(stack, null)); - } else { - if (projectileItemFeature.getCrossbowProjectile(player) == null) { - event.setCancelled(true); - } else { - player.setTag(START_SOUND_PLAYED, false); - player.setTag(MID_LOAD_SOUND_PLAYED, false); - } - } - }); - - node.addListener(PlayerTickEvent.class, event -> { - Player player = event.getPlayer(); - - // If not charging crossbow, return - LivingEntityMeta meta = (LivingEntityMeta) player.getEntityMeta(); - if (!meta.isHandActive() || player.getItemInHand(meta.getActiveHand()).material() != Material.CROSSBOW) - return; - - PlayerHand hand = player.getPlayerMeta().getActiveHand(); - ItemStack stack = player.getItemInHand(hand); - - int quickCharge = stack.get(DataComponents.ENCHANTMENTS).level(Enchantment.QUICK_CHARGE); - - long useTicks = player.getCurrentItemUseTime(); - double progress = (getCrossbowUseDuration(stack) - useTicks) / (double) getCrossbowChargeDuration(stack); - - Boolean startSoundPlayed = player.getTag(START_SOUND_PLAYED); - Boolean midLoadSoundPlayed = player.getTag(MID_LOAD_SOUND_PLAYED); - if (startSoundPlayed == null) startSoundPlayed = false; - if (midLoadSoundPlayed == null) midLoadSoundPlayed = false; - - if (progress >= 0.2 && !startSoundPlayed) { - SoundEvent startSound = getCrossbowStartSound(quickCharge); - ViewUtil.viewersAndSelf(player).playSound(Sound.sound( - startSound, Sound.Source.PLAYER, - 0.5f, 1.0f - ), player); - - player.setTag(START_SOUND_PLAYED, true); - player.setItemInHand(hand, stack); - } - - SoundEvent midLoadSound = quickCharge == 0 ? SoundEvent.ITEM_CROSSBOW_LOADING_MIDDLE : null; - if (progress >= 0.5F && midLoadSound != null && !midLoadSoundPlayed) { - ViewUtil.viewersAndSelf(player).playSound(Sound.sound( - midLoadSound, Sound.Source.PLAYER, - 0.5f, 1.0f - ), player); - - player.setTag(MID_LOAD_SOUND_PLAYED, true); - player.setItemInHand(hand, stack); - } - }); - - node.addListener(PlayerFinishItemUseEvent.class, event -> { - Player player = event.getPlayer(); - ItemStack stack = event.getItemStack(); - if (stack.material() != Material.CROSSBOW) return; - - int quickCharge = stack.get(DataComponents.ENCHANTMENTS).level(Enchantment.QUICK_CHARGE); - - if (quickCharge < 6) { - long useTicks = player.getCurrentItemUseTime(); - double power = getCrossbowPowerForTime(useTicks, stack); - if (!(power >= 1.0F) || isCrossbowCharged(stack)) - return; - } - - stack = loadCrossbowProjectiles(player, stack); - if (stack == null) return; - - ThreadLocalRandom random = ThreadLocalRandom.current(); - ViewUtil.viewersAndSelf(player).playSound(Sound.sound( - SoundEvent.ITEM_CROSSBOW_LOADING_END, Sound.Source.PLAYER, - 1.0f, 1.0f / (random.nextFloat() * 0.5f + 1.0f) + 0.2f - ), player); - - player.setItemInHand(event.getHand(), stack); - }); - } - - protected AbstractArrow createArrow(ItemStack stack, @Nullable Entity shooter) { - if (stack.material() == Material.SPECTRAL_ARROW) { - return new SpectralArrow(shooter, enchantmentFeature); - } else { - Arrow arrow = new Arrow(shooter, effectFeature, enchantmentFeature); - arrow.setItemStack(stack); - return arrow; - } - } - - protected double getCrossbowPower(ItemStack stack) { - return crossbowContainsProjectile(stack, Material.FIREWORK_ROCKET) ? 1.6 : 3.15; - } - - protected double getCrossbowPowerForTime(long ticks, ItemStack stack) { - double power = ticks / (double) getCrossbowChargeDuration(stack); - if (power > 1) { - power = 1; - } - - return power; - } - - protected boolean isCrossbowCharged(ItemStack stack) { - return stack.has(DataComponents.CHARGED_PROJECTILES) && - !Objects.requireNonNull(stack.get(DataComponents.CHARGED_PROJECTILES)).isEmpty(); - } - - protected ItemStack setCrossbowProjectile(ItemStack stack, @Nullable ItemStack projectile) { - return stack.with(DataComponents.CHARGED_PROJECTILES, projectile == null ? List.of() : List.of(projectile)); - } - - protected ItemStack setCrossbowProjectiles(ItemStack stack, ItemStack projectile1, - ItemStack projectile2, ItemStack projectile3) { - return stack.with(DataComponents.CHARGED_PROJECTILES, List.of(projectile1, projectile2, projectile3)); - } - - protected boolean crossbowContainsProjectile(ItemStack stack, Material projectile) { - List projectiles = stack.get(DataComponents.CHARGED_PROJECTILES); - if (projectiles == null) return false; - - for (ItemStack itemStack : projectiles) { - if (itemStack.material() == projectile) return true; - } - - return false; - } - - protected int getCrossbowUseDuration(ItemStack stack) { - return getCrossbowChargeDuration(stack) + 3; - } - - protected int getCrossbowChargeDuration(ItemStack stack) { - int quickCharge = stack.get(DataComponents.ENCHANTMENTS).level(Enchantment.QUICK_CHARGE); - return quickCharge == 0 ? 25 : 25 - 5 * quickCharge; - } - - protected SoundEvent getCrossbowStartSound(int quickCharge) { - return switch (quickCharge) { - case 1 -> SoundEvent.ITEM_CROSSBOW_QUICK_CHARGE_1; - case 2 -> SoundEvent.ITEM_CROSSBOW_QUICK_CHARGE_2; - case 3 -> SoundEvent.ITEM_CROSSBOW_QUICK_CHARGE_3; - default -> SoundEvent.ITEM_CROSSBOW_LOADING_START; - }; - } - - protected ItemStack loadCrossbowProjectiles(Player player, ItemStack stack) { - boolean multiShot = stack.get(DataComponents.ENCHANTMENTS).level(Enchantment.MULTISHOT) > 0; - - ItemStack projectileItem; - int projectileSlot; - - ProjectileItemFeature.ProjectileItem projectile = projectileItemFeature.getCrossbowProjectile(player); - if (projectile == null && player.getGameMode() == GameMode.CREATIVE) { - projectileItem = Arrow.DEFAULT_ARROW; - projectileSlot = -1; - } else if (projectile != null) { - projectileItem = projectile.stack(); - projectileSlot = projectile.slot(); - } else { - // Should not happen - return ItemStack.AIR; - } - - if (multiShot) { - stack = setCrossbowProjectiles(stack, projectileItem, projectileItem, projectileItem); - } else { - stack = setCrossbowProjectile(stack, projectileItem); - } - - if (player.getGameMode() != GameMode.CREATIVE && projectileSlot >= 0) { - player.getInventory().setItemStack(projectileSlot, projectileItem.withAmount(projectileItem.amount() - 1)); - } - - return stack; - } - - protected ItemStack performCrossbowShooting(Player player, PlayerHand hand, ItemStack stack, - double power, double spread) { - List projectiles = stack.get(DataComponents.CHARGED_PROJECTILES); - if (projectiles == null || projectiles.isEmpty()) return ItemStack.AIR; - - ItemStack projectile = projectiles.getFirst(); - if (!projectile.isAir()) { - shootCrossbowProjectile(player, hand, stack, projectile, 1.0F, power, spread, 0.0F); - } - - if (projectiles.size() > 2) { - ThreadLocalRandom random = ThreadLocalRandom.current(); - boolean firstHighPitch = random.nextBoolean(); - float firstPitch = getRandomShotPitch(firstHighPitch, random); - float secondPitch = getRandomShotPitch(!firstHighPitch, random); - - projectile = projectiles.get(1); - if (!projectile.isAir()) { - shootCrossbowProjectile(player, hand, stack, projectile, firstPitch, power, spread, -10.0F); - } - projectile = projectiles.get(2); - if (!projectile.isAir()) { - shootCrossbowProjectile(player, hand, stack, projectile, secondPitch, power, spread, 10.0F); - } - } - - return setCrossbowProjectile(stack, ItemStack.AIR); - } - - protected void shootCrossbowProjectile(Player player, PlayerHand hand, ItemStack crossbowStack, - ItemStack projectile, float soundPitch, - double power, double spread, float yaw) { - boolean firework = projectile.material() == Material.FIREWORK_ROCKET; - if (firework) return; //TODO firework - - AbstractArrow arrow = getCrossbowArrow(player, crossbowStack, projectile); - if (player.getGameMode() == GameMode.CREATIVE || yaw != 0.0) { - arrow.setPickupMode(AbstractArrow.PickupMode.CREATIVE_ONLY); - } - - //TODO fix velocity and yaw - Pos position = player.getPosition().add(0, player.getEyeHeight() - 0.1, 0); - arrow.setInstance(Objects.requireNonNull(player.getInstance()), position); - - position = position.withYaw(position.yaw() + yaw); - //Vec direction = position.direction(); - //position = position.add(direction).sub(0, 0.2, 0); //???????? - - //TODO probably use shootFromRotation - arrow.shootFrom(position, power, spread); - - itemDamageFeature.damageEquipment(player, hand == PlayerHand.MAIN ? - EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND, firework ? 3 : 1); - - ViewUtil.viewersAndSelf(player).playSound(Sound.sound( - SoundEvent.ITEM_CROSSBOW_SHOOT, Sound.Source.PLAYER, - 1.0f, soundPitch - ), player); - } - - protected AbstractArrow getCrossbowArrow(Player player, ItemStack crossbowStack, ItemStack projectile) { - AbstractArrow arrow = createArrow(projectile.withAmount(1), player); - arrow.setCritical(true); // Player shooter is always critical - arrow.setSound(SoundEvent.ITEM_CROSSBOW_HIT); - - int piercing = crossbowStack.get(DataComponents.ENCHANTMENTS).level(Enchantment.PIERCING); - if (piercing > 0) { - arrow.setPiercingLevel((byte) piercing); - } - - return arrow; - } - - protected float getRandomShotPitch(boolean high, ThreadLocalRandom random) { - float base = high ? 0.63F : 0.43F; - return 1.0F / (random.nextFloat() * 0.5F + 1.8F) + base; - } + public static final DefinedFeature DEFINED = new DefinedFeature<>( + FeatureType.CROSSBOW, VanillaCrossbowFeature::new, + FeatureType.ITEM_DAMAGE, FeatureType.EFFECT, FeatureType.ENCHANTMENT, FeatureType.PROJECTILE_ITEM, FeatureType.BLOCK + ); + + private static final Tag<@NotNull Boolean> START_SOUND_PLAYED = Tag.Transient("StartSoundPlayed"); + private static final Tag<@NotNull Boolean> MID_LOAD_SOUND_PLAYED = Tag.Transient("MidLoadSoundPlayed"); + + private static final double DEFAULT_POWER = 3.15; + private static final double FIREWORK_POWER = 1.6; + private static final float DEFAULT_SPREAD = 1.0f; + + private final FeatureConfiguration configuration; + + private ItemDamageFeature itemDamageFeature; + private EffectFeature effectFeature; + private EnchantmentFeature enchantmentFeature; + private ProjectileItemFeature projectileItemFeature; + private BlockFeature blockFeature; + + public VanillaCrossbowFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void initDependencies() { + this.itemDamageFeature = configuration.get(FeatureType.ITEM_DAMAGE); + this.effectFeature = configuration.get(FeatureType.EFFECT); + this.enchantmentFeature = configuration.get(FeatureType.ENCHANTMENT); + this.projectileItemFeature = configuration.get(FeatureType.PROJECTILE_ITEM); + this.blockFeature = configuration.get(FeatureType.BLOCK); + } + + @Override + public void init(EventNode<@NotNull EntityInstanceEvent> node) { + + // Player Loading the crossbow + node.addListener(PlayerBeginItemUseEvent.class, event -> { + var itemStack = event.getPlayer().getItemInHand(event.getHand()); + var player = event.getPlayer(); + if (itemStack.material() != Material.CROSSBOW) return; + + if (!isCrossbowCharged(itemStack) && projectileItemFeature.getCrossbowProjectile(player) == null && player.getGameMode() != GameMode.CREATIVE) { + event.setCancelled(true); + } + }); + + node.addListener(PlayerTickEvent.class, event -> { + Player player = event.getPlayer(); + var meta = (LivingEntityMeta) player.getEntityMeta(); + + // Check if player is actively charging a crossbow + if (!meta.isHandActive()) return; + + PlayerHand hand = meta.getActiveHand(); + ItemStack stack = player.getItemInHand(hand); + + if (stack.material() != Material.CROSSBOW) return; + if (isCrossbowCharged(stack)) return; // Already loaded + + // Calculate progress based on use time + long useTicks = player.getCurrentItemUseTime(); + int chargeDuration = getCrossbowChargeDuration(stack); + double progress = useTicks / (double) chargeDuration; + + int quickCharge = Objects.requireNonNull(stack.get(DataComponents.ENCHANTMENTS)).level(Enchantment.QUICK_CHARGE); + + Boolean startSoundPlayed = player.getTag(START_SOUND_PLAYED); + if (progress >= 0.2 && (startSoundPlayed == null || !startSoundPlayed)) { + SoundEvent startSound = getCrossbowStartSound(quickCharge); + ViewUtil.viewersAndSelf(player).playSound(Sound.sound( + startSound, Sound.Source.PLAYER, + 0.5f, 1.0f + ), player); + player.setTag(START_SOUND_PLAYED, true); + } + + Boolean midLoadSoundPlayed = player.getTag(MID_LOAD_SOUND_PLAYED); + SoundEvent midLoadSound = quickCharge == 0 ? SoundEvent.ITEM_CROSSBOW_LOADING_MIDDLE : null; + if (progress >= 0.5 && midLoadSound != null && (midLoadSoundPlayed == null || !midLoadSoundPlayed)) { + ViewUtil.viewersAndSelf(player).playSound(Sound.sound( + midLoadSound, Sound.Source.PLAYER, + 0.5f, 1.0f + ), player); + player.setTag(MID_LOAD_SOUND_PLAYED, true); + } + + if (progress >= 1) { + var chargedCrossbow = loadCrossbowProjectiles(player, stack); + player.setItemInHand(hand, chargedCrossbow); + event.getInstance().playSound(Sound.sound() + .type(SoundEvent.ITEM_CROSSBOW_LOADING_END) + .build(), + event.getPlayer().getPosition()); + player.removeTag(START_SOUND_PLAYED); + player.removeTag(MID_LOAD_SOUND_PLAYED); + } + }); + + node.addListener(PlayerCancelItemUseEvent.class, event -> { + var player = event.getPlayer(); + + player.removeTag(START_SOUND_PLAYED); + player.removeTag(MID_LOAD_SOUND_PLAYED); + }); + + // Shooting projectile from crossbow + node.addListener(PlayerUseItemEvent.class, event -> { + var player = event.getPlayer(); + var itemStack = event.getItemStack(); + if (itemStack.material() != Material.CROSSBOW) return; + if (!isCrossbowCharged(itemStack)) return; + + performCrossbowShooting(player, event.getHand(), itemStack); + }); + } + + protected AbstractArrow createArrow(ItemStack stack, @Nullable Entity shooter) { + if (stack.material() == Material.SPECTRAL_ARROW) { + return new SpectralArrow(shooter, enchantmentFeature); + } else { + Arrow arrow = new Arrow(shooter, effectFeature, enchantmentFeature); + arrow.setItemStack(stack); + return arrow; + } + } + + protected boolean isCrossbowCharged(ItemStack stack) { + return stack.has(DataComponents.CHARGED_PROJECTILES) && + !Objects.requireNonNull(stack.get(DataComponents.CHARGED_PROJECTILES)).isEmpty(); + } + + protected ItemStack setCrossbowProjectile(ItemStack stack, @NotNull List projectiles) { + return stack.with(DataComponents.CHARGED_PROJECTILES, projectiles); + } + + protected ItemStack setCrossbowProjectile(ItemStack stack, @NotNull ItemStack projectile) { + return stack.with(DataComponents.CHARGED_PROJECTILES, List.of(projectile)); + } + + protected boolean crossbowContainsProjectile(ItemStack stack, Material projectile) { + List projectiles = stack.get(DataComponents.CHARGED_PROJECTILES); + if (projectiles == null) return false; + + for (ItemStack itemStack : projectiles) { + if (itemStack.material() == projectile) return true; + } + + return false; + } + + protected int getCrossbowChargeDuration(ItemStack stack) { + int quickCharge = Objects.requireNonNull(stack.get(DataComponents.ENCHANTMENTS)).level(Enchantment.QUICK_CHARGE); + return Math.max(0, quickCharge == 0 ? 25 : 25 - 5 * quickCharge); + } + + protected SoundEvent getCrossbowStartSound(int quickCharge) { + return switch (quickCharge) { + case 1 -> SoundEvent.ITEM_CROSSBOW_QUICK_CHARGE_1; + case 2 -> SoundEvent.ITEM_CROSSBOW_QUICK_CHARGE_2; + case 3 -> SoundEvent.ITEM_CROSSBOW_QUICK_CHARGE_3; + default -> SoundEvent.ITEM_CROSSBOW_LOADING_START; + }; + } + + protected ItemStack loadCrossbowProjectiles(Player player, ItemStack stack) { + int multiShot = Objects.requireNonNull(stack.get(DataComponents.ENCHANTMENTS)).level(Enchantment.MULTISHOT); + + ItemStack projectileItem; + int projectileSlot; + + ProjectileItemFeature.ProjectileItem projectile = projectileItemFeature.getCrossbowProjectile(player); + if (projectile == null && player.getGameMode() == GameMode.CREATIVE) { + projectileItem = Arrow.DEFAULT_ARROW; + projectileSlot = -1; + } else if (projectile != null) { + projectileItem = projectile.stack(); + projectileSlot = projectile.slot(); + } else { + // Should not happen + return ItemStack.AIR; + } + + ArrayList projectiles = new ArrayList<>(List.of(projectileItem)); + if (multiShot > 0) { + for (int i = 0; i < multiShot; i++) { + projectiles.add(projectileItem); + projectiles.add(projectileItem); + } + } + stack = setCrossbowProjectile(stack, projectiles); + + if (player.getGameMode() != GameMode.CREATIVE && projectileSlot >= 0) { + player.getInventory().setItemStack(projectileSlot, projectileItem.withAmount(projectileItem.amount() - 1)); + } + + return stack; + } + + protected void performCrossbowShooting(Player player, PlayerHand hand, ItemStack stack) { + List projectiles = stack.get(DataComponents.CHARGED_PROJECTILES); + if (projectiles == null || projectiles.isEmpty()) return; + + var offsetYaw = 0.0f; + for (int turn = 0; turn < projectiles.size(); turn++) { + var projectile = projectiles.get(turn); + + var soundPitch = getSoundPitch(ThreadLocalRandom.current(), turn); + + if (turn == 0) { + shootCrossbowProjectile(player, hand, stack, projectile, soundPitch, offsetYaw); + offsetYaw += 10.0f; + } else { + if (turn % 2 == 1) { + shootCrossbowProjectile(player, hand, stack, projectile, soundPitch, offsetYaw); + } + if (turn % 2 == 0) { + shootCrossbowProjectile(player, hand, stack, projectile, soundPitch, -offsetYaw); + offsetYaw += 10.0f; + } + } + } + + player.setItemInHand(hand, setCrossbowProjectile(player.getItemInHand(hand), List.of())); + } + + protected void shootCrossbowProjectile(Player player, PlayerHand hand, ItemStack crossbowStack, + ItemStack projectile, float soundPitch, + float yaw) { + boolean isFirework = projectile.material() == Material.FIREWORK_ROCKET; + if (isFirework) { + FireworkRocketEntity firework = getFireworkRocket(player, projectile); + + Pos position = player.getPosition().add(0, player.getEyeHeight() - 0.1, 0); + position = position.add(position.direction().normalize().mul(0.1)); + + firework.setInstance(Objects.requireNonNull(player.getInstance()), position); + + firework.shootFromRotation(position.pitch(), position.yaw(), 0, FIREWORK_POWER, DEFAULT_SPREAD, yaw); + firework.setVelocity(firework.getVelocity() + .add(getRandomOffset(), getRandomOffset(), getRandomOffset()) + ); + } else { + AbstractArrow arrow = getCrossbowArrow(player, crossbowStack, projectile); + if (player.getGameMode() == GameMode.CREATIVE || yaw != 0.0) { + arrow.setPickupMode(AbstractArrow.PickupMode.CREATIVE_ONLY); + } + + Pos position = player.getPosition().add(0, player.getEyeHeight() - 0.1, 0); + + arrow.setInstance(Objects.requireNonNull(player.getInstance()), position); + + arrow.shootFromRotation(position.pitch(), position.yaw(), 0, DEFAULT_POWER, DEFAULT_SPREAD, yaw); + arrow.setVelocity(arrow.getVelocity() + .add(getRandomOffset(), getRandomOffset(), getRandomOffset()) + ); + + var direction = player.getPosition().direction().normalize(); + arrow.setView( + (float) Math.toDegrees(Math.atan2(direction.x(), direction.z())), + (float) Math.toDegrees(Math.asin(direction.y())) + ); + } + + itemDamageFeature.damageEquipment(player, + hand == PlayerHand.MAIN ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND, + isFirework ? 3 : 1); + + ViewUtil.viewersAndSelf(player).playSound(Sound.sound( + SoundEvent.ITEM_CROSSBOW_SHOOT, Sound.Source.PLAYER, + 1.0f, soundPitch + ), player); + } + + protected double getRandomOffset() { + return ThreadLocalRandom.current().nextDouble(-0.4, 0.4); + } + + // Multishot shoot sound being higher pitched or lower pitched randomly + private static float getSoundPitch(ThreadLocalRandom random, int index) { + return index == 0 ? 1.0F : getSoundPitch((index & 1) == 1, random); + } + + private static float getSoundPitch(boolean flag, ThreadLocalRandom random) { + float pitchOffset = flag ? 0.63F : 0.43F; + return 1.0F / (random.nextFloat() * 0.5F + 1.8F) + pitchOffset; + } + + protected AbstractArrow getCrossbowArrow(Player player, ItemStack crossbowStack, ItemStack projectile) { + AbstractArrow arrow = createArrow(projectile.withAmount(1), player); + arrow.setCritical(true); // Player shooter is always critical + arrow.setSound(SoundEvent.ITEM_CROSSBOW_HIT); + + int piercing = Objects.requireNonNull(crossbowStack.get(DataComponents.ENCHANTMENTS)).level(Enchantment.PIERCING); + if (piercing > 0) { + arrow.setPiercingLevel((byte) piercing); + } + + return arrow; + } + + protected FireworkRocketEntity getFireworkRocket(Player player, ItemStack projectile) { + return new FireworkRocketEntity(player, projectile, true, blockFeature); + } + } \ No newline at end of file diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaFireworkRocketFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaFireworkRocketFeature.java new file mode 100644 index 000000000..13172cac2 --- /dev/null +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaFireworkRocketFeature.java @@ -0,0 +1,82 @@ +package net.swofty.pvp.feature.projectile; + +import net.minestom.server.coordinate.Point; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.Player; +import net.minestom.server.event.EventNode; +import net.minestom.server.event.player.PlayerUseItemOnBlockEvent; +import net.minestom.server.event.trait.EntityInstanceEvent; +import net.minestom.server.instance.block.BlockFace; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.pvp.entity.projectile.FireworkRocketEntity; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.block.BlockFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import org.jetbrains.annotations.NotNull; + +/** + * Vanilla implementation of {@link FireworkRocketFeature} + */ +public class VanillaFireworkRocketFeature implements FireworkRocketFeature, RegistrableFeature { + + private final FeatureConfiguration configuration; + private BlockFeature blockFeature; + + public static final DefinedFeature DEFINED = new DefinedFeature<>( + FeatureType.FIREWORK, VanillaFireworkRocketFeature::new, + FeatureType.BLOCK + ); + + public VanillaFireworkRocketFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void initDependencies() { + this.blockFeature = configuration.get(FeatureType.BLOCK); + } + + @Override + public void init(EventNode<@NotNull EntityInstanceEvent> node) { + node.addListener(PlayerUseItemOnBlockEvent.class, event -> { + if (event.getItemStack().material() != Material.FIREWORK_ROCKET) return; + + Player player = event.getPlayer(); + ItemStack itemStack = event.getItemStack(); + + var offsetX = event.getCursorPosition().x(); + var offsetZ = event.getCursorPosition().z(); + Point position = getBlockPlacement( + event.getPosition().add(offsetX, 0, offsetZ), + event.getBlockFace()); + + FireworkRocketEntity fireworkRocketEntity = new FireworkRocketEntity( + player, + itemStack, + false, + blockFeature); + + fireworkRocketEntity.setInstance(event.getInstance(), position); + + if (player.getGameMode().equals(GameMode.CREATIVE)) return; + player.setItemInHand(event.getHand(), itemStack.withAmount(itemStack.amount() - 1)); + }); + + // TODO add plain PlayerUseItemEvent listener for elytra usage (need elytra first) + } + + private static Point getBlockPlacement(@NotNull Point position, BlockFace face) { + position = switch (face) { + case BlockFace.TOP -> position.add(0, 1, 0); + case BlockFace.BOTTOM -> position.add(0, -1, 0); + case BlockFace.NORTH -> position.add(0, 0, -1); + case BlockFace.SOUTH -> position.add(0, 0, 1); + case BlockFace.WEST -> position.add(-1, 0, 0); + case BlockFace.EAST -> position.add(1, 0, 0); + }; + return position; + } +} \ No newline at end of file diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaFishingRodFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaFishingRodFeature.java index b42c2cf0f..061739319 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaFishingRodFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaFishingRodFeature.java @@ -1,17 +1,5 @@ package net.swofty.pvp.feature.projectile; -import java.util.Objects; -import java.util.concurrent.ThreadLocalRandom; - -import net.swofty.pvp.entity.projectile.FishingBobber; -import net.swofty.pvp.events.FishingBobberRetrieveEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.item.ItemDamageFeature; -import net.swofty.pvp.utils.CombatVersion; -import net.swofty.pvp.utils.ViewUtil; import net.kyori.adventure.sound.Sound; import net.minestom.server.ServerFlag; import net.minestom.server.coordinate.Pos; @@ -29,6 +17,18 @@ import net.minestom.server.sound.SoundEvent; import net.minestom.server.tag.Tag; import net.minestom.server.utils.MathUtils; +import net.swofty.pvp.entity.projectile.FishingBobber; +import net.swofty.pvp.events.FishingBobberRetrieveEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.item.ItemDamageFeature; +import net.swofty.pvp.utils.CombatVersion; +import net.swofty.pvp.utils.ViewUtil; + +import java.util.Objects; +import java.util.concurrent.ThreadLocalRandom; /** * Vanilla implementation of {@link FishingRodFeature} @@ -38,42 +38,42 @@ public class VanillaFishingRodFeature implements FishingRodFeature, RegistrableF FeatureType.FISHING_ROD, VanillaFishingRodFeature::new, FeatureType.ITEM_DAMAGE, FeatureType.VERSION ); - + public static final Tag FISHING_BOBBER = Tag.Transient("fishingBobber"); - + private final FeatureConfiguration configuration; - + private ItemDamageFeature itemDamageFeature; private CombatVersion version; - + public VanillaFishingRodFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.itemDamageFeature = configuration.get(FeatureType.ITEM_DAMAGE); this.version = configuration.get(FeatureType.VERSION); } - + @Override public void init(EventNode node) { node.addListener(PlayerUseItemEvent.class, event -> { if (event.getItemStack().material() != Material.FISHING_ROD) return; - + ThreadLocalRandom random = ThreadLocalRandom.current(); Player player = event.getPlayer(); - + if (player.hasTag(FISHING_BOBBER)) { FishingBobber bobber = player.getTag(FISHING_BOBBER); - + FishingBobberRetrieveEvent retrieveEvent = new FishingBobberRetrieveEvent(player, bobber); EventDispatcher.callCancellable(retrieveEvent, () -> { int durability = bobber.retrieve(); if (player.getGameMode() != GameMode.CREATIVE) itemDamageFeature.damageEquipment(player, event.getHand() == PlayerHand.MAIN ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND, durability); - + ViewUtil.viewersAndSelf(player).playSound(Sound.sound( SoundEvent.ENTITY_FISHING_BOBBER_RETRIEVE, Sound.Source.NEUTRAL, 1.0f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) @@ -84,10 +84,10 @@ public void init(EventNode node) { SoundEvent.ENTITY_FISHING_BOBBER_THROW, Sound.Source.NEUTRAL, 0.5f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) ), player); - + FishingBobber bobber = new FishingBobber(player, version.legacy()); player.setTag(FISHING_BOBBER, bobber); - + EntityShootEvent shootEvent = new EntityShootEvent(player, bobber, player.getPosition(), 0, 1.0); EventDispatcher.call(shootEvent); @@ -96,20 +96,20 @@ public void init(EventNode node) { return; } double spread = shootEvent.getSpread() * (version.legacy() ? 0.0075 : 0.0045); - + Pos playerPos = player.getPosition(); float playerPitch = playerPos.pitch(); float playerYaw = playerPos.yaw(); - + float zDir = (float) Math.cos(Math.toRadians(-playerYaw) - Math.PI); float xDir = (float) Math.sin(Math.toRadians(-playerYaw) - Math.PI); double x = playerPos.x() - (double) xDir * 0.3D; double y = playerPos.y() + player.getEyeHeight(); double z = playerPos.z() - (double) zDir * 0.3D; bobber.setInstance(Objects.requireNonNull(player.getInstance()), new Pos(x, y, z)); - + Vec velocity; - + if (version.modern()) { velocity = new Vec( -xDir, @@ -144,7 +144,7 @@ public void init(EventNode node) { ) .mul(1.5); } - + //TODO fix velocity code bobber.setVelocity(velocity.mul(ServerFlag.SERVER_TICKS_PER_SECOND * 0.75)); } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaMiscProjectileFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaMiscProjectileFeature.java index 4df5de0b7..29a94c455 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaMiscProjectileFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaMiscProjectileFeature.java @@ -1,13 +1,5 @@ package net.swofty.pvp.feature.projectile; -import net.swofty.pvp.entity.projectile.*; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.cooldown.ItemCooldownFeature; -import net.swofty.pvp.feature.fall.FallFeature; -import net.swofty.pvp.utils.ViewUtil; import net.kyori.adventure.sound.Sound; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; @@ -19,6 +11,19 @@ import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.sound.SoundEvent; +import net.swofty.pvp.entity.projectile.CustomEntityProjectile; +import net.swofty.pvp.entity.projectile.ItemHoldingProjectile; +import net.swofty.pvp.entity.projectile.Snowball; +import net.swofty.pvp.entity.projectile.ThrownEgg; +import net.swofty.pvp.entity.projectile.ThrownEnderpearl; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.cooldown.ItemCooldownFeature; +import net.swofty.pvp.feature.fall.FallFeature; +import net.swofty.pvp.feature.provider.SoundProvider; +import net.swofty.pvp.utils.ViewUtil; import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; @@ -27,77 +32,83 @@ * Vanilla implementation of {@link MiscProjectileFeature} */ public class VanillaMiscProjectileFeature implements MiscProjectileFeature, RegistrableFeature { - public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.MISC_PROJECTILE, VanillaMiscProjectileFeature::new, - FeatureType.ITEM_COOLDOWN, FeatureType.FALL - ); - - private final FeatureConfiguration configuration; - - private ItemCooldownFeature itemCooldownFeature; - private FallFeature fallFeature; - - public VanillaMiscProjectileFeature(FeatureConfiguration configuration) { - this.configuration = configuration; - } - - @Override - public void initDependencies() { - this.itemCooldownFeature = configuration.get(FeatureType.ITEM_COOLDOWN); - this.fallFeature = configuration.get(FeatureType.FALL); - } - - @Override - public void init(EventNode node) { - node.addListener(PlayerUseItemEvent.class, event -> { - if (event.getItemStack().material() != Material.SNOWBALL - /*&& event.getItemStack().material() != Material.EGG*/ // UNOFFICIAL - use the net.swofty.pvp.projectile instead - && event.getItemStack().material() != Material.ENDER_PEARL) - return; - - Player player = event.getPlayer(); - ItemStack stack = event.getItemStack(); - - boolean snowball = stack.material() == Material.SNOWBALL; - boolean enderpearl = stack.material() == Material.ENDER_PEARL; - - SoundEvent soundEvent; - CustomEntityProjectile projectile; - if (snowball) { - soundEvent = SoundEvent.ENTITY_SNOWBALL_THROW; - projectile = new Snowball(player); - } else if (enderpearl) { - soundEvent = SoundEvent.ENTITY_ENDER_PEARL_THROW; - projectile = new ThrownEnderpearl(player, fallFeature); - } else { - soundEvent = SoundEvent.ENTITY_EGG_THROW; - projectile = new ThrownEgg(player); - } - - ((ItemHoldingProjectile) projectile).setItem(stack); - - ThreadLocalRandom random = ThreadLocalRandom.current(); - ViewUtil.viewersAndSelf(player).playSound(Sound.sound( - soundEvent, - snowball || enderpearl ? Sound.Source.NEUTRAL : Sound.Source.PLAYER, - 0.5f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) - ), player); - - if (enderpearl) { - itemCooldownFeature.setCooldown(player, Material.ENDER_PEARL, 20); - } - - Pos position = player.getPosition().add(0, player.getEyeHeight(), 0); - projectile.shootFromRotation(position.pitch(), position.yaw(), 0, 1.5, 1.0); - projectile.setInstance(Objects.requireNonNull(player.getInstance()), position.withView(projectile.getPosition())); - - Vec playerVel = player.getVelocity(); - projectile.setVelocity(projectile.getVelocity().add(playerVel.x(), - player.isOnGround() ? 0.0D : playerVel.y(), playerVel.z())); - - if (player.getGameMode() != GameMode.CREATIVE) { - player.setItemInHand(event.getHand(), stack.withAmount(stack.amount() - 1)); - } - }); - } + public static final DefinedFeature DEFINED = new DefinedFeature<>( + FeatureType.MISC_PROJECTILE, VanillaMiscProjectileFeature::new, + FeatureType.ITEM_COOLDOWN, FeatureType.FALL, FeatureType.SOUND + ); + + private final FeatureConfiguration configuration; + + private ItemCooldownFeature itemCooldownFeature; + private FallFeature fallFeature; + private SoundProvider soundProvider; + + public VanillaMiscProjectileFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void initDependencies() { + this.itemCooldownFeature = configuration.get(FeatureType.ITEM_COOLDOWN); + this.fallFeature = configuration.get(FeatureType.FALL); + this.soundProvider = configuration.get(FeatureType.SOUND); + } + + @Override + public void init(EventNode node) { + node.addListener(PlayerUseItemEvent.class, event -> { + if (event.getItemStack().material() != Material.SNOWBALL + /*&& event.getItemStack().material() != Material.EGG*/ // UNOFFICIAL - use the net.swofty.pvp.projectile instead + && event.getItemStack().material() != Material.ENDER_PEARL) + return; + + Player player = event.getPlayer(); + ItemStack stack = event.getItemStack(); + + boolean snowball = stack.material() == Material.SNOWBALL; + boolean enderpearl = stack.material() == Material.ENDER_PEARL; + + SoundEvent soundEvent; + CustomEntityProjectile projectile; + if (snowball) { + soundEvent = SoundEvent.ENTITY_SNOWBALL_THROW; + projectile = new Snowball(player); + } else if (enderpearl) { + soundEvent = SoundEvent.ENTITY_ENDER_PEARL_THROW; + projectile = new ThrownEnderpearl(player, fallFeature); + } else { + soundEvent = SoundEvent.ENTITY_EGG_THROW; + projectile = new ThrownEgg(player); + } + + ((ItemHoldingProjectile) projectile).setItem(stack); + + ThreadLocalRandom random = ThreadLocalRandom.current(); + soundProvider.playSound( + ViewUtil.viewersAndSelf(player), + Sound.sound( + soundEvent, + snowball || enderpearl ? Sound.Source.NEUTRAL : Sound.Source.PLAYER, + 0.5f, 0.4f / (random.nextFloat() * 0.4f + 0.8f) + ), + player.getPosition().x(), player.getPosition().y(), player.getPosition().z() + ); + + if (enderpearl) { + itemCooldownFeature.setCooldown(player, Material.ENDER_PEARL.name(), 20); + } + + Pos position = player.getPosition().add(0, player.getEyeHeight(), 0); + projectile.shootFromRotation(position.pitch(), position.yaw(), 0, 1.5, 1.0, 0.0); + projectile.setInstance(Objects.requireNonNull(player.getInstance()), position.withView(projectile.getPosition())); + + Vec playerVel = player.getVelocity(); + projectile.setVelocity(projectile.getVelocity().add(playerVel.x(), + player.isOnGround() ? 0.0D : playerVel.y(), playerVel.z())); + + if (player.getGameMode() != GameMode.CREATIVE) { + player.setItemInHand(event.getHand(), stack.withAmount(stack.amount() - 1)); + } + }); + } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaProjectileItemFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaProjectileItemFeature.java index 6fcd8e26b..f6fda1aa8 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaProjectileItemFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaProjectileItemFeature.java @@ -1,18 +1,17 @@ package net.swofty.pvp.feature.projectile; -import java.util.function.Predicate; - -import org.jetbrains.annotations.Nullable; - -import net.swofty.pvp.entity.projectile.Arrow; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.config.DefinedFeature; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; import net.minestom.server.entity.PlayerHand; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.utils.inventory.PlayerInventoryUtils; +import net.swofty.pvp.entity.projectile.Arrow; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.config.DefinedFeature; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Predicate; /** * Vanilla implementation of {@link ProjectileItemFeature} @@ -21,51 +20,51 @@ public class VanillaProjectileItemFeature implements ProjectileItemFeature { public static final DefinedFeature DEFINED = new DefinedFeature<>( FeatureType.PROJECTILE_ITEM, configuration -> new VanillaProjectileItemFeature() ); - + public static final Predicate ARROW_PREDICATE = stack -> stack.material() == Material.ARROW || stack.material() == Material.SPECTRAL_ARROW || stack.material() == Material.TIPPED_ARROW; - + public static final Predicate ARROW_OR_FIREWORK_PREDICATE = ARROW_PREDICATE.or(stack -> stack.material() == Material.FIREWORK_ROCKET); - + @Override public @Nullable ProjectileItem getBowProjectile(Player player) { return getProjectile(player, ARROW_PREDICATE, ARROW_PREDICATE); } - + @Override public @Nullable ProjectileItem getCrossbowProjectile(Player player) { return getProjectile(player, ARROW_OR_FIREWORK_PREDICATE, ARROW_PREDICATE); } - + public static @Nullable ProjectileItem getProjectile(Player player, Predicate heldSupportedPredicate, Predicate allSupportedPredicate) { ProjectileItem held = getHeldItem(player, heldSupportedPredicate); if (held != null) return held; - + ItemStack[] itemStacks = player.getInventory().getItemStacks(); for (int i = 0; i < itemStacks.length; i++) { ItemStack stack = itemStacks[i]; if (stack == null || stack.isAir()) continue; if (allSupportedPredicate.test(stack)) return new ProjectileItem(i, stack); } - + if (player.getGameMode() == GameMode.CREATIVE) { return new ProjectileItem(-1, Arrow.DEFAULT_ARROW); } else { return null; } } - + private static @Nullable ProjectileItem getHeldItem(Player player, Predicate predicate) { ItemStack stack = player.getItemInHand(PlayerHand.OFF); if (predicate.test(stack)) return new ProjectileItem(PlayerInventoryUtils.OFFHAND_SLOT, stack); - + stack = player.getItemInHand(PlayerHand.MAIN); if (predicate.test(stack)) return new ProjectileItem(player.getHeldSlot(), stack); - + return null; } } diff --git a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaTridentFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaTridentFeature.java index 07fea1850..4ad7d94e0 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaTridentFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/projectile/VanillaTridentFeature.java @@ -5,7 +5,11 @@ import net.minestom.server.component.DataComponents; import net.minestom.server.coordinate.Pos; import net.minestom.server.coordinate.Vec; -import net.minestom.server.entity.*; +import net.minestom.server.entity.EquipmentSlot; +import net.minestom.server.entity.GameMode; +import net.minestom.server.entity.LivingEntity; +import net.minestom.server.entity.Player; +import net.minestom.server.entity.PlayerHand; import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.EventNode; import net.minestom.server.event.entity.EntityAttackEvent; @@ -77,7 +81,7 @@ public void init(EventNode node) { ThrownTrident trident = new ThrownTrident(player, stack, enchantmentFeature); Pos position = player.getPosition().add(0, player.getEyeHeight() - 0.1, 0); - trident.shootFromRotation(position.pitch(), position.yaw(), 0, 2.5, 1.0); + trident.shootFromRotation(position.pitch(), position.yaw(), 0, 2.5, 1.0, 0.0); trident.setInstance(Objects.requireNonNull(player.getInstance()), position.withView(trident.getPosition())); Vec playerVel = player.getVelocity(); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/provider/PacketProvider.java b/pvp/src/main/java/net/swofty/pvp/feature/provider/PacketProvider.java new file mode 100644 index 000000000..0bdba0836 --- /dev/null +++ b/pvp/src/main/java/net/swofty/pvp/feature/provider/PacketProvider.java @@ -0,0 +1,12 @@ +package net.swofty.pvp.feature.provider; + +import net.minestom.server.Viewable; +import net.minestom.server.entity.Entity; +import net.minestom.server.network.packet.server.ServerPacket; +import net.swofty.pvp.feature.CombatFeature; + +public interface PacketProvider extends CombatFeature { + PacketProvider DEFAULT = Viewable::sendPacketToViewersAndSelf; + + void sendPacket(Entity viewable, ServerPacket.Play packet); +} diff --git a/pvp/src/main/java/net/swofty/pvp/feature/provider/SoundProvider.java b/pvp/src/main/java/net/swofty/pvp/feature/provider/SoundProvider.java new file mode 100644 index 000000000..09f61587a --- /dev/null +++ b/pvp/src/main/java/net/swofty/pvp/feature/provider/SoundProvider.java @@ -0,0 +1,13 @@ +package net.swofty.pvp.feature.provider; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.sound.Sound; +import net.swofty.pvp.feature.CombatFeature; +import org.jetbrains.annotations.NotNull; + +public interface SoundProvider extends CombatFeature { + SoundProvider DEFAULT = Audience::playSound; + + // TODO: support emitters + void playSound(Audience audience, final @NotNull Sound original, final double x, final double y, final double z); +} diff --git a/pvp/src/main/java/net/swofty/pvp/feature/spectate/VanillaSpectateFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/spectate/VanillaSpectateFeature.java index 7dca9c66c..3235b1b51 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/spectate/VanillaSpectateFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/spectate/VanillaSpectateFeature.java @@ -1,9 +1,5 @@ package net.swofty.pvp.feature.spectate; -import net.swofty.pvp.events.PlayerSpectateEvent; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; import net.minestom.server.entity.Entity; import net.minestom.server.entity.GameMode; import net.minestom.server.entity.LivingEntity; @@ -14,6 +10,10 @@ import net.minestom.server.event.player.PlayerTickEvent; import net.minestom.server.event.trait.EntityInstanceEvent; import net.minestom.server.tag.Tag; +import net.swofty.pvp.events.PlayerSpectateEvent; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; /** * Vanilla implementation of {@link SpectateFeature} @@ -22,41 +22,41 @@ public class VanillaSpectateFeature implements SpectateFeature, RegistrableFeatu public static final DefinedFeature DEFINED = new DefinedFeature<>( FeatureType.SPECTATE, configuration -> new VanillaSpectateFeature() ); - + public static final Tag SPECTATING = Tag.Transient("spectating"); - + @Override public int getPriority() { // Make sure events are called on this node before on VanillaAttackFeature // This seems to be the only way to have 'dependencies' without overcomplicating return -1; } - + @Override public void init(EventNode node) { node.addListener(EntityAttackEvent.class, event -> { if (event.getEntity() instanceof Player player && player.getGameMode() == GameMode.SPECTATOR) makeSpectate(player, event.getTarget()); }); - + node.addListener(PlayerTickEvent.class, event -> spectateTick(event.getPlayer())); } - + protected void spectateTick(Player player) { Entity spectating = player.getTag(SPECTATING); if (spectating == null || spectating == player) return; - + // This is to make sure other players don't see the player standing still while spectating // And when the player stops spectating, // they are at the entities position instead of their position before spectating player.teleport(spectating.getPosition()); - + if (player.getEntityMeta().isSneaking() || spectating.isRemoved() || (spectating instanceof LivingEntity livingSpectating && livingSpectating.isDead())) { stopSpectating(player); } } - + @Override public void makeSpectate(Player player, Entity target) { PlayerSpectateEvent playerSpectateEvent = new PlayerSpectateEvent(player, target); @@ -65,7 +65,7 @@ public void makeSpectate(Player player, Entity target) { player.setTag(SPECTATING, target); }); } - + @Override public void stopSpectating(Player player) { player.stopSpectating(); diff --git a/pvp/src/main/java/net/swofty/pvp/feature/totem/VanillaTotemFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/totem/VanillaTotemFeature.java index 5e5abfd85..6d388067a 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/totem/VanillaTotemFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/totem/VanillaTotemFeature.java @@ -13,7 +13,9 @@ import net.swofty.pvp.events.TotemUseEvent; import net.swofty.pvp.feature.FeatureType; import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; import net.swofty.pvp.feature.food.VanillaFoodFeature; +import net.swofty.pvp.feature.provider.SoundProvider; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; @@ -23,9 +25,21 @@ */ public class VanillaTotemFeature implements TotemFeature { public static final DefinedFeature DEFINED = new DefinedFeature<>( - FeatureType.TOTEM, configuration -> new VanillaTotemFeature() + FeatureType.TOTEM, VanillaTotemFeature::new, FeatureType.SOUND ); + private final FeatureConfiguration configuration; + private SoundProvider soundProvider; + + public VanillaTotemFeature(FeatureConfiguration configuration) { + this.configuration = configuration; + } + + @Override + public void initDependencies() { + this.soundProvider = configuration.get(FeatureType.SOUND); + } + @Override public boolean tryProtect(LivingEntity entity, DamageType type) { if (DamageTypeInfo.of(MinecraftServer.getDamageTypeRegistry().getKey(type)).outOfWorld()) return false; @@ -50,7 +64,7 @@ public boolean tryProtect(LivingEntity entity, DamageType type) { Random random = ThreadLocalRandom.current(); for (ConsumeEffect deathEffect : deathProtection.deathEffects()) { - VanillaFoodFeature.applyConsumeEffect(entity, deathEffect, random); + VanillaFoodFeature.applyConsumeEffect(entity, deathEffect, random, soundProvider); } // Totem particles diff --git a/pvp/src/main/java/net/swofty/pvp/feature/tracking/VanillaDeathMessageFeature.java b/pvp/src/main/java/net/swofty/pvp/feature/tracking/VanillaDeathMessageFeature.java index c6b56ea19..dd98f14a0 100644 --- a/pvp/src/main/java/net/swofty/pvp/feature/tracking/VanillaDeathMessageFeature.java +++ b/pvp/src/main/java/net/swofty/pvp/feature/tracking/VanillaDeathMessageFeature.java @@ -1,12 +1,5 @@ package net.swofty.pvp.feature.tracking; -import net.swofty.pvp.damage.combat.CombatManager; -import net.swofty.pvp.feature.FeatureType; -import net.swofty.pvp.feature.RegistrableFeature; -import net.swofty.pvp.feature.config.DefinedFeature; -import net.swofty.pvp.feature.config.FeatureConfiguration; -import net.swofty.pvp.feature.fall.FallFeature; -import net.swofty.pvp.feature.state.PlayerStateFeature; import net.kyori.adventure.text.Component; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Player; @@ -17,6 +10,13 @@ import net.minestom.server.event.player.PlayerTickEvent; import net.minestom.server.event.trait.EntityInstanceEvent; import net.minestom.server.tag.Tag; +import net.swofty.pvp.damage.combat.CombatManager; +import net.swofty.pvp.feature.FeatureType; +import net.swofty.pvp.feature.RegistrableFeature; +import net.swofty.pvp.feature.config.DefinedFeature; +import net.swofty.pvp.feature.config.FeatureConfiguration; +import net.swofty.pvp.feature.fall.FallFeature; +import net.swofty.pvp.feature.state.PlayerStateFeature; import org.jetbrains.annotations.Nullable; /** @@ -28,47 +28,47 @@ public class VanillaDeathMessageFeature implements TrackingFeature, RegistrableF VanillaDeathMessageFeature::initPlayer, FeatureType.FALL, FeatureType.PLAYER_STATE ); - + public static final Tag COMBAT_MANAGER = Tag.Transient("combatManager"); - + private final FeatureConfiguration configuration; - + private FallFeature fallFeature; private PlayerStateFeature playerStateFeature; - + public VanillaDeathMessageFeature(FeatureConfiguration configuration) { this.configuration = configuration; } - + @Override public void initDependencies() { this.fallFeature = configuration.get(FeatureType.FALL); this.playerStateFeature = configuration.get(FeatureType.PLAYER_STATE); } - + public static void initPlayer(Player player, boolean firstInit) { if (firstInit) player.setTag(COMBAT_MANAGER, new CombatManager(player)); } - + @Override public void init(EventNode node) { node.addListener(PlayerSpawnEvent.class, event -> event.getPlayer().getTag(COMBAT_MANAGER).reset()); - + node.addListener(PlayerTickEvent.class, event -> event.getPlayer().getTag(COMBAT_MANAGER).tick()); - + node.addListener(PlayerDeathEvent.class, event -> { Component message = getDeathMessage(event.getPlayer()); event.setChatMessage(message); event.setDeathText(message); }); } - + @Override public void recordDamage(Player player, @Nullable Entity attacker, Damage damage) { int id = attacker == null ? -1 : attacker.getEntityId(); player.getTag(COMBAT_MANAGER).recordDamage(id, damage, fallFeature, playerStateFeature); } - + @Override public @Nullable Component getDeathMessage(Player player) { return player.getTag(COMBAT_MANAGER).getDeathMessage(); diff --git a/pvp/src/main/java/net/swofty/pvp/projectile/BowModule.java b/pvp/src/main/java/net/swofty/pvp/projectile/BowModule.java index 9fa767b59..745db4ffa 100644 --- a/pvp/src/main/java/net/swofty/pvp/projectile/BowModule.java +++ b/pvp/src/main/java/net/swofty/pvp/projectile/BowModule.java @@ -1,6 +1,5 @@ package net.swofty.pvp.projectile; -import net.swofty.pvp.projectile.entities.ArrowProjectile; import net.kyori.adventure.sound.Sound; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Player; @@ -12,6 +11,8 @@ import net.minestom.server.item.Material; import net.minestom.server.sound.SoundEvent; import net.minestom.server.tag.Tag; +import net.swofty.pvp.feature.provider.SoundProvider; +import net.swofty.pvp.projectile.entities.ArrowProjectile; import org.jetbrains.annotations.NotNull; import java.util.concurrent.ThreadLocalRandom; @@ -21,8 +22,10 @@ public class BowModule { private static final Tag CHARGE_SINCE_TAG = Tag.Long("bow_charge_since").defaultValue(Long.MAX_VALUE); private static final Tag BOW_POWER = Tag.Double("bow_power").defaultValue(0.0); + private SoundProvider soundProvider; public BowModule(@NotNull EventNode node, BiFunction arrowSupplier) { + this.soundProvider = SoundProvider.DEFAULT; node.addListener(PlayerBeginItemUseEvent.class, event -> { if (event.getItemStack().material() != Material.BOW) return; event.getPlayer().setTag(CHARGE_SINCE_TAG, System.currentTimeMillis()); @@ -30,7 +33,7 @@ public BowModule(@NotNull EventNode node, BiFunction { if (event.getItemStack().material() != Material.BOW) return; Player player = event.getPlayer(); - long duration = System.currentTimeMillis()-player.getTag(CHARGE_SINCE_TAG); + long duration = System.currentTimeMillis() - player.getTag(CHARGE_SINCE_TAG); double power = getPower(duration); if (power < 0.1) return; @@ -39,14 +42,27 @@ public BowModule(@NotNull EventNode node, BiFunction node, BiFunction arrowSupplier, SoundProvider soundProvider) { + this(node, arrowSupplier); + this.soundProvider = soundProvider; + } + + private void playShootSound(Player audience, double power) { + soundProvider.playSound( + audience, + Sound.sound(SoundEvent.ENTITY_ARROW_SHOOT, Sound.Source.PLAYER, 1f, getRandomPitchFromPower(power)), + audience.getPosition().x(), audience.getPosition().y(), audience.getPosition().z() + ); + } + private double getPower(long duration) { - double secs = duration/1000.0; + double secs = duration / 1000.0; double pow = (secs * secs + secs * 2.0) / 3.0; if (pow > 1) { pow = 1; diff --git a/pvp/src/main/java/net/swofty/pvp/utils/FluidUtil.java b/pvp/src/main/java/net/swofty/pvp/utils/FluidUtil.java index 5ca86f4de..38832c5cd 100644 --- a/pvp/src/main/java/net/swofty/pvp/utils/FluidUtil.java +++ b/pvp/src/main/java/net/swofty/pvp/utils/FluidUtil.java @@ -1,6 +1,7 @@ package net.swofty.pvp.utils; import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.Player; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; @@ -90,4 +91,36 @@ public static boolean isTouchingWater(Player player) { return false; } + + /** + * Checks if a LivingEntity is touching water. + * This is used for critical hit detection in legacy 1.8.9 mode. + * + * @param entity The entity to check + * @return true if the entity is touching water + */ + public static boolean isTouchingWater(LivingEntity entity) { + if (entity instanceof Player player) { + return isTouchingWater(player); + } + + // For non-player entities, check the blocks at their position + Pos position = entity.getPosition(); + int blockX = position.blockX(); + int blockZ = position.blockZ(); + int blockY = position.blockY(); + + Instance instance = entity.getInstance(); + if (instance == null) return false; + + // Check current block and blocks above + for (int yOff = 0; yOff <= 2; yOff++) { + Block block = instance.getBlock(blockX, blockY + yOff, blockZ); + if (block.compare(Block.WATER)) { + return true; + } + } + + return false; + } } \ No newline at end of file diff --git a/server/proxy/velocity.jar b/server/proxy/velocity.jar index 09a0a0c1d..7bcc3bb92 100644 Binary files a/server/proxy/velocity.jar and b/server/proxy/velocity.jar differ diff --git a/service.api/build.gradle.kts b/service.api/build.gradle.kts index 27981c5ed..d081a84a4 100644 --- a/service.api/build.gradle.kts +++ b/service.api/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.auctionhouse/build.gradle.kts b/service.auctionhouse/build.gradle.kts index bd49f0610..40f80420d 100644 --- a/service.auctionhouse/build.gradle.kts +++ b/service.auctionhouse/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionActiveDatabase.java b/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionActiveDatabase.java index f8be62b4b..8779541bd 100644 --- a/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionActiveDatabase.java +++ b/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionActiveDatabase.java @@ -2,11 +2,16 @@ import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; -import com.mongodb.client.*; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; import net.swofty.service.generic.MongoDB; import org.bson.Document; +import org.jspecify.annotations.NonNull; import java.util.ArrayList; import java.util.List; @@ -17,7 +22,7 @@ public record AuctionActiveDatabase(String auctionId) implements MongoDB { public static MongoCollection collection; @Override - public MongoDB connect(String connectionString) { + public @NonNull MongoDB connect(@NonNull String connectionString) { ConnectionString cs = new ConnectionString(connectionString); MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); client = MongoClients.create(settings); @@ -28,12 +33,12 @@ public MongoDB connect(String connectionString) { } @Override - public void set(String key, Object value) { + public void set(@NonNull String key, Object value) { insertOrUpdate(key, value); } @Override - public Object get(String key, Object def) { + public Object get(@NonNull String key, Object def) { Document doc = collection.find(Filters.eq("_id", auctionId)).first(); if (doc == null) { return def; @@ -56,7 +61,7 @@ public Document getDocument() { } @Override - public boolean remove(String id) { + public boolean remove(@NonNull String id) { Document query = new Document("_id", id); Document found = collection.find(query).first(); @@ -68,7 +73,7 @@ public boolean remove(String id) { return true; } - public void insertOrUpdate(String key, Object value) { + public void insertOrUpdate(@NonNull String key, Object value) { if (exists()) { Document query = new Document("_id", auctionId); Document found = collection.find(query).first(); diff --git a/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionInactiveDatabase.java b/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionInactiveDatabase.java index 3506f3810..8da9068bd 100644 --- a/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionInactiveDatabase.java +++ b/service.auctionhouse/src/main/java/net/swofty/service/auction/AuctionInactiveDatabase.java @@ -2,11 +2,16 @@ import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; -import com.mongodb.client.*; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; import net.swofty.service.generic.MongoDB; import org.bson.Document; +import org.jspecify.annotations.NonNull; import java.util.ArrayList; import java.util.List; @@ -17,7 +22,7 @@ public record AuctionInactiveDatabase(String auctionId) implements MongoDB { public static MongoCollection collection; @Override - public MongoDB connect(String connectionString) { + public @NonNull MongoDB connect(@NonNull String connectionString) { ConnectionString cs = new ConnectionString(connectionString); MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); client = MongoClients.create(settings); @@ -28,12 +33,12 @@ public MongoDB connect(String connectionString) { } @Override - public void set(String key, Object value) { + public void set(@NonNull String key, Object value) { insertOrUpdate(key, value); } @Override - public Object get(String key, Object def) { + public Object get(@NonNull String key, Object def) { Document doc = collection.find(Filters.eq("_id", auctionId)).first(); if (doc == null) { return def; @@ -56,7 +61,7 @@ public Document getDocument() { } @Override - public boolean remove(String id) { + public boolean remove(@NonNull String id) { Document query = new Document("_id", id); Document found = collection.find(query).first(); @@ -68,7 +73,7 @@ public boolean remove(String id) { return true; } - public void insertOrUpdate(String key, Object value) { + public void insertOrUpdate(@NonNull String key, Object value) { if (exists()) { Document query = new Document("_id", auctionId); Document found = collection.find(query).first(); diff --git a/service.bazaar/build.gradle.kts b/service.bazaar/build.gradle.kts index 0690ef80e..8352df74c 100644 --- a/service.bazaar/build.gradle.kts +++ b/service.bazaar/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.darkauction/src/main/java/net/swofty/service/darkauction/DarkAuctionService.java b/service.darkauction/src/main/java/net/swofty/service/darkauction/DarkAuctionService.java index 4d705382e..306711e71 100644 --- a/service.darkauction/src/main/java/net/swofty/service/darkauction/DarkAuctionService.java +++ b/service.darkauction/src/main/java/net/swofty/service/darkauction/DarkAuctionService.java @@ -10,7 +10,7 @@ public class DarkAuctionService implements SkyBlockService { private static DarkAuctionState currentAuction = null; - static void main(String[] args) { + public static void main(String[] args) { SkyBlockService.init(new DarkAuctionService()); // Start the scheduler that checks SkyBlock time diff --git a/service.datamutex/build.gradle.kts b/service.datamutex/build.gradle.kts index f55e9726f..11c6c5ace 100644 --- a/service.datamutex/build.gradle.kts +++ b/service.datamutex/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java b/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java index ef48f8c2f..df4feb1b8 100644 --- a/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java +++ b/service.elections/src/main/java/net/swofty/service/election/ElectionDatabase.java @@ -11,6 +11,7 @@ import com.mongodb.client.model.Updates; import net.swofty.service.generic.MongoDB; import org.bson.Document; +import org.jspecify.annotations.NonNull; import java.util.HashMap; import java.util.List; @@ -24,7 +25,7 @@ public record ElectionDatabase(String key) implements MongoDB { public static MongoCollection talliesCollection; @Override - public MongoDB connect(String connectionString) { + public @NonNull MongoDB connect(@NonNull String connectionString) { ConnectionString cs = new ConnectionString(connectionString); MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); client = MongoClients.create(settings); @@ -37,7 +38,7 @@ public MongoDB connect(String connectionString) { } @Override - public void set(String key, Object value) { + public void set(@NonNull String key, Object value) { insertOrUpdate(key, value); } @@ -49,14 +50,14 @@ public boolean exists() { } @Override - public Object get(String key, Object def) { + public Object get(@NonNull String key, Object def) { Document doc = electionCollection.find(Filters.eq("_id", this.key)).first(); if (doc == null) return def; return doc.get(key); } @Override - public void insertOrUpdate(String key, Object value) { + public void insertOrUpdate(@NonNull String key, Object value) { Document doc = new Document("_id", this.key).append(key, value); electionCollection.replaceOne( Filters.eq("_id", this.key), @@ -66,7 +67,7 @@ public void insertOrUpdate(String key, Object value) { } @Override - public boolean remove(String id) { + public boolean remove(@NonNull String id) { Document query = new Document("_id", id); Document found = electionCollection.find(query).first(); if (found == null) return false; diff --git a/service.friend/build.gradle.kts b/service.friend/build.gradle.kts index ee385ed64..ffa7fb3c8 100644 --- a/service.friend/build.gradle.kts +++ b/service.friend/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.friend/src/main/java/net/swofty/service/friend/FriendCache.java b/service.friend/src/main/java/net/swofty/service/friend/FriendCache.java index 5cd5ee6a8..e6953c704 100644 --- a/service.friend/src/main/java/net/swofty/service/friend/FriendCache.java +++ b/service.friend/src/main/java/net/swofty/service/friend/FriendCache.java @@ -5,6 +5,7 @@ import net.swofty.commons.friend.*; import net.swofty.commons.friend.events.*; import net.swofty.commons.friend.events.response.*; +import net.swofty.commons.presence.PresenceInfo; import net.swofty.commons.protocol.objects.friend.FriendEventPushProtocol; import net.swofty.commons.protocol.objects.messaging.SendMessagePushProtocol; import net.swofty.service.generic.redis.ServiceToServerManager; @@ -294,7 +295,7 @@ public static void handleListRequest(FriendListRequestEvent event) { int totalFriends = friends.size(); int totalPages = Math.max(1, (int) Math.ceil((double) totalFriends / FRIENDS_PER_PAGE)); - page = Math.max(1, Math.min(page, totalPages)); + page = Math.clamp(page, 1, totalPages); int startIndex = (page - 1) * FRIENDS_PER_PAGE; int endIndex = Math.min(startIndex + FRIENDS_PER_PAGE, totalFriends); @@ -341,7 +342,7 @@ public static void handleRequestsListRequest(FriendRequestsListEvent event) { int totalRequests = requests.size(); int totalPages = Math.max(1, (int) Math.ceil((double) totalRequests / FRIENDS_PER_PAGE)); - page = Math.max(1, Math.min(page, totalPages)); + page = Math.clamp(page, 1, totalPages); int startIndex = (page - 1) * FRIENDS_PER_PAGE; int endIndex = Math.min(startIndex + FRIENDS_PER_PAGE, totalRequests); @@ -376,7 +377,7 @@ public static void handlePlayerJoin(UUID playerUuid, String playerName) { FriendData playerData = getFriendData(playerUuid); for (Friend friend : playerData.getFriends()) { - net.swofty.commons.presence.PresenceInfo friendPresence = PresenceStorage.get(friend.getUuid()); + PresenceInfo friendPresence = PresenceStorage.get(friend.getUuid()); if (friendPresence == null || !friendPresence.isOnline()) continue; FriendData friendData = cachedFriendData.get(friend.getUuid()); @@ -392,7 +393,7 @@ public static void handlePlayerJoin(UUID playerUuid, String playerName) { } public static void handlePlayerLeave(UUID playerUuid, String playerName) { - PresenceStorage.upsertPreservingServer(new net.swofty.commons.presence.PresenceInfo( + PresenceStorage.upsertPreservingServer(new PresenceInfo( playerUuid, false, null, diff --git a/service.friend/src/main/java/net/swofty/service/friend/FriendDatabase.java b/service.friend/src/main/java/net/swofty/service/friend/FriendDatabase.java index 5cc1375c5..c7143a09a 100644 --- a/service.friend/src/main/java/net/swofty/service/friend/FriendDatabase.java +++ b/service.friend/src/main/java/net/swofty/service/friend/FriendDatabase.java @@ -2,13 +2,18 @@ import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; -import com.mongodb.client.*; +import com.mongodb.client.FindIterable; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; import net.swofty.commons.friend.FriendData; import net.swofty.commons.friend.PendingFriendRequest; import net.swofty.service.generic.MongoDB; import org.bson.Document; +import org.jspecify.annotations.NonNull; import java.util.ArrayList; import java.util.List; @@ -21,7 +26,7 @@ public record FriendDatabase(String playerId) implements MongoDB { public static MongoCollection pendingRequestsCollection; @Override - public MongoDB connect(String connectionString) { + public @NonNull MongoDB connect(@NonNull String connectionString) { ConnectionString cs = new ConnectionString(connectionString); MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); client = MongoClients.create(settings); @@ -119,12 +124,12 @@ public PendingFriendRequest getPendingRequest(UUID from, UUID to) { } @Override - public void set(String key, Object value) { + public void set(@NonNull String key, Object value) { insertOrUpdate(key, value); } @Override - public Object get(String key, Object def) { + public Object get(@NonNull String key, Object def) { Document doc = friendDataCollection.find(Filters.eq("_id", playerId)).first(); if (doc == null) { return def; @@ -133,7 +138,7 @@ public Object get(String key, Object def) { } @Override - public void insertOrUpdate(String key, Object value) { + public void insertOrUpdate(@NonNull String key, Object value) { if (exists()) { Document query = new Document("_id", playerId); Document found = friendDataCollection.find(query).first(); @@ -147,7 +152,7 @@ public void insertOrUpdate(String key, Object value) { } @Override - public boolean remove(String id) { + public boolean remove(@NonNull String id) { Document query = new Document("_id", id); Document found = friendDataCollection.find(query).first(); if (found == null) { diff --git a/service.friend/src/main/java/net/swofty/service/friend/FriendService.java b/service.friend/src/main/java/net/swofty/service/friend/FriendService.java index c19bee4b1..f94d16d40 100644 --- a/service.friend/src/main/java/net/swofty/service/friend/FriendService.java +++ b/service.friend/src/main/java/net/swofty/service/friend/FriendService.java @@ -9,7 +9,7 @@ public class FriendService implements SkyBlockService { - static void main(String[] args) { + static void main() { String mongoUri = ConfigProvider.settings().getMongodb(); new FriendDatabase(null).connect(mongoUri); diff --git a/service.generic/src/main/java/net/swofty/service/generic/MongoDB.java b/service.generic/src/main/java/net/swofty/service/generic/MongoDB.java index 8dd71f364..93ed57dd3 100644 --- a/service.generic/src/main/java/net/swofty/service/generic/MongoDB.java +++ b/service.generic/src/main/java/net/swofty/service/generic/MongoDB.java @@ -1,15 +1,20 @@ package net.swofty.service.generic; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + public interface MongoDB { - MongoDB connect(String connectionString); + @NotNull + MongoDB connect(@NotNull String connectionString); - void set(String key, Object value); + void set(@NotNull String key, @Nullable Object value); - Object get(String key, Object def); + @Nullable + Object get(@NotNull String key, @Nullable Object def); - void insertOrUpdate(String key, Object value); + void insertOrUpdate(@NotNull String key, @Nullable Object value); - boolean remove(String id); + boolean remove(@NotNull String id); boolean exists(); -} +} \ No newline at end of file diff --git a/service.generic/src/main/java/net/swofty/service/generic/redis/ServiceToServerManager.java b/service.generic/src/main/java/net/swofty/service/generic/redis/ServiceToServerManager.java index 1c690599d..3b4f00aa7 100644 --- a/service.generic/src/main/java/net/swofty/service/generic/redis/ServiceToServerManager.java +++ b/service.generic/src/main/java/net/swofty/service/generic/redis/ServiceToServerManager.java @@ -204,4 +204,14 @@ public static CompletableFuture> return sendToServers(List.of(serverUUID), GAME_INFORMATION_PROTOCOL, new GameInformationPushProtocol.Request(playerUUID, gameId)); } + + private static final net.swofty.commons.protocol.objects.game.ViewReplayPushProtocol VIEW_REPLAY_PROTOCOL = new net.swofty.commons.protocol.objects.game.ViewReplayPushProtocol(); + + public static CompletableFuture> viewReplay(UUID playerUUID, String gameId) { + return viewReplay(playerUUID, gameId, null); + } + + public static CompletableFuture> viewReplay(UUID playerUUID, String gameId, String shareCode) { + return sendToAllServers(VIEW_REPLAY_PROTOCOL, new net.swofty.commons.protocol.objects.game.ViewReplayPushProtocol.Request(playerUUID, gameId, shareCode), 300); + } } \ No newline at end of file diff --git a/service.guild/build.gradle.kts b/service.guild/build.gradle.kts new file mode 100644 index 000000000..710b93149 --- /dev/null +++ b/service.guild/build.gradle.kts @@ -0,0 +1,47 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + java + application + id("com.gradleup.shadow") version "9.3.1" +} + +group = "net.swofty" +version = "3.0" + +java { + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 + toolchain { + languageVersion.set(JavaLanguageVersion.of(25)) + } +} + +repositories { + maven("https://jitpack.io") + mavenCentral() +} + +dependencies { + implementation(project(":service.generic")) + implementation(project(":commons")) + implementation(libs.caffeine) + implementation(libs.tinylog.api) + implementation(libs.tinylog.impl) + implementation(libs.mongodb.bson) + implementation(libs.mongodb.driver.sync) + implementation(libs.annotations) + annotationProcessor(libs.annotations) +} + +application { + mainClass.set("net.swofty.service.guild.GuildService") +} + +tasks { + named("shadowJar") { + archiveBaseName.set("ServiceGuild") + archiveClassifier.set("") + archiveVersion.set("") + } +} diff --git a/service.guild/src/main/java/net/swofty/service/guild/GuildCache.java b/service.guild/src/main/java/net/swofty/service/guild/GuildCache.java new file mode 100644 index 000000000..fd2eb2892 --- /dev/null +++ b/service.guild/src/main/java/net/swofty/service/guild/GuildCache.java @@ -0,0 +1,727 @@ +package net.swofty.service.guild; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildEvent; +import net.swofty.commons.guild.GuildMember; +import net.swofty.commons.guild.GuildPermission; +import net.swofty.commons.guild.GuildRank; +import net.swofty.commons.guild.events.*; +import net.swofty.commons.guild.events.response.*; +import net.swofty.commons.protocol.objects.guild.GuildEventPushProtocol; +import net.swofty.commons.protocol.objects.messaging.SendMessagePushProtocol; +import net.swofty.service.generic.redis.ServiceToServerManager; +import org.jetbrains.annotations.NotNull; + +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +public class GuildCache { + private static final DateTimeFormatter LOG_DATE = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm z"); + private static final Cache guildCache = Caffeine.newBuilder() + .maximumSize(10_000) + .expireAfterAccess(30, TimeUnit.MINUTES) + .build(); + + private static final Map pendingInvites = new ConcurrentHashMap<>(); + private static final Map lastChatTimestamps = new ConcurrentHashMap<>(); + + public static boolean isInGuild(final @NotNull UUID playerUUID) { + Objects.requireNonNull(playerUUID, "playerUUID cannot be null"); + + return getGuildFromPlayer(playerUUID) != null; + } + + public static GuildData getGuildFromPlayer(final @NotNull UUID playerUUID) { + Objects.requireNonNull(playerUUID, "playerUUID cannot be null"); + + UUID guildId = GuildDatabase.getPlayerGuildId(playerUUID); + if (guildId == null) return null; + GuildData guild = getGuild(guildId); + if (guild == null) { + GuildDatabase.removePlayerMapping(playerUUID); + } + return guild; + } + + public static GuildData getGuild(final @NotNull UUID guildId) { + return guildCache.get(guildId, GuildDatabase::getGuild); + } + + public static void handleCreateRequest(final GuildCreateRequestEvent event) { + final UUID creator = event.getCreator(); + final String guildName = event.getGuildName(); + + if (isInGuild(creator)) { + sendErrorToPlayer(creator, "§cYou are already in a guild! Leave your current guild to create a new one."); + return; + } + + if (guildName.length() < 3 || guildName.length() > 30) { + sendErrorToPlayer(creator, "§cGuild name must be between 3 and 30 characters."); + return; + } + + if (GuildDatabase.guildNameExists(guildName)) { + sendErrorToPlayer(creator, "§cA guild with that name already exists!"); + return; + } + + final GuildData guild = new GuildData(UUID.randomUUID(), guildName, creator); + persistGuild(guild); + GuildDatabase.mapPlayerToGuild(creator, guild.getGuildId()); + + GuildCreatedResponseEvent response = new GuildCreatedResponseEvent(guild, creator); + sendEvent(response); + } + + public static void handleInviteRequest(GuildInviteRequestEvent event) { + UUID inviter = event.getInviter(); + UUID invitee = event.getInvitee(); + + GuildData guild = getGuildFromPlayer(inviter); + if (guild == null) { + sendErrorToPlayer(inviter, "§cYou are not in a guild!"); + return; + } + + GuildRank inviterRank = guild.getMemberRank(inviter); + if (inviterRank == null || !inviterRank.hasPermission(GuildPermission.INVITE)) { + sendErrorToPlayer(inviter, "§cYou do not have permission to invite players!"); + return; + } + + if (guild.isFull()) { + sendErrorToPlayer(inviter, "§cYour guild is full!"); + return; + } + + if (isInGuild(invitee)) { + sendErrorToPlayer(inviter, "§cThat player is already in a guild!"); + return; + } + + if (pendingInvites.containsKey(invitee)) { + sendErrorToPlayer(inviter, "§cThat player already has a pending guild invite!"); + return; + } + + PendingGuildInvite invite = new PendingGuildInvite(guild.getGuildId(), inviter, invitee); + pendingInvites.put(invitee, invite); + scheduleInviteExpiration(guild.getGuildId(), inviter, invitee, 60000); + log(guild, "§a" + inviter + "§7 invited §e" + invitee); + persistGuild(guild); + + GuildInviteSentResponseEvent response = new GuildInviteSentResponseEvent(guild, inviter, invitee); + sendEvent(response); + } + + public static void handleAcceptInvite(GuildAcceptInviteRequestEvent event) { + UUID accepter = event.getAccepter(); + UUID inviter = event.getInviter(); + + PendingGuildInvite invite = pendingInvites.get(accepter); + if (invite == null || !invite.inviter().equals(inviter)) { + sendErrorToPlayer(accepter, "§cYou don't have a pending invite from that player, or it has expired!"); + return; + } + + if (isInGuild(accepter)) { + sendErrorToPlayer(accepter, "§cYou must leave your current guild before joining another!"); + return; + } + + GuildData guild = getGuild(invite.guildId()); + if (guild == null) { + sendErrorToPlayer(accepter, "§cThe guild no longer exists!"); + pendingInvites.remove(accepter); + return; + } + + if (guild.isFull()) { + sendErrorToPlayer(accepter, "§cThe guild is now full!"); + pendingInvites.remove(accepter); + return; + } + + GuildMember newMember = new GuildMember(accepter, "Member", System.currentTimeMillis()); + guild.getMembers().add(newMember); + log(guild, "§a" + accepter + "§7 joined"); + pendingInvites.remove(accepter); + + persistGuild(guild); + GuildDatabase.mapPlayerToGuild(accepter, guild.getGuildId()); + + GuildMemberJoinedResponseEvent response = new GuildMemberJoinedResponseEvent(guild, accepter); + sendEvent(response); + } + + public static void handleLeaveRequest(GuildLeaveRequestEvent event) { + UUID leaver = event.getLeaver(); + + GuildData guild = getGuildFromPlayer(leaver); + if (guild == null) { + sendErrorToPlayer(leaver, "§cYou are not in a guild!"); + return; + } + + if (guild.getMasterUuid().equals(leaver)) { + sendErrorToPlayer(leaver, "§cYou cannot leave a guild as the Guild Master! Transfer ownership first or disband the guild."); + return; + } + + GuildMember member = guild.getMember(leaver); + guild.getMembers().remove(member); + log(guild, "§a" + leaver + "§7 left"); + + persistGuild(guild); + GuildDatabase.removePlayerMapping(leaver); + + GuildMemberLeftResponseEvent response = new GuildMemberLeftResponseEvent(guild, leaver); + sendEvent(response); + } + + public static void handleKickRequest(GuildKickRequestEvent event) { + UUID kicker = event.getKicker(); + UUID target = event.getTarget(); + String reason = event.getReason(); + + GuildData guild = getGuildFromPlayer(kicker); + if (guild == null) { + sendErrorToPlayer(kicker, "§cYou are not in a guild!"); + return; + } + + GuildRank kickerRank = guild.getMemberRank(kicker); + if (kickerRank == null || !kickerRank.hasPermission(GuildPermission.KICK)) { + sendErrorToPlayer(kicker, "§cYou do not have permission to kick members!"); + return; + } + + GuildMember targetMember = guild.getMember(target); + if (targetMember == null) { + sendErrorToPlayer(kicker, "§cThat player is not in your guild!"); + return; + } + + GuildRank targetRank = guild.getRank(targetMember.getRankName()); + if (targetRank != null && !kickerRank.isHigherThan(targetRank)) { + sendErrorToPlayer(kicker, "§cYou cannot kick someone of equal or higher rank!"); + return; + } + + guild.getMembers().remove(targetMember); + log(guild, "§a" + kicker + "§7 kicked §e" + target + (reason.isBlank() ? "" : " §7for §e" + reason)); + + persistGuild(guild); + GuildDatabase.removePlayerMapping(target); + + GuildMemberKickedResponseEvent response = new GuildMemberKickedResponseEvent(guild, kicker, target, reason); + sendEvent(response); + } + + public static void handleDisbandRequest(GuildDisbandRequestEvent event) { + UUID disbander = event.getDisbander(); + + GuildData guild = getGuildFromPlayer(disbander); + if (guild == null) { + sendErrorToPlayer(disbander, "§cYou are not in a guild!"); + return; + } + + if (!guild.getMasterUuid().equals(disbander)) { + sendErrorToPlayer(disbander, "§cOnly the Guild Master can disband the guild!"); + return; + } + + disbandGuild(guild, disbander); + } + + public static void handlePromoteRequest(GuildPromoteRequestEvent event) { + UUID promoter = event.getPromoter(); + UUID target = event.getTarget(); + + GuildData guild = getGuildFromPlayer(promoter); + if (guild == null) { + sendErrorToPlayer(promoter, "§cYou are not in a guild!"); + return; + } + + GuildRank promoterRank = guild.getMemberRank(promoter); + if (promoterRank == null || !promoterRank.hasPermission(GuildPermission.PROMOTE)) { + sendErrorToPlayer(promoter, "§cYou do not have permission to promote members!"); + return; + } + + GuildMember targetMember = guild.getMember(target); + if (targetMember == null) { + sendErrorToPlayer(promoter, "§cThat player is not in your guild!"); + return; + } + + GuildRank currentRank = guild.getRank(targetMember.getRankName()); + if (currentRank == null) return; + + GuildRank nextRank = guild.getNextRankUp(currentRank); + if (nextRank == null || nextRank.getName().equals("Guild Master")) { + sendErrorToPlayer(promoter, "§cThat player cannot be promoted any further!"); + return; + } + + if (!promoterRank.isHigherThan(nextRank)) { + sendErrorToPlayer(promoter, "§cYou can only promote members to ranks below yours!"); + return; + } + + String oldRank = targetMember.getRankName(); + targetMember.setRankName(nextRank.getName()); + log(guild, "§a" + promoter + "§7 set rank of §e" + target + " §7to §e" + nextRank.getName()); + persistGuild(guild); + + GuildRankChangedResponseEvent response = new GuildRankChangedResponseEvent(guild, promoter, target, oldRank, nextRank.getName()); + sendEvent(response); + } + + public static void handleDemoteRequest(GuildDemoteRequestEvent event) { + UUID demoter = event.getDemoter(); + UUID target = event.getTarget(); + + GuildData guild = getGuildFromPlayer(demoter); + if (guild == null) { + sendErrorToPlayer(demoter, "§cYou are not in a guild!"); + return; + } + + GuildRank demoterRank = guild.getMemberRank(demoter); + if (demoterRank == null || !demoterRank.hasPermission(GuildPermission.DEMOTE)) { + sendErrorToPlayer(demoter, "§cYou do not have permission to demote members!"); + return; + } + + GuildMember targetMember = guild.getMember(target); + if (targetMember == null) { + sendErrorToPlayer(demoter, "§cThat player is not in your guild!"); + return; + } + + GuildRank currentRank = guild.getRank(targetMember.getRankName()); + if (currentRank == null) return; + + GuildRank nextRank = guild.getNextRankDown(currentRank); + if (nextRank == null) { + sendErrorToPlayer(demoter, "§cThat player cannot be demoted any further!"); + return; + } + + if (!demoterRank.isHigherThan(currentRank)) { + sendErrorToPlayer(demoter, "§cYou can only demote members of lower rank!"); + return; + } + + String oldRank = targetMember.getRankName(); + targetMember.setRankName(nextRank.getName()); + log(guild, "§a" + demoter + "§7 set rank of §e" + target + " §7to §e" + nextRank.getName()); + persistGuild(guild); + + GuildRankChangedResponseEvent response = new GuildRankChangedResponseEvent(guild, demoter, target, oldRank, nextRank.getName()); + sendEvent(response); + } + + public static void handleTransferRequest(GuildTransferRequestEvent event) { + UUID currentOwner = event.getCurrentOwner(); + UUID newOwner = event.getNewOwner(); + + GuildData guild = getGuildFromPlayer(currentOwner); + if (guild == null) { + sendErrorToPlayer(currentOwner, "§cYou are not in a guild!"); + return; + } + + if (!guild.getMasterUuid().equals(currentOwner)) { + sendErrorToPlayer(currentOwner, "§cOnly the Guild Master can transfer ownership!"); + return; + } + + GuildMember newOwnerMember = guild.getMember(newOwner); + if (newOwnerMember == null) { + sendErrorToPlayer(currentOwner, "§cThat player is not in your guild!"); + return; + } + + GuildMember currentOwnerMember = guild.getMember(currentOwner); + currentOwnerMember.setRankName("Officer"); + newOwnerMember.setRankName("Guild Master"); + log(guild, "§a" + currentOwner + "§7 transferred the guild to §e" + newOwner); + persistGuild(guild); + + GuildTransferredResponseEvent response = new GuildTransferredResponseEvent(guild, currentOwner, newOwner); + sendEvent(response); + } + + public static void handleProgressRequest(GuildProgressRequestEvent event) { + GuildData guild = getGuildFromPlayer(event.getPlayer()); + if (guild == null) return; + guild.resetDailyProgressIfNeeded(); + GuildMember member = guild.getMember(event.getPlayer()); + if (member == null) return; + if (event.getGexp() > 0) { + guild.addGexp(event.getGexp()); + guild.addDailyGexp(event.getGexp()); + member.setWeeklyGexp(member.getWeeklyGexp() + event.getGexp()); + member.setTotalGexp(member.getTotalGexp() + event.getGexp()); + } + if (event.isWin()) guild.addDailyWin(); + persistGuild(guild); + } + + public static void handleChatRequest(GuildChatRequestEvent event) { + UUID sender = event.getSender(); + String message = event.getMessage(); + boolean officerChat = event.isOfficerChat(); + + GuildData guild = getGuildFromPlayer(sender); + if (guild == null) { + sendErrorToPlayer(sender, "§cYou are not in a guild!"); + return; + } + + if (officerChat) { + GuildRank rank = guild.getMemberRank(sender); + if (rank == null || !rank.hasPermission(GuildPermission.OFFICER_CHAT)) { + sendErrorToPlayer(sender, "§cYou do not have permission to use officer chat!"); + return; + } + } + + GuildMember member = guild.getMember(sender); + if (member != null && member.isMuted()) { + sendErrorToPlayer(sender, "§cYou are muted in this guild!"); + return; + } + + if (guild.isEveryoneMuted() && guild.getEveryoneMutedExpiry() > System.currentTimeMillis()) { + GuildRank rank = guild.getMemberRank(sender); + if (rank == null || !rank.hasPermission(GuildPermission.MUTE_MEMBERS)) { + sendErrorToPlayer(sender, "§cGuild chat is currently muted!"); + return; + } + } + + if (guild.isSlowChat()) { + Long lastChat = lastChatTimestamps.get(sender); + if (lastChat != null && System.currentTimeMillis() - lastChat < 10000) { + sendErrorToPlayer(sender, "§cSlow mode is enabled. Please wait before sending another message."); + return; + } + lastChatTimestamps.put(sender, System.currentTimeMillis()); + } + + GuildChatResponseEvent response = new GuildChatResponseEvent(guild, sender, message, officerChat); + sendEvent(response); + } + + public static void handleSettingRequest(GuildSettingRequestEvent event) { + UUID changer = event.getChanger(); + String setting = event.getSetting(); + String value = event.getValue(); + + GuildData guild = getGuildFromPlayer(changer); + if (guild == null) { + sendErrorToPlayer(changer, "§cYou are not in a guild!"); + return; + } + + GuildRank rank = guild.getMemberRank(changer); + if (rank == null) return; + + switch (setting.toLowerCase()) { + case "tag" -> { + if (!rank.hasPermission(GuildPermission.MODIFY_TAG)) { + sendErrorToPlayer(changer, "§cYou do not have permission to change the guild tag!"); + return; + } + if (!guild.canSetTag()) { + sendErrorToPlayer(changer, "§cYour guild must be Level 5 to set a tag!"); + return; + } + if (value.length() > guild.getMaxTagLength()) { + sendErrorToPlayer(changer, "§cTag cannot be longer than " + guild.getMaxTagLength() + " characters!"); + return; + } + guild.setTag(value); + } + case "tagcolor" -> { + if (!rank.hasPermission(GuildPermission.MODIFY_TAG)) { + sendErrorToPlayer(changer, "§cYou do not have permission to change the tag color!"); + return; + } + int requiredLevel = switch (value) { + case "§7" -> 5; + case "§3" -> 15; + case "§2" -> 25; + default -> Integer.MAX_VALUE; + }; + if (guild.getLevel() < requiredLevel) { + sendErrorToPlayer(changer, "§cThat guild tag color has not been unlocked!"); + return; + } + guild.setTagColor(value); + } + case "motd" -> { + if (!rank.hasPermission(GuildPermission.MODIFY_MOTD)) { + sendErrorToPlayer(changer, "§cYou do not have permission to change the MOTD!"); + return; + } + guild.setMotd(value); + } + case "description" -> { + if (!rank.hasPermission(GuildPermission.MODIFY_DESCRIPTION)) { + sendErrorToPlayer(changer, "§cYou do not have permission to change the description!"); + return; + } + guild.setDescription(value); + } + case "discord" -> { + if (!rank.hasPermission(GuildPermission.MODIFY_DISCORD)) { + sendErrorToPlayer(changer, "§cYou do not have permission to change the discord link!"); + return; + } + guild.setDiscordLink(value); + } + case "rename" -> { + if (!guild.getMasterUuid().equals(changer)) { + sendErrorToPlayer(changer, "§cOnly the Guild Master can rename the guild!"); + return; + } + if (value.length() < 3 || value.length() > 30) { + sendErrorToPlayer(changer, "§cGuild name must be between 3 and 30 characters."); + return; + } + if (GuildDatabase.guildNameExists(value)) { + sendErrorToPlayer(changer, "§cA guild with that name already exists!"); + return; + } + guild.setName(value); + } + case "slow" -> { + if (!rank.hasPermission(GuildPermission.MODIFY_SETTINGS)) { + sendErrorToPlayer(changer, "§cYou do not have permission to modify settings!"); + return; + } + guild.setSlowChat(!guild.isSlowChat()); + value = guild.isSlowChat() ? "enabled" : "disabled"; + } + case "finder" -> { + if (!rank.hasPermission(GuildPermission.MODIFY_SETTINGS)) { + sendErrorToPlayer(changer, "§cYou do not have permission to modify settings!"); + return; + } + guild.setListedInFinder(!guild.isListedInFinder()); + value = guild.isListedInFinder() ? "visible" : "hidden"; + } + case "notifications" -> { + GuildMember member = guild.getMember(changer); + member.setNotificationsEnabled(!member.isNotificationsEnabled()); + value = member.isNotificationsEnabled() ? "enabled" : "disabled"; + } + case "toggle" -> { + GuildMember member = guild.getMember(changer); + member.setGuildChatEnabled(!member.isGuildChatEnabled()); + value = member.isGuildChatEnabled() ? "enabled" : "disabled"; + } + case "onlinemode" -> { + guild.setOnlineMode(!guild.isOnlineMode()); + value = guild.isOnlineMode() ? "enabled" : "disabled"; + } + default -> { + sendErrorToPlayer(changer, "§cUnknown setting: " + setting); + return; + } + } + + log(guild, "§a" + changer + "§7 changed guild setting §e" + setting); + persistGuild(guild); + + GuildSettingChangedResponseEvent response = new GuildSettingChangedResponseEvent(guild, changer, setting, value); + sendEvent(response); + } + + public static void handleMuteRequest(GuildMuteRequestEvent event) { + UUID muter = event.getMuter(); + String target = event.getTarget(); + long duration = event.getDuration(); + + GuildData guild = getGuildFromPlayer(muter); + if (guild == null) { + sendErrorToPlayer(muter, "§cYou are not in a guild!"); + return; + } + + GuildRank muterRank = guild.getMemberRank(muter); + if (muterRank == null || !muterRank.hasPermission(GuildPermission.MUTE_MEMBERS)) { + sendErrorToPlayer(muter, "§cYou do not have permission to mute guild members!"); + return; + } + + if (target.equalsIgnoreCase("everyone")) { + guild.setEveryoneMuted(true); + guild.setEveryoneMutedExpiry(System.currentTimeMillis() + duration); + } else { + UUID targetUUID = UUID.fromString(target); + GuildMember member = guild.getMember(targetUUID); + if (member == null) { + sendErrorToPlayer(muter, "§cThat player is not in your guild!"); + return; + } + member.setMutedUntil(System.currentTimeMillis() + duration); + } + + log(guild, "§a" + muter + "§7 muted §e" + target + " §7for §e" + duration + "ms"); + persistGuild(guild); + + GuildMuteChangedResponseEvent response = new GuildMuteChangedResponseEvent(guild, muter, target, duration, false); + sendEvent(response); + } + + public static void handleUnmuteRequest(GuildUnmuteRequestEvent event) { + UUID actor = event.getActor(); + String target = event.getTarget(); + + GuildData guild = getGuildFromPlayer(actor); + if (guild == null) { + sendErrorToPlayer(actor, "§cYou are not in a guild!"); + return; + } + + GuildRank actorRank = guild.getMemberRank(actor); + if (actorRank == null || !actorRank.hasPermission(GuildPermission.MUTE_MEMBERS)) { + sendErrorToPlayer(actor, "§cYou do not have permission to unmute guild members!"); + return; + } + + if (target.equalsIgnoreCase("everyone")) { + guild.setEveryoneMuted(false); + guild.setEveryoneMutedExpiry(0); + } else { + UUID targetUUID = UUID.fromString(target); + GuildMember member = guild.getMember(targetUUID); + if (member == null) { + sendErrorToPlayer(actor, "§cThat player is not in your guild!"); + return; + } + member.setMutedUntil(0); + } + + log(guild, "§a" + actor + "§7 unmuted §e" + target); + persistGuild(guild); + + GuildMuteChangedResponseEvent response = new GuildMuteChangedResponseEvent(guild, actor, target, 0, true); + sendEvent(response); + } + + public static void handleSetRankRequest(GuildSetRankRequestEvent event) { + UUID setter = event.getSetter(); + UUID target = event.getTarget(); + String rankName = event.getRankName(); + + GuildData guild = getGuildFromPlayer(setter); + if (guild == null) { + sendErrorToPlayer(setter, "§cYou are not in a guild!"); + return; + } + + if (!guild.getMasterUuid().equals(setter)) { + sendErrorToPlayer(setter, "§cOnly the Guild Master can set ranks directly!"); + return; + } + + GuildMember targetMember = guild.getMember(target); + if (targetMember == null) { + sendErrorToPlayer(setter, "§cThat player is not in your guild!"); + return; + } + + GuildRank newRank = guild.getRank(rankName); + if (newRank == null) { + sendErrorToPlayer(setter, "§cThat rank does not exist!"); + return; + } + + if (newRank.getName().equals("Guild Master")) { + sendErrorToPlayer(setter, "§cUse /guild transfer to transfer Guild Master!"); + return; + } + + String oldRank = targetMember.getRankName(); + targetMember.setRankName(newRank.getName()); + log(guild, "§a" + setter + "§7 set rank of §e" + target + " §7to §e" + newRank.getName()); + persistGuild(guild); + + GuildRankChangedResponseEvent response = new GuildRankChangedResponseEvent(guild, setter, target, oldRank, newRank.getName()); + sendEvent(response); + } + + private static void disbandGuild(GuildData guild, UUID disbander) { + GuildDisbandedResponseEvent response = new GuildDisbandedResponseEvent(guild, disbander); + sendEvent(response); + + guildCache.invalidate(guild.getGuildId()); + GuildDatabase.deleteGuild(guild.getGuildId()); + } + + private static void sendEvent(final @NotNull GuildEvent event) { + ServiceToServerManager.sendToAllServers( + new GuildEventPushProtocol(), + new GuildEventPushProtocol.Request( + event.getClass().getSimpleName(), + event.getSerializer().serialize(event), + event.getParticipants() + ), + 300 + ); + } + + private static void sendErrorToPlayer(UUID playerUUID, String message) { + sendMessageToPlayer(playerUUID, "§9§m-----------------------------------------------------\n" + message + "\n§9§m-----------------------------------------------------"); + } + + private static void sendMessageToPlayer(final @NotNull UUID playerUUID, final @NotNull String message) { + ServiceToServerManager.sendToAllServers( + new SendMessagePushProtocol(), + new SendMessagePushProtocol.Request(playerUUID, message), + 300 + ); + } + + private static void scheduleInviteExpiration(UUID guildId, UUID inviter, UUID invitee, long delayMs) { + CompletableFuture.delayedExecutor(delayMs, TimeUnit.MILLISECONDS).execute(() -> { + PendingGuildInvite invite = pendingInvites.remove(invitee); + if (invite != null) { + GuildData guild = getGuild(guildId); + if (guild != null) { + GuildInviteExpiredResponseEvent response = new GuildInviteExpiredResponseEvent(guild, inviter, invitee); + sendEvent(response); + } + } + }); + } + + private static void persistGuild(final @NotNull GuildData guild) { + guildCache.put(guild.getGuildId(), guild); + GuildDatabase.saveGuild(guild); + } + + private static void log(GuildData guild, String message) { + guild.addAuditLog("§7" + LOG_DATE.format(ZonedDateTime.now()) + ": " + message); + } + + public record PendingGuildInvite(@NotNull UUID guildId, @NotNull UUID inviter, @NotNull UUID invitee) { + } +} diff --git a/service.guild/src/main/java/net/swofty/service/guild/GuildDatabase.java b/service.guild/src/main/java/net/swofty/service/guild/GuildDatabase.java new file mode 100644 index 000000000..78c015116 --- /dev/null +++ b/service.guild/src/main/java/net/swofty/service/guild/GuildDatabase.java @@ -0,0 +1,144 @@ +package net.swofty.service.guild; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.Indexes; +import com.mongodb.client.model.Updates; +import net.swofty.commons.guild.GuildData; +import net.swofty.service.generic.MongoDB; +import org.bson.Document; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jspecify.annotations.NonNull; + +import java.util.UUID; + +public record GuildDatabase(String id) implements MongoDB { + public static MongoClient client; + public static MongoDatabase database; + public static MongoCollection guildCollection; + public static MongoCollection playerGuildCollection; + + @Override + public @NonNull MongoDB connect(@NotNull String connectionString) { + ConnectionString cs = new ConnectionString(connectionString); + MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); + client = MongoClients.create(settings); + + database = client.getDatabase("Minestom"); + guildCollection = database.getCollection("guilds"); + playerGuildCollection = database.getCollection("player-guilds"); + + guildCollection.createIndex(Indexes.ascending("name"), new IndexOptions().unique(true)); + playerGuildCollection.createIndex(Indexes.ascending("guildId")); + return this; + } + + public static GuildData getGuild(final @NotNull UUID guildId) { + Document doc = guildCollection.find(Filters.eq("_id", guildId.toString())).first(); + if (doc == null) return null; + return GuildData.getStaticSerializer().deserialize(doc.getString("data")); + } + + public static void saveGuild(final @NotNull GuildData guild) { + String serialized = guild.getSerializer().serialize(guild); + String guildId = guild.getGuildId().toString(); + + Document query = new Document("_id", guildId); + Document existing = guildCollection.find(query).first(); + + if (existing != null) { + guildCollection.updateOne(query, + Updates.combine( + Updates.set("data", serialized), + Updates.set("name", guild.getName().toLowerCase()) + )); + } else { + Document doc = new Document("_id", guildId); + doc.append("data", serialized); + doc.append("name", guild.getName().toLowerCase()); + guildCollection.insertOne(doc); + } + } + + public static void deleteGuild(@NotNull UUID guildId) { + guildCollection.deleteOne(Filters.eq("_id", guildId.toString())); + playerGuildCollection.deleteMany(Filters.eq("guildId", guildId.toString())); + } + + public static void mapPlayerToGuild(@NotNull UUID playerUuid, @NotNull UUID guildId) { + String playerId = playerUuid.toString(); + Document query = new Document("_id", playerId); + Document existing = playerGuildCollection.find(query).first(); + + if (existing != null) { + playerGuildCollection.updateOne(query, Updates.set("guildId", guildId.toString())); + } else { + Document doc = new Document("_id", playerId); + doc.append("guildId", guildId.toString()); + playerGuildCollection.insertOne(doc); + } + } + + public static void removePlayerMapping(@NotNull UUID playerUuid) { + playerGuildCollection.deleteOne(Filters.eq("_id", playerUuid.toString())); + } + + public static UUID getPlayerGuildId(@NotNull UUID playerUuid) { + Document doc = playerGuildCollection.find(Filters.eq("_id", playerUuid.toString())).first(); + if (doc == null) return null; + String guildId = doc.getString("guildId"); + return guildId != null ? UUID.fromString(guildId) : null; + } + + public static boolean guildNameExists(@NotNull String name) { + return guildCollection.find(Filters.eq("name", name.toLowerCase())).first() != null; + } + + @Override + public void set(@NotNull String key, @Nullable Object value) { + insertOrUpdate(key, value); + } + + @Override + public Object get(@NotNull String key, @Nullable Object def) { + Document doc = guildCollection.find(Filters.eq("_id", id)).first(); + if (doc == null) return def; + return doc.get(key); + } + + @Override + public void insertOrUpdate(@NonNull String key, Object value) { + if (exists()) { + Document query = new Document("_id", id); + Document found = guildCollection.find(query).first(); + assert found != null; + guildCollection.updateOne(found, Updates.set(key, value)); + return; + } + Document newDoc = new Document("_id", id); + newDoc.append(key, value); + guildCollection.insertOne(newDoc); + } + + @Override + public boolean remove(@NonNull String id) { + Document query = new Document("_id", id); + Document found = guildCollection.find(query).first(); + if (found == null) return false; + guildCollection.deleteOne(query); + return true; + } + + @Override + public boolean exists() { + Document query = new Document("_id", id); + return guildCollection.find(query).first() != null; + } +} diff --git a/service.guild/src/main/java/net/swofty/service/guild/GuildService.java b/service.guild/src/main/java/net/swofty/service/guild/GuildService.java new file mode 100644 index 000000000..2bfd2ee98 --- /dev/null +++ b/service.guild/src/main/java/net/swofty/service/guild/GuildService.java @@ -0,0 +1,28 @@ +package net.swofty.service.guild; + +import net.swofty.commons.ServiceType; +import net.swofty.commons.config.ConfigProvider; +import net.swofty.service.generic.SkyBlockService; +import net.swofty.service.generic.redis.ServiceEndpoint; + +import java.util.List; + +public class GuildService implements SkyBlockService { + + static void main() { + String mongoUri = ConfigProvider.settings().getMongodb(); + new GuildDatabase(null).connect(mongoUri); + + SkyBlockService.init(new GuildService()); + } + + @Override + public ServiceType getType() { + return ServiceType.GUILD; + } + + @Override + public List getEndpoints() { + return loopThroughPackage("net.swofty.service.guild.endpoints", ServiceEndpoint.class).toList(); + } +} diff --git a/service.guild/src/main/java/net/swofty/service/guild/endpoints/GetGuildEndpoint.java b/service.guild/src/main/java/net/swofty/service/guild/endpoints/GetGuildEndpoint.java new file mode 100644 index 000000000..27b1817c0 --- /dev/null +++ b/service.guild/src/main/java/net/swofty/service/guild/endpoints/GetGuildEndpoint.java @@ -0,0 +1,25 @@ +package net.swofty.service.guild.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.guild.GetGuildProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.guild.GuildCache; + +public class GetGuildEndpoint implements ServiceEndpoint< + GetGuildProtocolObject.GetGuildMessage, + GetGuildProtocolObject.GetGuildResponse> { + + @Override + public GetGuildProtocolObject associatedProtocolObject() { + return new GetGuildProtocolObject(); + } + + @Override + public GetGuildProtocolObject.GetGuildResponse onMessage( + ServiceProxyRequest message, + GetGuildProtocolObject.GetGuildMessage messageObject) { + return new GetGuildProtocolObject.GetGuildResponse( + GuildCache.getGuildFromPlayer(messageObject.memberUUID()) + ); + } +} diff --git a/service.guild/src/main/java/net/swofty/service/guild/endpoints/GuildEventToServiceEndpoint.java b/service.guild/src/main/java/net/swofty/service/guild/endpoints/GuildEventToServiceEndpoint.java new file mode 100644 index 000000000..8faefbc2e --- /dev/null +++ b/service.guild/src/main/java/net/swofty/service/guild/endpoints/GuildEventToServiceEndpoint.java @@ -0,0 +1,48 @@ +package net.swofty.service.guild.endpoints; + +import net.swofty.commons.guild.GuildEvent; +import net.swofty.commons.guild.events.*; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.guild.SendGuildEventToServiceProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.guild.GuildCache; + +public class GuildEventToServiceEndpoint implements ServiceEndpoint< + SendGuildEventToServiceProtocolObject.SendGuildEventToServiceMessage, + SendGuildEventToServiceProtocolObject.SendGuildEventToServiceResponse> { + + @Override + public SendGuildEventToServiceProtocolObject associatedProtocolObject() { + return new SendGuildEventToServiceProtocolObject(); + } + + @Override + public SendGuildEventToServiceProtocolObject.SendGuildEventToServiceResponse onMessage( + ServiceProxyRequest message, + SendGuildEventToServiceProtocolObject.SendGuildEventToServiceMessage messageObject) { + GuildEvent template = GuildEvent.findFromType(messageObject.eventType()); + GuildEvent event = template.getSerializer().deserialize(messageObject.eventData()); + + switch (event) { + case GuildCreateRequestEvent e -> GuildCache.handleCreateRequest(e); + case GuildInviteRequestEvent e -> GuildCache.handleInviteRequest(e); + case GuildAcceptInviteRequestEvent e -> GuildCache.handleAcceptInvite(e); + case GuildLeaveRequestEvent e -> GuildCache.handleLeaveRequest(e); + case GuildKickRequestEvent e -> GuildCache.handleKickRequest(e); + case GuildDisbandRequestEvent e -> GuildCache.handleDisbandRequest(e); + case GuildPromoteRequestEvent e -> GuildCache.handlePromoteRequest(e); + case GuildDemoteRequestEvent e -> GuildCache.handleDemoteRequest(e); + case GuildTransferRequestEvent e -> GuildCache.handleTransferRequest(e); + case GuildChatRequestEvent e -> GuildCache.handleChatRequest(e); + case GuildSettingRequestEvent e -> GuildCache.handleSettingRequest(e); + case GuildMuteRequestEvent e -> GuildCache.handleMuteRequest(e); + case GuildUnmuteRequestEvent e -> GuildCache.handleUnmuteRequest(e); + case GuildSetRankRequestEvent e -> GuildCache.handleSetRankRequest(e); + case GuildProgressRequestEvent e -> GuildCache.handleProgressRequest(e); + default -> + throw new IllegalArgumentException("Unknown guild event type: " + event.getClass().getSimpleName()); + } + + return new SendGuildEventToServiceProtocolObject.SendGuildEventToServiceResponse(true); + } +} diff --git a/service.guild/src/main/java/net/swofty/service/guild/endpoints/IsPlayerInGuildEndpoint.java b/service.guild/src/main/java/net/swofty/service/guild/endpoints/IsPlayerInGuildEndpoint.java new file mode 100644 index 000000000..b142bba1a --- /dev/null +++ b/service.guild/src/main/java/net/swofty/service/guild/endpoints/IsPlayerInGuildEndpoint.java @@ -0,0 +1,25 @@ +package net.swofty.service.guild.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.guild.IsPlayerInGuildProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.guild.GuildCache; + +public class IsPlayerInGuildEndpoint implements ServiceEndpoint< + IsPlayerInGuildProtocolObject.IsPlayerInGuildMessage, + IsPlayerInGuildProtocolObject.IsPlayerInGuildResponse> { + + @Override + public IsPlayerInGuildProtocolObject associatedProtocolObject() { + return new IsPlayerInGuildProtocolObject(); + } + + @Override + public IsPlayerInGuildProtocolObject.IsPlayerInGuildResponse onMessage( + ServiceProxyRequest message, + IsPlayerInGuildProtocolObject.IsPlayerInGuildMessage messageObject) { + return new IsPlayerInGuildProtocolObject.IsPlayerInGuildResponse( + GuildCache.isInGuild(messageObject.playerUUID()) + ); + } +} diff --git a/service.itemtracker/build.gradle.kts b/service.itemtracker/build.gradle.kts index 753c0c5f4..afe06d7a3 100644 --- a/service.itemtracker/build.gradle.kts +++ b/service.itemtracker/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java index b4e0ae11f..9961622fd 100644 --- a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java +++ b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorCache.java @@ -1,8 +1,9 @@ package net.swofty.service.orchestrator; import net.swofty.commons.ServerType; -import net.swofty.commons.bedwars.BedwarsGameType; -import net.swofty.commons.game.Game; +import net.swofty.commons.bedwars.BedWarsGameType; +import net.swofty.commons.protocol.objects.orchestrator.GameHeartbeatProtocolObject; +import net.swofty.type.game.game.GameObject; import java.time.Instant; import java.util.ArrayList; @@ -14,256 +15,476 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ThreadLocalRandom; public class OrchestratorCache { - private static final Map serversByShortName = new ConcurrentHashMap<>(); - private static final Map gamesByGameId = new ConcurrentHashMap<>(); - private static final long HEARTBEAT_TTL_MS = 10000; // 10s - - public static void handleHeartbeat(UUID uuid, - String shortName, - ServerType type, - int maxPlayers, - int onlinePlayers, - List games) { - GameServerState state = new GameServerState( - uuid, - shortName, - type, - maxPlayers, - onlinePlayers, - Instant.now().toEpochMilli() - ); - serversByShortName.put(shortName, state); - - // Remove old games from this server - gamesByGameId.entrySet().removeIf(entry -> entry.getValue().serverUuid().equals(uuid)); - - // Add current games with server tracking - for (Game game : games) { - gamesByGameId.put(game.getGameId(), new GameWithServer(game, uuid, shortName)); - } - } - - /** - * Finds an existing joinable game for the specified game type and map (Bedwars-specific) - */ - public static GameWithServer findExisting(BedwarsGameType gameType, String map) { - return findExisting(ServerType.BEDWARS_GAME, gameType.maxPlayers(), map, 1); - } - - /** - * Finds an existing joinable game for the specified game type and map with needed slots (Bedwars-specific) - */ - public static GameWithServer findExisting(BedwarsGameType gameType, String map, int neededSlots) { - return findExisting(ServerType.BEDWARS_GAME, gameType.maxPlayers(), map, neededSlots); - } - - /** - * Generic version - finds an existing joinable game for any server type - */ - public static GameWithServer findExisting(ServerType serverType, int maxPlayers, String map) { - return findExisting(serverType, maxPlayers, map, 1); - } - - /** - * Finds an existing joinable game with at least neededSlots available slots - */ - public static GameWithServer findExisting(ServerType serverType, int maxPlayers, String map, int neededSlots) { - return findExisting(serverType, maxPlayers, map, neededSlots, null); - } - - /** - * Finds an existing joinable game with at least neededSlots available slots, filtered by game type name - */ - public static GameWithServer findExisting(ServerType serverType, int maxPlayers, String map, int neededSlots, String gameTypeName) { - cleanup(); - - List candidates = new ArrayList<>(); - for (GameWithServer gameWithServer : gamesByGameId.values()) { - Game game = gameWithServer.game(); - int availableSlots = maxPlayers - game.getInvolvedPlayers().size(); - if (game.getType() == serverType && - availableSlots >= neededSlots && - (map == null || game.getMap().equals(map)) && - (gameTypeName == null || gameTypeName.equals(game.getGameTypeName()))) { - candidates.add(gameWithServer); - } - } - - if (candidates.isEmpty()) { - return null; - } - - // Prefer games with more players (closer to starting) - candidates.sort(Comparator.comparingInt((GameWithServer g) -> g.game().getInvolvedPlayers().size()).reversed()); - return candidates.getFirst(); - } - - /** - * Finds a server with capacity to host a new game (Bedwars-specific) - */ - public static GameServerState instantiateServer(BedwarsGameType gameType, String map) { - return instantiateServer(ServerType.BEDWARS_GAME, gameType.maxPlayers()); - } - - /** - * Generic version - finds a server with capacity to host a new game for any server type - */ - public static GameServerState instantiateServer(ServerType serverType, int maxPlayers) { - cleanup(); - - List candidates = new ArrayList<>(); - for (GameServerState server : serversByShortName.values()) { - if (server.type() == serverType && - server.availableSlots() >= maxPlayers) { - candidates.add(server); - } - } - - if (candidates.isEmpty()) { - return null; - } - - // Prefer servers with more available capacity - candidates.sort(Comparator.comparingInt(GameServerState::availableSlots).reversed()); - int topAvail = candidates.getFirst().availableSlots(); - - List topServers = new ArrayList<>(); - for (GameServerState server : candidates) { - if (server.availableSlots() == topAvail) { - topServers.add(server); - } else { - break; - } - } - - return topServers.get(ThreadLocalRandom.current().nextInt(topServers.size())); - } - - public static Set getMaps(ServerType type, String gameTypeName) { - cleanup(); - Set maps = new HashSet<>(); - - for (GameWithServer gameWithServer : gamesByGameId.values()) { - Game game = gameWithServer.game(); - if (game.getType() == type) { - maps.add(game.getMap()); - } - } - - return maps; - } - - /** - * Find a game that a player is part of (either active or disconnected). - * Used for the rejoin system. - */ - public static GameWithServer findPlayerGame(UUID playerUuid) { - cleanup(); - - for (GameWithServer gameWithServer : gamesByGameId.values()) { - Game game = gameWithServer.game(); - // Check active players - if (game.getInvolvedPlayers().contains(playerUuid)) { - return gameWithServer; - } - // Check disconnected players - if (game.getDisconnectedPlayers() != null && game.getDisconnectedPlayers().contains(playerUuid)) { - return gameWithServer; - } - } - return null; - } - - public static void cleanup() { - long now = Instant.now().toEpochMilli(); - - // Remove stale servers - serversByShortName.values().removeIf(server -> - now - server.lastHeartbeat() > HEARTBEAT_TTL_MS); - - // Remove games from servers that are no longer available - Set availableServerUuids = new HashSet<>(); - for (GameServerState server : serversByShortName.values()) { - availableServerUuids.add(server.uuid()); - } - - gamesByGameId.values().removeIf(gameWithServer -> - !availableServerUuids.contains(gameWithServer.serverUuid())); - } - - public record GameServerState(UUID uuid, - String shortName, - ServerType type, - int maxPlayers, - int onlinePlayers, - long lastHeartbeat) { - - public int availableSlots() { - return Math.max(0, maxPlayers - onlinePlayers); - } - } - - public record GameWithServer(Game game, UUID serverUuid, String serverShortName) { - } - - // Getter methods for debugging/monitoring - public static Collection getAllServers() { - cleanup(); - return new ArrayList<>(serversByShortName.values()); - } - - public static Collection getAllActiveGames() { - cleanup(); - return new ArrayList<>(gamesByGameId.values()); - } - - public static GameServerState getServerByUuid(UUID serverUuid) { - cleanup(); - return serversByShortName.values().stream() - .filter(server -> server.uuid().equals(serverUuid)) - .findFirst() - .orElse(null); - } - - /** - * Get player and game counts filtered by server type and optionally by game type name. - * @param type The server type (e.g., MURDER_MYSTERY_GAME, BEDWARS_GAME) - * @param gameTypeName Optional game type name to filter by (e.g., "CLASSIC", "SOLO"). Pass null for all. - * @return GameCountStats with player count and game count - */ - public static GameCountStats getGameCounts(ServerType type, String gameTypeName) { - return getGameCounts(type, gameTypeName, null); - } - - /** - * Get player and game counts filtered by server type, game type name, and map name. - * @param type The server type (e.g., MURDER_MYSTERY_GAME, BEDWARS_GAME) - * @param gameTypeName Optional game type name to filter by (e.g., "CLASSIC", "SOLO"). Pass null for all. - * @param mapName Optional map name to filter by. Pass null for all maps. - * @return GameCountStats with player count and game count - */ - public static GameCountStats getGameCounts(ServerType type, String gameTypeName, String mapName) { - cleanup(); - int playerCount = 0; - int gameCount = 0; - - for (GameWithServer gameWithServer : gamesByGameId.values()) { - Game game = gameWithServer.game(); - if (game.getType() == type) { - if (gameTypeName == null || gameTypeName.equals(game.getGameTypeName())) { - if (mapName == null || mapName.equals(game.getMap())) { - playerCount += game.getInvolvedPlayers().size(); - gameCount++; - } - } - } - } - - return new GameCountStats(playerCount, gameCount); - } - - public record GameCountStats(int playerCount, int gameCount) {} -} \ No newline at end of file + private static final Map serversByShortName = new ConcurrentHashMap<>(); + private static final Map gamesByGameId = new ConcurrentHashMap<>(); + private static final Map> reservationsByGameId = new ConcurrentHashMap<>(); + private static final long HEARTBEAT_TTL_MS = 10000; // 10s + private static final long RESERVATION_TTL_MS = 8000; // 8s + + public static void handleHeartbeat(UUID uuid, + String shortName, + ServerType type, + int maxPlayers, + int onlinePlayers, + List games) { + handleHeartbeat(uuid, shortName, type, maxPlayers, onlinePlayers, games, List.of(), null); + } + + public static void handleHeartbeat(UUID uuid, + String shortName, + ServerType type, + int maxPlayers, + int onlinePlayers, + List games, + List mapAdvertisements, + Integer remainingGameSlots) { + GameServerState state = new GameServerState( + uuid, + shortName, + type, + maxPlayers, + onlinePlayers, + Instant.now().toEpochMilli(), + mapAdvertisements != null ? List.copyOf(mapAdvertisements) : List.of(), + remainingGameSlots + ); + serversByShortName.put(shortName, state); + + // Remove old games from this server + gamesByGameId.entrySet().removeIf(entry -> entry.getValue().serverUuid().equals(uuid)); + + // Add current games with server tracking + for (GameObject game : games) { + gamesByGameId.put(game.getGameId(), new GameWithServer(game, uuid, shortName)); + } + } + + /** + * Finds an existing joinable game for the specified game type and map (Bedwars-specific) + */ + public static GameWithServer findExisting(BedWarsGameType gameType, String map) { + return findExisting(ServerType.BEDWARS_GAME, gameType.maxPlayers(), map, 1, gameType.name()); + } + + /** + * Finds an existing joinable game for the specified game type and map with needed slots (Bedwars-specific) + */ + public static GameWithServer findExisting(BedWarsGameType gameType, String map, int neededSlots) { + return findExisting(ServerType.BEDWARS_GAME, gameType.maxPlayers(), map, neededSlots, gameType.name()); + } + + public static GameWithServer findMostPopulatedBedwarsGame(BedWarsGameType gameType, int neededSlots) { + return findExisting(ServerType.BEDWARS_GAME, gameType.maxPlayers(), null, neededSlots, gameType.name(), true); + } + + /** + * Generic version - finds an existing joinable game for any server type + */ + public static GameWithServer findExisting(ServerType serverType, int maxPlayers, String map) { + return findExisting(serverType, maxPlayers, map, 1); + } + + /** + * Finds an existing joinable game with at least neededSlots available slots + */ + public static GameWithServer findExisting(ServerType serverType, int maxPlayers, String map, int neededSlots) { + return findExisting(serverType, maxPlayers, map, neededSlots, null); + } + + /** + * Finds an existing joinable game with at least neededSlots available slots, filtered by game type name + */ + public static GameWithServer findExisting(ServerType serverType, int maxPlayers, String map, int neededSlots, String gameTypeName) { + return findExisting(serverType, maxPlayers, map, neededSlots, gameTypeName, false); + } + + /** + * Finds an existing joinable game with at least neededSlots available slots. + * If requirePlayers is true, only considers games that already have players. + */ + public static synchronized GameWithServer findExisting(ServerType serverType, + int maxPlayers, + String map, + int neededSlots, + String gameTypeName, + boolean requirePlayers) { + cleanup(); + + List candidates = new ArrayList<>(); + for (GameWithServer gameWithServer : gamesByGameId.values()) { + GameObject game = gameWithServer.game(); + int reservedSlots = getReservedSlots(game.getGameId()); + int availableSlots = maxPlayers - game.getInvolvedPlayers().size() - reservedSlots; + if (game.getType() == serverType && + game.isAcceptingJoins() && + availableSlots >= neededSlots && + (map == null || game.getMap().equals(map)) && + (gameTypeName == null || gameTypeName.equals(game.getGameTypeName())) && + (!requirePlayers || !game.getInvolvedPlayers().isEmpty())) { + candidates.add(gameWithServer); + } + } + + if (candidates.isEmpty()) { + return null; + } + + // Prefer games with more players (closer to starting) + candidates.sort(Comparator.comparingInt((GameWithServer g) -> g.game().getInvolvedPlayers().size()).reversed()); + GameWithServer selected = candidates.getFirst(); + if (neededSlots > 0) { + reserveSlots(selected.game().getGameId(), neededSlots); + } + return selected; + } + + /** + * Finds a server with capacity to host a new game (Bedwars-specific) + */ + public static GameServerState instantiateServer(BedWarsGameType gameType, String map) { + cleanup(); + + List candidates = new ArrayList<>(); + for (GameServerState server : serversByShortName.values()) { + if (server.type() != ServerType.BEDWARS_GAME) { + continue; + } + if (server.availableSlots() < gameType.maxPlayers()) { + continue; + } + if (server.remainingGameSlots() != null && server.remainingGameSlots() <= 0) { + continue; + } + if (!supportsBedwarsRequest(server, map, gameType.name())) { + continue; + } + candidates.add(server); + } + + if (candidates.isEmpty()) { + return null; + } + + candidates.sort(Comparator + .comparingInt(GameServerState::availableSlots) + .thenComparingInt(server -> server.remainingGameSlots() != null ? server.remainingGameSlots() : Integer.MAX_VALUE) + .reversed()); + + GameServerState best = candidates.getFirst(); + List topServers = candidates.stream() + .filter(server -> server.availableSlots() == best.availableSlots()) + .filter(server -> { + int serverSlots = server.remainingGameSlots() != null ? server.remainingGameSlots() : Integer.MAX_VALUE; + int bestSlots = best.remainingGameSlots() != null ? best.remainingGameSlots() : Integer.MAX_VALUE; + return serverSlots == bestSlots; + }) + .toList(); + + return topServers.get(ThreadLocalRandom.current().nextInt(topServers.size())); + } + + /** + * Generic version - finds a server with capacity to host a new game for any server type + */ + public static GameServerState instantiateServer(ServerType serverType, int maxPlayers) { + cleanup(); + + List candidates = new ArrayList<>(); + for (GameServerState server : serversByShortName.values()) { + if (server.type() == serverType && + server.availableSlots() >= maxPlayers) { + candidates.add(server); + } + } + + if (candidates.isEmpty()) { + return null; + } + + // Prefer servers with more available capacity + candidates.sort(Comparator.comparingInt(GameServerState::availableSlots).reversed()); + int topAvail = candidates.getFirst().availableSlots(); + + List topServers = new ArrayList<>(); + for (GameServerState server : candidates) { + if (server.availableSlots() == topAvail) { + topServers.add(server); + } else { + break; + } + } + + return topServers.get(ThreadLocalRandom.current().nextInt(topServers.size())); + } + + public static Set getMaps(ServerType type, String gameTypeName) { + cleanup(); + + if (type == ServerType.BEDWARS_GAME) { + Set advertisedMaps = getAdvertisedBedwarsMapNames(gameTypeName); + if (!advertisedMaps.isEmpty()) { + return advertisedMaps; + } + } + + Set maps = new HashSet<>(); + + for (GameWithServer gameWithServer : gamesByGameId.values()) { + GameObject game = gameWithServer.game(); + if (game.getType() == type && (gameTypeName == null || gameTypeName.equals(game.getGameTypeName()))) { + maps.add(game.getMap()); + } + } + + return maps; + } + + public static List getEligibleBedwarsMaps(BedWarsGameType gameType) { + cleanup(); + Set advertisedMaps = getAdvertisedBedwarsMapNames(gameType.name()); + if (!advertisedMaps.isEmpty()) { + return advertisedMaps.stream().sorted(String.CASE_INSENSITIVE_ORDER).toList(); + } + + Set maps = new HashSet<>(); + for (GameWithServer gameWithServer : gamesByGameId.values()) { + GameObject game = gameWithServer.game(); + if (game.getType() == ServerType.BEDWARS_GAME && gameType.name().equals(game.getGameTypeName())) { + maps.add(game.getMap()); + } + } + return maps.stream().sorted(String.CASE_INSENSITIVE_ORDER).toList(); + } + + public static String pickRandomBedwarsMap(BedWarsGameType gameType) { + List maps = getEligibleBedwarsMaps(gameType); + if (maps.isEmpty()) { + return null; + } + return maps.get(ThreadLocalRandom.current().nextInt(maps.size())); + } + + /** + * Find a game that a player is part of (either active or disconnected). + * Used for the rejoin system. + */ + public static GameWithServer findPlayerGame(UUID playerUuid) { + cleanup(); + + for (GameWithServer gameWithServer : gamesByGameId.values()) { + GameObject game = gameWithServer.game(); + // Check active players + if (game.getInvolvedPlayers().contains(playerUuid)) { + return gameWithServer; + } + // Check disconnected players + if (game.getDisconnectedPlayers() != null && game.getDisconnectedPlayers().contains(playerUuid)) { + return gameWithServer; + } + } + return null; + } + + public static void cleanup() { + long now = Instant.now().toEpochMilli(); + cleanupReservations(now); + + // Remove stale servers + serversByShortName.values().removeIf(server -> + now - server.lastHeartbeat() > HEARTBEAT_TTL_MS); + + // Remove games from servers that are no longer available + Set availableServerUuids = new HashSet<>(); + for (GameServerState server : serversByShortName.values()) { + availableServerUuids.add(server.uuid()); + } + + gamesByGameId.values().removeIf(gameWithServer -> + !availableServerUuids.contains(gameWithServer.serverUuid())); + + reservationsByGameId.entrySet().removeIf(entry -> !gamesByGameId.containsKey(entry.getKey())); + } + + private static void reserveSlots(UUID gameId, int slots) { + if (slots <= 0) { + return; + } + + long expiresAt = Instant.now().toEpochMilli() + RESERVATION_TTL_MS; + reservationsByGameId + .computeIfAbsent(gameId, ignored -> new CopyOnWriteArrayList<>()) + .add(new SlotReservation(slots, expiresAt)); + } + + private static int getReservedSlots(UUID gameId) { + List reservations = reservationsByGameId.get(gameId); + if (reservations == null || reservations.isEmpty()) { + return 0; + } + + long now = Instant.now().toEpochMilli(); + int total = 0; + for (SlotReservation reservation : reservations) { + if (reservation.expiresAtMs() > now) { + total += reservation.slots(); + } + } + return total; + } + + private static void cleanupReservations(long now) { + reservationsByGameId.entrySet().removeIf(entry -> { + List reservations = entry.getValue(); + reservations.removeIf(reservation -> reservation.expiresAtMs() <= now); + return reservations.isEmpty(); + }); + } + + private record SlotReservation(int slots, long expiresAtMs) { + } + + public record GameServerState(UUID uuid, + String shortName, + ServerType type, + int maxPlayers, + int onlinePlayers, + long lastHeartbeat, + List mapAdvertisements, + Integer remainingGameSlots) { + + public GameServerState { + mapAdvertisements = mapAdvertisements != null ? List.copyOf(mapAdvertisements) : List.of(); + } + + public int availableSlots() { + return Math.max(0, maxPlayers - onlinePlayers); + } + } + + public record GameWithServer(GameObject game, UUID serverUuid, String serverShortName) { + } + + // Getter methods for debugging/monitoring + public static Collection getAllServers() { + cleanup(); + return new ArrayList<>(serversByShortName.values()); + } + + public static Collection getAllActiveGames() { + cleanup(); + return new ArrayList<>(gamesByGameId.values()); + } + + public static GameServerState getServerByUuid(UUID serverUuid) { + cleanup(); + return serversByShortName.values().stream() + .filter(server -> server.uuid().equals(serverUuid)) + .findFirst() + .orElse(null); + } + + /** + * Get player and game counts filtered by server type and optionally by game type name. + * + * @param type The server type (e.g., MURDER_MYSTERY_GAME, BEDWARS_GAME) + * @param gameTypeName Optional game type name to filter by (e.g., "CLASSIC", "SOLO"). Pass null for all. + * @return GameCountStats with player count and game count + */ + public static GameCountStats getGameCounts(ServerType type, String gameTypeName) { + return getGameCounts(type, gameTypeName, null); + } + + /** + * Get player and game counts filtered by server type, game type name, and map name. + * + * @param type The server type (e.g., MURDER_MYSTERY_GAME, BEDWARS_GAME) + * @param gameTypeName Optional game type name to filter by (e.g., "CLASSIC", "SOLO"). Pass null for all. + * @param mapName Optional map name to filter by. Pass null for all maps. + * @return GameCountStats with player count and game count + */ + public static GameCountStats getGameCounts(ServerType type, String gameTypeName, String mapName) { + cleanup(); + int playerCount = 0; + int gameCount = 0; + + for (GameWithServer gameWithServer : gamesByGameId.values()) { + GameObject game = gameWithServer.game(); + if (game.getType() == type) { + if (gameTypeName == null || gameTypeName.equals(game.getGameTypeName())) { + if (mapName == null || mapName.equals(game.getMap())) { + playerCount += game.getInvolvedPlayers().size(); + gameCount++; + } + } + } + } + + return new GameCountStats(playerCount, gameCount); + } + + public record GameCountStats(int playerCount, int gameCount) { + } + + private static Set getAdvertisedBedwarsMapNames(String gameTypeName) { + Set maps = new HashSet<>(); + for (GameServerState server : serversByShortName.values()) { + if (server.type() != ServerType.BEDWARS_GAME || server.mapAdvertisements().isEmpty()) { + continue; + } + for (GameHeartbeatProtocolObject.MapAdvertisement advertisement : server.mapAdvertisements()) { + if (supportsMode(advertisement, gameTypeName)) { + maps.add(advertisement.mapName()); + } + } + } + return maps; + } + + private static boolean supportsBedwarsRequest(GameServerState server, String map, String gameTypeName) { + if (server.mapAdvertisements().isEmpty()) { + return true; + } + + if (map == null) { + for (GameHeartbeatProtocolObject.MapAdvertisement advertisement : server.mapAdvertisements()) { + if (supportsMode(advertisement, gameTypeName)) { + return true; + } + } + return false; + } + + for (GameHeartbeatProtocolObject.MapAdvertisement advertisement : server.mapAdvertisements()) { + if (matchesMap(advertisement, map) && supportsMode(advertisement, gameTypeName)) { + return true; + } + } + return false; + } + + private static boolean matchesMap(GameHeartbeatProtocolObject.MapAdvertisement advertisement, String requestedMap) { + return advertisement.mapId().equalsIgnoreCase(requestedMap) + || advertisement.mapName().equalsIgnoreCase(requestedMap); + } + + private static boolean supportsMode(GameHeartbeatProtocolObject.MapAdvertisement advertisement, String gameTypeName) { + if (gameTypeName == null) { + return true; + } + String compatibleMode = gameTypeName; + BedWarsGameType parsed = BedWarsGameType.from(gameTypeName); + if (parsed != null) { + compatibleMode = parsed.getMapCompatibilityType().name(); + } + for (String mode : advertisement.supportedModes()) { + if (mode.equalsIgnoreCase(gameTypeName) || mode.equalsIgnoreCase(compatibleMode)) { + return true; + } + } + return false; + } +} diff --git a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorService.java b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorService.java index 480e257d4..44091167a 100644 --- a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorService.java +++ b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/OrchestratorService.java @@ -3,6 +3,7 @@ import net.swofty.commons.ServiceType; import net.swofty.service.generic.SkyBlockService; import net.swofty.service.generic.redis.ServiceEndpoint; +import org.tinylog.Logger; import java.util.List; import java.util.concurrent.Executors; @@ -11,15 +12,16 @@ public class OrchestratorService implements SkyBlockService { - static void main(String[] args) { - SkyBlockService.init(new OrchestratorService()); + static void main() { + SkyBlockService.init(new OrchestratorService()); - ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(r -> { - Thread t = new Thread(r, "orchestrator-cleanup"); - t.setDaemon(true); - return t; - }); - scheduler.scheduleAtFixedRate(OrchestratorCache::cleanup, 5, 5, TimeUnit.SECONDS); + ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(r -> { + Thread t = new Thread(r, "orchestrator-cleanup"); + t.setDaemon(true); + return t; + }); + scheduler.scheduleAtFixedRate(OrchestratorCache::cleanup, 5, 5, TimeUnit.SECONDS); + Logger.info("Started orchestrator service"); } @Override diff --git a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/endpoints/GameHeartbeatEndpoint.java b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/endpoints/GameHeartbeatEndpoint.java index 17fc357e8..a88a7e8db 100644 --- a/service.orchestrator/src/main/java/net/swofty/service/orchestrator/endpoints/GameHeartbeatEndpoint.java +++ b/service.orchestrator/src/main/java/net/swofty/service/orchestrator/endpoints/GameHeartbeatEndpoint.java @@ -7,8 +7,8 @@ import net.swofty.service.orchestrator.OrchestratorCache; public class GameHeartbeatEndpoint implements ServiceEndpoint - { + { @Override public ProtocolObject associatedProtocolObject() { @@ -19,12 +19,14 @@ public ProtocolObject { - - @Override - public ProtocolObject associatedProtocolObject() { - return new GetServerForMapProtocolObject(); - } - - @Override - public GetServerForMapProtocolObject.GetServerForMapResponse onMessage(ServiceProxyRequest message, - GetServerForMapProtocolObject.GetServerForMapMessage body) { - return switch (body.type()) { - case BEDWARS_GAME -> handleBedwars(body); - case MURDER_MYSTERY_GAME -> handleMurderMystery(body); - case SKYWARS_GAME -> handleSkywars(body); - default -> new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - }; - } - - private GetServerForMapProtocolObject.GetServerForMapResponse handleBedwars( - GetServerForMapProtocolObject.GetServerForMapMessage body) { - try { - BedwarsGameType gameType = parseBedwarsGameType(body.mode()); - if (gameType == null) { - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } - - int neededSlots = body.neededSlots() > 0 ? body.neededSlots() : 1; - - // First, try to find an existing joinable game with enough slots - OrchestratorCache.GameWithServer existingGameWithServer = OrchestratorCache.findExisting(gameType, body.map(), neededSlots); - if (existingGameWithServer != null) { - OrchestratorCache.GameServerState hostingServer = OrchestratorCache.getServerByUuid(existingGameWithServer.serverUuid()); - if (hostingServer != null) { - UnderstandableProxyServer proxy = new UnderstandableProxyServer( - hostingServer.shortName(), - hostingServer.uuid(), - hostingServer.type(), - -1, - new ArrayList<>(), - hostingServer.maxPlayers(), - hostingServer.shortName() - ); - return new GetServerForMapProtocolObject.GetServerForMapResponse(proxy, existingGameWithServer.game().getGameId().toString(), true, null); - } - } - - // If no existing game found, find a server that can instantiate a new one - OrchestratorCache.GameServerState availableServer = OrchestratorCache.instantiateServer(gameType, body.map()); - if (availableServer != null) { - try { - CompletableFuture responseFuture = ServiceToServerManager.sendToServer( - availableServer.uuid(), - new InstantiateGamePushProtocol(), - new InstantiateGamePushProtocol.Request(gameType.toString(), body.map()) - ); - - InstantiateGamePushProtocol.Response response = responseFuture.get(); - - if (response != null && response.success()) { - UnderstandableProxyServer proxy = new UnderstandableProxyServer( - availableServer.shortName(), - availableServer.uuid(), - availableServer.type(), - -1, - new ArrayList<>(), - availableServer.maxPlayers(), - availableServer.shortName() - ); - return new GetServerForMapProtocolObject.GetServerForMapResponse(proxy, response.gameId(), true, null); - } - } catch (Exception e) { - System.err.println("Failed to instantiate Bedwars game: " + e.getMessage()); - } - } - - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } catch (Exception e) { - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } - } - - private GetServerForMapProtocolObject.GetServerForMapResponse handleMurderMystery( - GetServerForMapProtocolObject.GetServerForMapMessage body) { - try { - MurderMysteryGameType gameType = parseMurderMysteryGameType(body.mode()); - if (gameType == null) { - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } - - int neededSlots = body.neededSlots() > 0 ? body.neededSlots() : 1; - - // First, try to find an existing joinable game with enough slots - OrchestratorCache.GameWithServer existingGameWithServer = OrchestratorCache.findExisting( - ServerType.MURDER_MYSTERY_GAME, gameType.getMaxPlayers(), body.map(), neededSlots, gameType.name()); - if (existingGameWithServer != null) { - OrchestratorCache.GameServerState hostingServer = OrchestratorCache.getServerByUuid(existingGameWithServer.serverUuid()); - if (hostingServer != null) { - UnderstandableProxyServer proxy = new UnderstandableProxyServer( - hostingServer.shortName(), - hostingServer.uuid(), - hostingServer.type(), - -1, - new ArrayList<>(), - hostingServer.maxPlayers(), - hostingServer.shortName() - ); - return new GetServerForMapProtocolObject.GetServerForMapResponse(proxy, existingGameWithServer.game().getGameId().toString(), true, null); - } - } - - // If no existing game found, find a server that can instantiate a new one - OrchestratorCache.GameServerState availableServer = OrchestratorCache.instantiateServer( - ServerType.MURDER_MYSTERY_GAME, gameType.getMaxPlayers()); - if (availableServer != null) { - try { - CompletableFuture responseFuture = ServiceToServerManager.sendToServer( - availableServer.uuid(), - new InstantiateGamePushProtocol(), - new InstantiateGamePushProtocol.Request(gameType.name(), body.map()) - ); - - InstantiateGamePushProtocol.Response response = responseFuture.get(); - - if (response != null && response.success()) { - UnderstandableProxyServer proxy = new UnderstandableProxyServer( - availableServer.shortName(), - availableServer.uuid(), - availableServer.type(), - -1, - new ArrayList<>(), - availableServer.maxPlayers(), - availableServer.shortName() - ); - return new GetServerForMapProtocolObject.GetServerForMapResponse(proxy, response.gameId(), true, null); - } - } catch (Exception e) { - System.err.println("Failed to instantiate Murder Mystery game: " + e.getMessage()); - } - } - - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } catch (Exception e) { - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } - } - - private BedwarsGameType parseBedwarsGameType(String mode) { - if (mode == null) return null; - - try { - return BedwarsGameType.valueOf(mode.toUpperCase()); - } catch (IllegalArgumentException e) { - switch (mode.toLowerCase()) { - case "solo", "1v1v1v1v1v1v1v1" -> { return BedwarsGameType.SOLO; } - case "doubles", "2v2v2v2" -> { return BedwarsGameType.DOUBLES; } - case "triples", "3v3v3v3" -> { return BedwarsGameType.THREE_THREE_THREE_THREE; } - case "quads", "4v4v4v4" -> { return BedwarsGameType.FOUR_FOUR_FOUR_FOUR; } - case "4v4" -> { return BedwarsGameType.FOUR_FOUR; } - default -> { return null; } - } - } - } - - private MurderMysteryGameType parseMurderMysteryGameType(String mode) { - if (mode == null) return null; - - // First try the enum's from() method - MurderMysteryGameType type = MurderMysteryGameType.from(mode); - if (type != null) return type; - - // Try display name - type = MurderMysteryGameType.fromDisplayName(mode); - if (type != null) return type; - - // Handle common aliases - return switch (mode.toLowerCase()) { - case "classic" -> MurderMysteryGameType.CLASSIC; - case "double_up", "doubleup", "double up" -> MurderMysteryGameType.DOUBLE_UP; - case "assassins" -> MurderMysteryGameType.ASSASSINS; - default -> null; - }; - } - - private GetServerForMapProtocolObject.GetServerForMapResponse handleSkywars( - GetServerForMapProtocolObject.GetServerForMapMessage body) { - try { - SkywarsGameType gameType = parseSkywarsGameType(body.mode()); - if (gameType == null) { - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } - - int neededSlots = body.neededSlots() > 0 ? body.neededSlots() : 1; - - // First, try to find an existing joinable game with enough slots - OrchestratorCache.GameWithServer existingGameWithServer = OrchestratorCache.findExisting( - ServerType.SKYWARS_GAME, gameType.getMaxPlayers(), body.map(), neededSlots, gameType.name()); - if (existingGameWithServer != null) { - OrchestratorCache.GameServerState hostingServer = OrchestratorCache.getServerByUuid(existingGameWithServer.serverUuid()); - if (hostingServer != null) { - UnderstandableProxyServer proxy = new UnderstandableProxyServer( - hostingServer.shortName(), - hostingServer.uuid(), - hostingServer.type(), - -1, - new ArrayList<>(), - hostingServer.maxPlayers(), - hostingServer.shortName() - ); - return new GetServerForMapProtocolObject.GetServerForMapResponse(proxy, existingGameWithServer.game().getGameId().toString(), true, null); - } - } - - // If no existing game found, find a server that can instantiate a new one - OrchestratorCache.GameServerState availableServer = OrchestratorCache.instantiateServer( - ServerType.SKYWARS_GAME, gameType.getMaxPlayers()); - if (availableServer != null) { - try { - CompletableFuture responseFuture = ServiceToServerManager.sendToServer( - availableServer.uuid(), - new InstantiateGamePushProtocol(), - new InstantiateGamePushProtocol.Request(gameType.name(), body.map()) - ); - - InstantiateGamePushProtocol.Response response = responseFuture.get(); - - if (response != null && response.success()) { - UnderstandableProxyServer proxy = new UnderstandableProxyServer( - availableServer.shortName(), - availableServer.uuid(), - availableServer.type(), - -1, - new ArrayList<>(), - availableServer.maxPlayers(), - availableServer.shortName() - ); - return new GetServerForMapProtocolObject.GetServerForMapResponse(proxy, response.gameId(), true, null); - } - } catch (Exception e) { - System.err.println("Failed to instantiate Skywars game: " + e.getMessage()); - } - } - - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } catch (Exception e) { - return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); - } - } - - private SkywarsGameType parseSkywarsGameType(String mode) { - if (mode == null) return null; - - // First try the enum's from() method - SkywarsGameType type = SkywarsGameType.from(mode); - if (type != null) return type; - - // Try display name - type = SkywarsGameType.fromDisplayName(mode); - if (type != null) return type; - - // Handle common aliases - return switch (mode.toLowerCase()) { - case "solo_normal", "solo normal", "normal" -> SkywarsGameType.SOLO_NORMAL; - case "solo_insane", "solo insane", "insane" -> SkywarsGameType.SOLO_INSANE; - case "doubles_normal", "doubles normal", "doubles" -> SkywarsGameType.DOUBLES_NORMAL; - case "solo_lucky_block", "lucky_block", "lucky block", "luckyblock" -> SkywarsGameType.SOLO_LUCKY_BLOCK; - default -> null; - }; - } + { + + @Override + public ProtocolObject associatedProtocolObject() { + return new GetServerForMapProtocolObject(); + } + + @Override + public GetServerForMapProtocolObject.GetServerForMapResponse onMessage(ServiceProxyRequest message, + GetServerForMapProtocolObject.GetServerForMapMessage body) { + return switch (body.type()) { + case BEDWARS_GAME -> handleBedwars(body); + case MURDER_MYSTERY_GAME -> handleMurderMystery(body); + case SKYWARS_GAME -> handleSkywars(body); + default -> new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + }; + } + + private GetServerForMapProtocolObject.GetServerForMapResponse handleBedwars( + GetServerForMapProtocolObject.GetServerForMapMessage body) { + try { + BedWarsGameType gameType = parseBedwarsGameType(body.mode()); + if (gameType == null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + + int neededSlots = body.neededSlots() > 0 ? body.neededSlots() : 1; + String requestedMap = body.map(); + + if (requestedMap != null) { + OrchestratorCache.GameWithServer existing = OrchestratorCache.findExisting(gameType, requestedMap, neededSlots); + if (existing != null) { + GetServerForMapProtocolObject.GetServerForMapResponse reused = responseFromExisting(existing); + if (reused.server() != null) { + return reused; + } + } + return instantiateBedwarsGame(gameType, requestedMap); + } + + OrchestratorCache.GameWithServer populatedExisting = OrchestratorCache.findMostPopulatedBedwarsGame(gameType, neededSlots); + if (populatedExisting != null) { + GetServerForMapProtocolObject.GetServerForMapResponse reused = responseFromExisting(populatedExisting); + if (reused.server() != null) { + return reused; + } + } + + String randomlyChosenMap = OrchestratorCache.pickRandomBedwarsMap(gameType); + if (randomlyChosenMap == null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + + OrchestratorCache.GameWithServer existingForRandomMap = OrchestratorCache.findExisting(gameType, randomlyChosenMap, neededSlots); + if (existingForRandomMap != null) { + GetServerForMapProtocolObject.GetServerForMapResponse reused = responseFromExisting(existingForRandomMap); + if (reused.server() != null) { + return reused; + } + } + + return instantiateBedwarsGame(gameType, randomlyChosenMap); + } catch (Exception e) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + } + + private GetServerForMapProtocolObject.GetServerForMapResponse instantiateBedwarsGame(BedWarsGameType gameType, String map) { + OrchestratorCache.GameServerState availableServer = OrchestratorCache.instantiateServer(gameType, map); + if (availableServer == null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + + try { + CompletableFuture responseFuture = ServiceToServerManager.sendToServer( + availableServer.uuid(), + new InstantiateGamePushProtocol(), + new InstantiateGamePushProtocol.Request(gameType.toString(), map) + ); + + InstantiateGamePushProtocol.Response response = responseFuture.get(); + if (response != null && response.success()) { + String gameId = response.gameId(); + if (gameId != null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(createProxy(availableServer), gameId, true, null); + } + } + } catch (Exception e) { + System.err.println("Failed to instantiate Bedwars game: " + e.getMessage()); + } + + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + + private GetServerForMapProtocolObject.GetServerForMapResponse responseFromExisting(OrchestratorCache.GameWithServer gameWithServer) { + OrchestratorCache.GameServerState hostingServer = OrchestratorCache.getServerByUuid(gameWithServer.serverUuid()); + if (hostingServer == null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + return new GetServerForMapProtocolObject.GetServerForMapResponse( + createProxy(hostingServer), + gameWithServer.game().getGameId().toString(), true, null + ); + } + + private UnderstandableProxyServer createProxy(OrchestratorCache.GameServerState server) { + return new UnderstandableProxyServer( + server.shortName(), + server.uuid(), + server.type(), + -1, + new ArrayList<>(), + server.maxPlayers(), + server.shortName() + ); + } + + private GetServerForMapProtocolObject.GetServerForMapResponse handleMurderMystery( + GetServerForMapProtocolObject.GetServerForMapMessage body) { + try { + MurderMysteryGameType gameType = parseMurderMysteryGameType(body.mode()); + if (gameType == null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + + int neededSlots = body.neededSlots() > 0 ? body.neededSlots() : 1; + + OrchestratorCache.GameWithServer existingGameWithServer = OrchestratorCache.findExisting( + ServerType.MURDER_MYSTERY_GAME, gameType.getMaxPlayers(), body.map(), neededSlots, gameType.name()); + if (existingGameWithServer != null) { + OrchestratorCache.GameServerState hostingServer = OrchestratorCache.getServerByUuid(existingGameWithServer.serverUuid()); + if (hostingServer != null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(createProxy(hostingServer), existingGameWithServer.game().getGameId().toString(), true, null); + } + } + + OrchestratorCache.GameServerState availableServer = OrchestratorCache.instantiateServer( + ServerType.MURDER_MYSTERY_GAME, gameType.getMaxPlayers()); + if (availableServer != null) { + try { + CompletableFuture responseFuture = ServiceToServerManager.sendToServer( + availableServer.uuid(), + new InstantiateGamePushProtocol(), + new InstantiateGamePushProtocol.Request(gameType.name(), body.map()) + ); + + InstantiateGamePushProtocol.Response response = responseFuture.get(); + + if (response != null && response.success()) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(createProxy(availableServer), response.gameId(), true, null); + } + } catch (Exception e) { + System.err.println("Failed to instantiate Murder Mystery game: " + e.getMessage()); + } + } + + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } catch (Exception e) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + } + + private GetServerForMapProtocolObject.GetServerForMapResponse handleSkywars( + GetServerForMapProtocolObject.GetServerForMapMessage body) { + try { + SkywarsGameType gameType = parseSkywarsGameType(body.mode()); + if (gameType == null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + + int neededSlots = body.neededSlots() > 0 ? body.neededSlots() : 1; + + OrchestratorCache.GameWithServer existingGameWithServer = OrchestratorCache.findExisting( + ServerType.SKYWARS_GAME, gameType.getMaxPlayers(), body.map(), neededSlots, gameType.name()); + if (existingGameWithServer != null) { + OrchestratorCache.GameServerState hostingServer = OrchestratorCache.getServerByUuid(existingGameWithServer.serverUuid()); + if (hostingServer != null) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(createProxy(hostingServer), existingGameWithServer.game().getGameId().toString(), true, null); + } + } + + OrchestratorCache.GameServerState availableServer = OrchestratorCache.instantiateServer( + ServerType.SKYWARS_GAME, gameType.getMaxPlayers()); + if (availableServer != null) { + try { + CompletableFuture responseFuture = ServiceToServerManager.sendToServer( + availableServer.uuid(), + new InstantiateGamePushProtocol(), + new InstantiateGamePushProtocol.Request(gameType.name(), body.map()) + ); + + InstantiateGamePushProtocol.Response response = responseFuture.get(); + + if (response != null && response.success()) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(createProxy(availableServer), response.gameId(), true, null); + } + } catch (Exception e) { + System.err.println("Failed to instantiate Skywars game: " + e.getMessage()); + } + } + + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } catch (Exception e) { + return new GetServerForMapProtocolObject.GetServerForMapResponse(null, null, true, null); + } + } + + private BedWarsGameType parseBedwarsGameType(String mode) { + if (mode == null) return null; + + BedWarsGameType type = BedWarsGameType.from(mode); + if (type != null) return type; + + return BedWarsGameType.fromDisplayName(mode); + } + + private MurderMysteryGameType parseMurderMysteryGameType(String mode) { + if (mode == null) return null; + + MurderMysteryGameType type = MurderMysteryGameType.from(mode); + if (type != null) return type; + + type = MurderMysteryGameType.fromDisplayName(mode); + if (type != null) return type; + + return switch (mode.toLowerCase()) { + case "classic" -> MurderMysteryGameType.CLASSIC; + case "double_up", "doubleup", "double up" -> MurderMysteryGameType.DOUBLE_UP; + case "assassins" -> MurderMysteryGameType.ASSASSINS; + default -> null; + }; + } + + private SkywarsGameType parseSkywarsGameType(String mode) { + if (mode == null) return null; + + SkywarsGameType type = SkywarsGameType.from(mode); + if (type != null) return type; + + type = SkywarsGameType.fromDisplayName(mode); + if (type != null) return type; + + return switch (mode.toLowerCase()) { + case "solo_normal", "solo normal", "normal" -> SkywarsGameType.SOLO_NORMAL; + case "solo_insane", "solo insane", "insane" -> SkywarsGameType.SOLO_INSANE; + case "doubles_normal", "doubles normal", "doubles" -> SkywarsGameType.DOUBLES_NORMAL; + case "solo_lucky_block", "lucky_block", "lucky block", "luckyblock" -> SkywarsGameType.SOLO_LUCKY_BLOCK; + default -> null; + }; + } } diff --git a/service.party/build.gradle.kts b/service.party/build.gradle.kts index e60f3c4c9..cf630f248 100644 --- a/service.party/build.gradle.kts +++ b/service.party/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.punishment/build.gradle.kts b/service.punishment/build.gradle.kts index 677ae159f..2cae97e8d 100644 --- a/service.punishment/build.gradle.kts +++ b/service.punishment/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/service.punishment/src/main/java/net/swofty/service/punishment/PunishmentDatabase.java b/service.punishment/src/main/java/net/swofty/service/punishment/PunishmentDatabase.java index a9e65f38e..d00db7265 100644 --- a/service.punishment/src/main/java/net/swofty/service/punishment/PunishmentDatabase.java +++ b/service.punishment/src/main/java/net/swofty/service/punishment/PunishmentDatabase.java @@ -10,6 +10,7 @@ import com.mongodb.client.model.Updates; import net.swofty.service.generic.MongoDB; import org.bson.Document; +import org.jspecify.annotations.NonNull; public record PunishmentDatabase(String playerId) implements MongoDB { public static MongoClient client; @@ -17,7 +18,7 @@ public record PunishmentDatabase(String playerId) implements MongoDB { public static MongoCollection punishmentCollection; @Override - public MongoDB connect(String connectionString) { + public @NonNull MongoDB connect(@NonNull String connectionString) { ConnectionString cs = new ConnectionString(connectionString); MongoClientSettings settings = MongoClientSettings.builder().applyConnectionString(cs).build(); client = MongoClients.create(settings); @@ -28,7 +29,7 @@ public MongoDB connect(String connectionString) { } @Override - public void set(String key, Object value) { + public void set(@NonNull String key, Object value) { insertOrUpdate(key, value); } @@ -40,7 +41,7 @@ public boolean exists() { } @Override - public Object get(String key, Object def) { + public Object get(@NonNull String key, Object def) { Document doc = punishmentCollection.find(Filters.eq("_id", playerId)).first(); if (doc == null) { return def; @@ -49,7 +50,7 @@ public Object get(String key, Object def) { } @Override - public void insertOrUpdate(String key, Object value) { + public void insertOrUpdate(@NonNull String key, Object value) { if (exists()) { Document query = new Document("_id", playerId); Document found = punishmentCollection.find(query).first(); @@ -63,7 +64,7 @@ public void insertOrUpdate(String key, Object value) { } @Override - public boolean remove(String id) { + public boolean remove(@NonNull String id) { Document query = new Document("_id", id); Document found = punishmentCollection.find(query).first(); if (found == null) { diff --git a/service.replay/build.gradle.kts b/service.replay/build.gradle.kts new file mode 100644 index 000000000..21b27b013 --- /dev/null +++ b/service.replay/build.gradle.kts @@ -0,0 +1,48 @@ +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar + +plugins { + java + application + id("com.gradleup.shadow") version "9.3.1" +} + +group = "net.swofty" +version = "3.0" + +java { + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 + toolchain { + languageVersion.set(JavaLanguageVersion.of(25)) + } +} + +repositories { + maven("https://jitpack.io") + mavenCentral() +} + +dependencies { + implementation(project(":service.generic")) + implementation(project(":type.game")) + implementation(project(":commons")) + implementation(libs.caffeine) + implementation(libs.tinylog.api) + implementation(libs.tinylog.impl) + implementation(libs.gson) + implementation(libs.mongodb.bson) + implementation(libs.mongodb.driver.sync) + +} + +application { + mainClass.set("net.swofty.service.replay.ReplayService") +} + +tasks { + named("shadowJar") { + archiveBaseName.set("ServiceReplay") + archiveClassifier.set("") + archiveVersion.set("") + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/ReplayService.java b/service.replay/src/main/java/net/swofty/service/replay/ReplayService.java new file mode 100644 index 000000000..566b12148 --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/ReplayService.java @@ -0,0 +1,45 @@ +package net.swofty.service.replay; + +import lombok.Getter; +import net.swofty.commons.ServiceType; +import net.swofty.commons.config.ConfigProvider; +import net.swofty.service.generic.SkyBlockService; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.session.ReplaySessionManager; +import net.swofty.service.replay.storage.ReplayDatabase; +import org.tinylog.Logger; + +import java.util.List; + +public class ReplayService implements SkyBlockService { + + @Getter + private static ReplayDatabase database; + @Getter + private static ReplaySessionManager sessionManager; + + static void main() { + Logger.info("Starting Replay Service..."); + + String mongoUri = ConfigProvider.settings().getMongodb(); + database = new ReplayDatabase(); + database.connect(mongoUri); + + sessionManager = new ReplaySessionManager(database); + sessionManager.startCleanupTask(); + + SkyBlockService.init(new ReplayService()); + + Logger.info("Replay Service started successfully"); + } + + @Override + public ServiceType getType() { + return ServiceType.REPLAY; + } + + @Override + public List getEndpoints() { + return loopThroughPackage("net.swofty.service.replay.endpoints", ServiceEndpoint.class).toList(); + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayChooseEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayChooseEndpoint.java new file mode 100644 index 000000000..e960f426c --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayChooseEndpoint.java @@ -0,0 +1,25 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.ProtocolObject; +import net.swofty.commons.protocol.objects.replay.ChooseReplayProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.generic.redis.ServiceToServerManager; + +public class ReplayChooseEndpoint implements ServiceEndpoint + { + + @Override + public ProtocolObject associatedProtocolObject() { + return new ChooseReplayProtocolObject(); + } + + @Override + public ChooseReplayProtocolObject.ChooseReplayResponse onMessage(ServiceProxyRequest message, + ChooseReplayProtocolObject.ChooseReplayMessage body) { + ServiceToServerManager.viewReplay(body.player(), body.replayId(), body.shareCode()); + return new ChooseReplayProtocolObject.ChooseReplayResponse(false); + } + +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayDataBatchEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayDataBatchEndpoint.java new file mode 100644 index 000000000..c1c87e2b8 --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayDataBatchEndpoint.java @@ -0,0 +1,43 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.replay.ReplayDataBatchProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.ReplayService; +import org.tinylog.Logger; + +public class ReplayDataBatchEndpoint implements ServiceEndpoint< + ReplayDataBatchProtocolObject.BatchMessage, + ReplayDataBatchProtocolObject.BatchResponse> { + + @Override + public ReplayDataBatchProtocolObject associatedProtocolObject() { + return new ReplayDataBatchProtocolObject(); + } + + @Override + public ReplayDataBatchProtocolObject.BatchResponse onMessage( + ServiceProxyRequest message, + ReplayDataBatchProtocolObject.BatchMessage msg) { + + try { + ReplayService.getSessionManager().receiveBatch( + msg.replayId(), + msg.batchIndex(), + msg.startTick(), + msg.endTick(), + msg.recordableCount(), + msg.compressedData() + ); + + Logger.debug("Received batch {} for replay {} ({} bytes, ticks {}-{})", + msg.batchIndex(), msg.replayId(), msg.compressedData().length, msg.startTick(), msg.endTick()); + + return new ReplayDataBatchProtocolObject.BatchResponse(true, msg.compressedData().length); + + } catch (Exception e) { + Logger.error(e, "Failed to process replay batch"); + return new ReplayDataBatchProtocolObject.BatchResponse(false, 0); + } + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayEndEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayEndEndpoint.java new file mode 100644 index 000000000..8d55decdb --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayEndEndpoint.java @@ -0,0 +1,51 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.replay.ReplayEndProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.ReplayService; +import net.swofty.service.replay.session.ReplaySessionManager; +import org.tinylog.Logger; + +import java.util.concurrent.TimeUnit; + +public class ReplayEndEndpoint implements ServiceEndpoint< + ReplayEndProtocolObject.EndMessage, + ReplayEndProtocolObject.EndResponse> { + + @Override + public ReplayEndProtocolObject associatedProtocolObject() { + return new ReplayEndProtocolObject(); + } + + @Override + public ReplayEndProtocolObject.EndResponse onMessage( + ServiceProxyRequest message, + ReplayEndProtocolObject.EndMessage msg) { + + try { + Logger.info("Ending replay session {} (duration: {} ticks)", msg.replayId(), msg.durationTicks()); + ReplaySessionManager.EndResult result = ReplayService.getSessionManager() + .endSession( + msg.replayId(), + msg.endTime(), + msg.durationTicks() + ) + .get(30, TimeUnit.SECONDS); // Wait up to 30 seconds + + Logger.info("Replay {} finalized: {} -> {} bytes", + msg.replayId(), result.totalBytes(), result.compressedBytes()); + + return new ReplayEndProtocolObject.EndResponse( + result.success(), + result.totalBytes(), + result.compressedBytes(), + result.success() + ); + + } catch (Exception e) { + Logger.error(e, "Failed to end replay session"); + return new ReplayEndProtocolObject.EndResponse(false, 0, 0, false); + } + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayListEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayListEndpoint.java new file mode 100644 index 000000000..aa3f558aa --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayListEndpoint.java @@ -0,0 +1,68 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.ServerType; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.replay.ReplayListProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.ReplayService; +import org.bson.Document; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ReplayListEndpoint implements ServiceEndpoint< + ReplayListProtocolObject.ListRequest, + ReplayListProtocolObject.ListResponse> { + + @Override + public ReplayListProtocolObject associatedProtocolObject() { + return new ReplayListProtocolObject(); + } + + @Override + public ReplayListProtocolObject.ListResponse onMessage( + ServiceProxyRequest message, + ReplayListProtocolObject.ListRequest msg) { + + try { + List docs = ReplayService.getDatabase().getReplaysByPlayer(msg.playerId(), msg.limit()); + + List replays = new ArrayList<>(); + for (Document doc : docs) { + Map players = new HashMap<>(); + Document playerNames = doc.get("playerNames", Document.class); + if (playerNames != null) { + playerNames.forEach((key, value) -> players.put(UUID.fromString(key), (String) value)); + } + + replays.add(new ReplayListProtocolObject.ReplaySummary( + UUID.fromString(doc.getString("replayId")), + doc.getString("gameId"), + ServerType.valueOf(doc.getString("serverType")), + doc.getString("serverId"), + doc.getString("gameTypeName"), + doc.getString("mapName"), + doc.getLong("startTime"), + doc.getLong("endTime"), + doc.getInteger("durationTicks"), + players.size(), + players, + doc.getString("winnerId"), + doc.getString("winnerType"), + doc.getLong("dataSize") + )); + } + + Logger.debug("Returning {} replays for player {}", replays.size(), msg.playerId()); + return new ReplayListProtocolObject.ListResponse(true, replays); + + } catch (Exception e) { + Logger.error(e, "Failed to fetch replays for player {}", msg.playerId()); + return new ReplayListProtocolObject.ListResponse(false, List.of()); + } + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayLoadEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayLoadEndpoint.java new file mode 100644 index 000000000..15b05f928 --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayLoadEndpoint.java @@ -0,0 +1,141 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.ServerType; +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.replay.ReplayLoadProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.ReplayService; +import org.bson.Document; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ReplayLoadEndpoint implements ServiceEndpoint< + ReplayLoadProtocolObject.LoadRequest, + ReplayLoadProtocolObject.LoadResponse> { + + @Override + public ReplayLoadProtocolObject associatedProtocolObject() { + return new ReplayLoadProtocolObject(); + } + + @Override + public ReplayLoadProtocolObject.LoadResponse onMessage( + ServiceProxyRequest message, + ReplayLoadProtocolObject.LoadRequest msg) { + + try { + UUID replayId = msg.replayId(); + Document metadataDoc = ReplayService.getDatabase().getReplayMetadata(replayId); + if (metadataDoc == null) { + Logger.warn("Replay not found: {}", replayId); + return new ReplayLoadProtocolObject.LoadResponse( + false, + "Replay not found", + null, + null + ); + } + + // Parse metadata + ReplayLoadProtocolObject.ReplayMetadata metadata = parseMetadata(metadataDoc); + + // Fetch data chunks + List chunkDocs = ReplayService.getDatabase().getReplayDataChunks(replayId); + List dataChunks = new ArrayList<>(); + + for (Document chunkDoc : chunkDocs) { + byte[] data = chunkDoc.get("data", org.bson.types.Binary.class).getData(); + dataChunks.add(new ReplayLoadProtocolObject.DataChunk( + chunkDoc.getInteger("chunkIndex"), + chunkDoc.getInteger("startTick"), + chunkDoc.getInteger("endTick"), + data + )); + } + + Logger.debug("Loaded replay {} with {} chunks", replayId, dataChunks.size()); + + return new ReplayLoadProtocolObject.LoadResponse( + true, + null, + metadata, + dataChunks + ); + + } catch (Exception e) { + Logger.error(e, "Failed to load replay {}", msg.replayId()); + return new ReplayLoadProtocolObject.LoadResponse( + false, + "Failed to load replay: " + e.getMessage(), + null, + null + ); + } + } + + private ReplayLoadProtocolObject.ReplayMetadata parseMetadata(Document doc) { + Map players = new HashMap<>(); + Document playerNames = doc.get("playerNames", Document.class); + if (playerNames != null) { + playerNames.forEach((key, value) -> players.put(UUID.fromString(key), (String) value)); + } + + Map> teams = new HashMap<>(); + Document teamsDoc = doc.get("teams", Document.class); + if (teamsDoc != null) { + teamsDoc.forEach((teamId, value) -> { + @SuppressWarnings("unchecked") + List playerList = (List) value; + List playerUUIDs = new ArrayList<>(); + for (String uuidStr : playerList) { + playerUUIDs.add(UUID.fromString(uuidStr)); + } + teams.put(teamId, playerUUIDs); + }); + } + + Map teamInfo = new HashMap<>(); + Document teamInfoDoc = doc.get("teamInfo", Document.class); + if (teamInfoDoc != null) { + teamInfoDoc.forEach((teamId, value) -> { + Document infoDoc = (Document) value; + teamInfo.put(teamId, new ReplayLoadProtocolObject.TeamInfo( + infoDoc.getString("name"), + infoDoc.getString("colorCode"), + infoDoc.getInteger("color") + )); + }); + } + + String mapHash = doc.getString("mapHash"); + String winnerId = doc.getString("winnerId"); + String winnerType = doc.getString("winnerType"); + + return new ReplayLoadProtocolObject.ReplayMetadata( + UUID.fromString(doc.getString("replayId")), + doc.getString("gameId"), + ServerType.valueOf(doc.getString("serverType")), + doc.getString("serverId"), + doc.getString("gameTypeName"), + doc.getString("mapName"), + mapHash, + doc.getInteger("version", 1), + doc.getLong("startTime"), + doc.getLong("endTime"), + doc.getInteger("durationTicks"), + players, + teams, + teamInfo, + winnerId, + winnerType, + doc.getLong("dataSize"), + doc.getDouble("mapCenterX"), + doc.getDouble("mapCenterZ") + ); + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayMapLoadEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayMapLoadEndpoint.java new file mode 100644 index 000000000..3a4141dab --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayMapLoadEndpoint.java @@ -0,0 +1,47 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.replay.ReplayMapLoadProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.ReplayService; +import org.tinylog.Logger; + +public class ReplayMapLoadEndpoint implements ServiceEndpoint< + ReplayMapLoadProtocolObject.MapLoadRequest, + ReplayMapLoadProtocolObject.MapLoadResponse> { + @Override + public ReplayMapLoadProtocolObject associatedProtocolObject() { + return new ReplayMapLoadProtocolObject(); + } + + @Override + public ReplayMapLoadProtocolObject.MapLoadResponse onMessage( + ServiceProxyRequest message, + ReplayMapLoadProtocolObject.MapLoadRequest msg) { + try { + String mapHash = msg.mapHash(); + if (!ReplayService.getDatabase().hasMap(mapHash)) { + Logger.debug("Map not found: {}", mapHash); + return new ReplayMapLoadProtocolObject.MapLoadResponse( + true, false, null, null, 0 + ); + } + byte[] compressedData = ReplayService.getDatabase().getMapData(mapHash); + if (compressedData == null) { + Logger.warn("Map data is null for hash: {}", mapHash); + return new ReplayMapLoadProtocolObject.MapLoadResponse( + false, false, null, null, 0 + ); + } + Logger.info("Loaded map {} - {} bytes", mapHash, compressedData.length); + return new ReplayMapLoadProtocolObject.MapLoadResponse( + true, true, mapHash, compressedData, 0 + ); + } catch (Exception e) { + Logger.error(e, "Failed to load map {}", msg.mapHash()); + return new ReplayMapLoadProtocolObject.MapLoadResponse( + false, false, null, null, 0 + ); + } + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayMapUploadEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayMapUploadEndpoint.java new file mode 100644 index 000000000..b382d8a9f --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayMapUploadEndpoint.java @@ -0,0 +1,41 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.replay.ReplayMapUploadProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.ReplayService; +import org.tinylog.Logger; + +public class ReplayMapUploadEndpoint implements ServiceEndpoint< + ReplayMapUploadProtocolObject.MapUploadMessage, + ReplayMapUploadProtocolObject.MapUploadResponse> { + + @Override + public ReplayMapUploadProtocolObject associatedProtocolObject() { + return new ReplayMapUploadProtocolObject(); + } + + @Override + public ReplayMapUploadProtocolObject.MapUploadResponse onMessage( + ServiceProxyRequest message, + ReplayMapUploadProtocolObject.MapUploadMessage msg) { + + try { + // Check if map already exists + if (ReplayService.getDatabase().hasMap(msg.mapHash())) { + Logger.debug("Map {} already exists", msg.mapHash()); + return new ReplayMapUploadProtocolObject.MapUploadResponse(true, true); + } + + // Save map + ReplayService.getDatabase().saveMap(msg.mapHash(), msg.mapName(), msg.compressedData()); + Logger.info("Saved map {} ({}) - {} bytes", msg.mapName(), msg.mapHash(), msg.compressedData().length); + + return new ReplayMapUploadProtocolObject.MapUploadResponse(true, false); + + } catch (Exception e) { + Logger.error(e, "Failed to upload map"); + return new ReplayMapUploadProtocolObject.MapUploadResponse(false, false); + } + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayStartEndpoint.java b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayStartEndpoint.java new file mode 100644 index 000000000..026a91565 --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/endpoints/ReplayStartEndpoint.java @@ -0,0 +1,59 @@ +package net.swofty.service.replay.endpoints; + +import net.swofty.commons.impl.ServiceProxyRequest; +import net.swofty.commons.protocol.objects.replay.ReplayStartProtocolObject; +import net.swofty.service.generic.redis.ServiceEndpoint; +import net.swofty.service.replay.ReplayService; +import net.swofty.type.game.replay.ReplayMetadata; +import org.tinylog.Logger; + +import java.util.HashMap; +import java.util.Map; + +public class ReplayStartEndpoint implements ServiceEndpoint< + ReplayStartProtocolObject.StartMessage, + ReplayStartProtocolObject.StartResponse> { + + @Override + public ReplayStartProtocolObject associatedProtocolObject() { + return new ReplayStartProtocolObject(); + } + + @Override + public ReplayStartProtocolObject.StartResponse onMessage( + ServiceProxyRequest message, + ReplayStartProtocolObject.StartMessage msg) { + + try { + Map teamInfo = new HashMap<>(); + msg.teamInfo().forEach((teamId, info) -> + teamInfo.put(teamId, new ReplayMetadata.TeamInfo(info.name(), info.colorCode(), info.color())) + ); + + ReplayService.getSessionManager().startSession( + msg.replayId(), + msg.gameId(), + msg.serverType(), + msg.serverId(), + msg.gameTypeName(), + msg.mapName(), + msg.mapHash(), + msg.startTime(), + msg.mapCenterX(), + msg.mapCenterZ(), + msg.players(), + msg.teams(), + teamInfo + ); + + Logger.info("Started replay session {} for game {} with {} players", + msg.replayId(), msg.gameId(), msg.players().size()); + + return new ReplayStartProtocolObject.StartResponse(true, null); + + } catch (Exception e) { + Logger.error(e, "Failed to start replay session"); + return new ReplayStartProtocolObject.StartResponse(false, e.getMessage()); + } + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/session/RecordingSession.java b/service.replay/src/main/java/net/swofty/service/replay/session/RecordingSession.java new file mode 100644 index 000000000..dcd9658f9 --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/session/RecordingSession.java @@ -0,0 +1,109 @@ +package net.swofty.service.replay.session; + +import lombok.Getter; +import lombok.Setter; +import net.swofty.commons.ServerType; +import net.swofty.type.game.replay.ReplayMetadata; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentSkipListMap; + +@Getter +public class RecordingSession { + private final UUID replayId; + private final String gameId; + private final ServerType serverType; + private final String serverId; + private final String gameTypeName; + private final String mapName; + private final String mapHash; + private final long startTime; + private final double mapCenterX; + private final double mapCenterZ; + private final Map players; + private final Map> teams; + private final Map teamInfo; + + @Setter + private long endTime; + @Setter + private int durationTicks; + @Setter + private String winnerId; + @Setter + private String winnerType; + + // Batches ordered by index + private final ConcurrentSkipListMap batches = new ConcurrentSkipListMap<>(); + private volatile long lastDataTime; + private volatile int highestTick = 0; + + // this is so large, so maybe a builder that requires all fields could be cleaner? + public RecordingSession( + UUID replayId, + String gameId, + ServerType serverType, + String serverId, + String gameTypeName, + String mapName, + String mapHash, + long startTime, + double mapCenterX, + double mapCenterZ, + Map players, + Map> teams, + Map teamInfo + ) { + this.replayId = replayId; + this.gameId = gameId; + this.serverType = serverType; + this.serverId = serverId; + this.gameTypeName = gameTypeName; + this.mapName = mapName; + this.mapHash = mapHash; + this.startTime = startTime; + this.mapCenterX = mapCenterX; + this.mapCenterZ = mapCenterZ; + this.players = new HashMap<>(players); + this.teams = new HashMap<>(teams); + this.teamInfo = new HashMap<>(teamInfo); + this.lastDataTime = System.currentTimeMillis(); + } + + public void addBatch(int index, int startTick, int endTick, int recordableCount, byte[] compressedData) { + batches.put(index, new DataBatch(index, startTick, endTick, recordableCount, compressedData)); + lastDataTime = System.currentTimeMillis(); + if (endTick > highestTick) { + highestTick = endTick; + } + } + + public List getOrderedBatches() { + return new ArrayList<>(batches.values()); + } + + public long getTotalBytesReceived() { + return batches.values().stream() + .mapToLong(b -> b.compressedData.length) + .sum(); + } + + public int getTotalRecordableCount() { + return batches.values().stream() + .mapToInt(DataBatch::recordableCount) + .sum(); + } + + public record DataBatch( + int index, + int startTick, + int endTick, + int recordableCount, + byte[] compressedData + ) { + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/session/ReplaySessionManager.java b/service.replay/src/main/java/net/swofty/service/replay/session/ReplaySessionManager.java new file mode 100644 index 000000000..eab21a7ae --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/session/ReplaySessionManager.java @@ -0,0 +1,196 @@ +package net.swofty.service.replay.session; + +import net.swofty.commons.ServerType; +import net.swofty.service.replay.storage.ReplayDatabase; +import net.swofty.type.game.replay.ReplayMetadata; +import net.swofty.type.game.replay.ReplayVersion; +import org.bson.Document; +import org.tinylog.Logger; + +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class ReplaySessionManager { + private final ReplayDatabase database; + private final Map activeSessions = new ConcurrentHashMap<>(); + private final ScheduledExecutorService cleanupExecutor = Executors.newSingleThreadScheduledExecutor(); + private final ExecutorService compressionExecutor = Executors.newFixedThreadPool(4); + + // Session timeout - if no data received for this long, session is considered stale + private static final long SESSION_TIMEOUT_MS = 5 * 60 * 1000; // 5 minutes + + public ReplaySessionManager(ReplayDatabase database) { + this.database = database; + } + + public RecordingSession startSession( + UUID replayId, + String gameId, + ServerType serverType, + String serverId, + String gameTypeName, + String mapName, + String mapHash, + long startTime, + double mapCenterX, + double mapCenterZ, + Map players, + Map> teams, + Map teamInfo + ) { + RecordingSession session = new RecordingSession( + replayId, gameId, serverType, serverId, gameTypeName, mapName, mapHash, + startTime, mapCenterX, mapCenterZ, players, teams, teamInfo + ); + + activeSessions.put(replayId, session); + Logger.info("Started replay recording session {} for game {}", replayId, gameId); + + return session; + } + + public RecordingSession getSession(UUID replayId) { + return activeSessions.get(replayId); + } + + public void receiveBatch(UUID replayId, int batchIndex, int startTick, int endTick, int recordableCount, byte[] compressedData) { + RecordingSession session = activeSessions.get(replayId); + if (session == null) { + Logger.warn("Received data for unknown session: {}", replayId); + return; + } + + session.addBatch(batchIndex, startTick, endTick, recordableCount, compressedData); + } + + public CompletableFuture endSession(UUID replayId, long endTime, int durationTicks) { + RecordingSession session = activeSessions.remove(replayId); + if (session == null) { + return CompletableFuture.completedFuture(new EndResult(false, 0, 0)); + } + + session.setEndTime(endTime); + session.setDurationTicks(durationTicks); + + return CompletableFuture.supplyAsync(() -> { + try { + return finalizeSession(session); + } catch (Exception e) { + Logger.error(e, "Failed to finalize session {}", replayId); + return new EndResult(false, 0, 0); + } + }, compressionExecutor); + } + + private EndResult finalizeSession(RecordingSession session) { + Logger.info("Finalizing replay session {}", session.getReplayId()); + + long compressedBytes = 0; + + // Process and store each batch + List batches = session.getOrderedBatches(); + for (RecordingSession.DataBatch batch : batches) { + database.saveReplayDataChunk( + session.getReplayId(), + batch.index(), + batch.compressedData(), + batch.startTick(), + batch.endTick() + ); + compressedBytes += batch.compressedData().length; + } + + // Store metadata + Document metadata = createMetadataDocument(session, compressedBytes); + database.saveReplayMetadata(metadata); + + Logger.info("Replay {} finalized: {} compressed bytes", + session.getReplayId(), compressedBytes); + + return new EndResult(true, compressedBytes, compressedBytes); + } + + private Document createMetadataDocument(RecordingSession session, long dataSize) { + Document doc = new Document() + .append("replayId", session.getReplayId().toString()) + .append("gameId", session.getGameId()) + .append("serverType", session.getServerType().name()) + .append("serverId", session.getServerId()) + .append("gameTypeName", session.getGameTypeName()) + .append("mapName", session.getMapName()) + .append("mapHash", session.getMapHash()) + .append("version", ReplayVersion.CURRENT_VERSION) + .append("startTime", session.getStartTime()) + .append("endTime", session.getEndTime()) + .append("durationTicks", session.getDurationTicks()) + .append("mapCenterX", session.getMapCenterX()) + .append("mapCenterZ", session.getMapCenterZ()) + .append("dataSize", dataSize); + + // Players + List playerIds = new ArrayList<>(); + Document playerNames = new Document(); + session.getPlayers().forEach((uuid, name) -> { + playerIds.add(uuid.toString()); + playerNames.append(uuid.toString(), name); + }); + doc.append("players", playerIds); + doc.append("playerNames", playerNames); + + // Teams + Document teams = new Document(); + session.getTeams().forEach((teamId, uuids) -> { + List uuidStrings = uuids.stream().map(UUID::toString).toList(); + teams.append(teamId, uuidStrings); + }); + doc.append("teams", teams); + + // Team info + Document teamInfo = new Document(); + session.getTeamInfo().forEach((teamId, info) -> { + teamInfo.append(teamId, new Document() + .append("name", info.name()) + .append("colorCode", info.colorCode()) + .append("color", info.color()) + ); + }); + doc.append("teamInfo", teamInfo); + + // Winner + if (session.getWinnerId() != null) { + doc.append("winnerId", session.getWinnerId()); + doc.append("winnerType", session.getWinnerType()); + } + + return doc; + } + + public void startCleanupTask() { + cleanupExecutor.scheduleAtFixedRate(() -> { + long now = System.currentTimeMillis(); + activeSessions.entrySet().removeIf(entry -> { + if (now - entry.getValue().getLastDataTime() > SESSION_TIMEOUT_MS) { + Logger.warn("Removing stale replay session: {}", entry.getKey()); + return true; + } + return false; + }); + }, 1, 1, TimeUnit.MINUTES); + } + + public int getActiveSessionCount() { + return activeSessions.size(); + } + + public record EndResult(boolean success, long totalBytes, long compressedBytes) { + } +} diff --git a/service.replay/src/main/java/net/swofty/service/replay/storage/ReplayDatabase.java b/service.replay/src/main/java/net/swofty/service/replay/storage/ReplayDatabase.java new file mode 100644 index 000000000..bc7bf57b8 --- /dev/null +++ b/service.replay/src/main/java/net/swofty/service/replay/storage/ReplayDatabase.java @@ -0,0 +1,145 @@ +package net.swofty.service.replay.storage; + +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoClients; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.IndexOptions; +import com.mongodb.client.model.Indexes; +import com.mongodb.client.model.ReplaceOptions; +import org.bson.Document; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ReplayDatabase { + private MongoClient client; + private MongoDatabase database; + private MongoCollection replays; + private MongoCollection replayData; + private MongoCollection maps; + + public void connect(String mongoUri) { + Logger.info("Connecting to MongoDB..."); + client = MongoClients.create(mongoUri); + database = client.getDatabase("Minestom"); + + replays = database.getCollection("replays"); + replayData = database.getCollection("replay_data"); + maps = database.getCollection("replay_maps"); + + replays.createIndex(Indexes.ascending("replayId"), new IndexOptions().unique(true)); + replays.createIndex(Indexes.ascending("gameId")); + replays.createIndex(Indexes.descending("startTime")); + replays.createIndex(Indexes.ascending("players")); + + replayData.createIndex(Indexes.ascending("replayId", "chunkIndex"), new IndexOptions().unique(true)); + + maps.createIndex(Indexes.ascending("hash"), new IndexOptions().unique(true)); + + Logger.info("Connected to MongoDB, collections initialized"); + } + + public void saveReplayMetadata(Document metadata) { + replays.replaceOne( + Filters.eq("replayId", metadata.getString("replayId")), + metadata, + new ReplaceOptions().upsert(true) + ); + } + + public Document getReplayMetadata(UUID replayId) { + return replays.find(Filters.eq("replayId", replayId.toString())).first(); + } + + public List getReplaysByPlayer(UUID playerId, int limit) { + return replays.find(Filters.eq("players", playerId.toString())) + .sort(new Document("startTime", -1)) + .limit(limit) + .into(new ArrayList<>()); + } + + public List getReplaysByGame(String gameId) { + return replays.find(Filters.eq("gameId", gameId)) + .into(new ArrayList<>()); + } + + + public void saveReplayDataChunk(UUID replayId, int chunkIndex, byte[] compressedData, int startTick, int endTick) { + Document doc = new Document() + .append("replayId", replayId.toString()) + .append("chunkIndex", chunkIndex) + .append("startTick", startTick) + .append("endTick", endTick) + .append("data", compressedData) + .append("size", compressedData.length); + + replayData.replaceOne( + Filters.and( + Filters.eq("replayId", replayId.toString()), + Filters.eq("chunkIndex", chunkIndex) + ), + doc, + new ReplaceOptions().upsert(true) + ); + } + + public List getReplayDataChunks(UUID replayId) { + return replayData.find(Filters.eq("replayId", replayId.toString())) + .sort(new Document("chunkIndex", 1)) + .into(new ArrayList<>()); + } + + public Document getReplayDataChunk(UUID replayId, int chunkIndex) { + return replayData.find(Filters.and( + Filters.eq("replayId", replayId.toString()), + Filters.eq("chunkIndex", chunkIndex) + )).first(); + } + + public boolean hasMap(String mapHash) { + return maps.countDocuments(Filters.eq("hash", mapHash)) > 0; + } + + public void saveMap(String mapHash, String mapName, byte[] compressedData) { + Document doc = new Document() + .append("hash", mapHash) + .append("name", mapName) + .append("data", compressedData) + .append("size", compressedData.length) + .append("uploadedAt", System.currentTimeMillis()); + + maps.replaceOne( + Filters.eq("hash", mapHash), + doc, + new ReplaceOptions().upsert(true) + ); + } + + public byte[] getMapData(String mapHash) { + Document doc = maps.find(Filters.eq("hash", mapHash)).first(); + if (doc == null) return null; + return doc.get("data", org.bson.types.Binary.class).getData(); + } + + public Document getMapMetadata(String mapHash) { + return maps.find(Filters.eq("hash", mapHash)).first(); + } + + public long getTotalReplays() { + return replays.countDocuments(); + } + + public long getTotalMaps() { + return maps.countDocuments(); + } + + public long getTotalDataSize() { + // Approximate total size from replay_data collection + Document result = database.runCommand(new Document("collStats", "replay_data")); + return result.getInteger("size", 0); + } +} diff --git a/settings.gradle.kts b/settings.gradle.kts index d3db14d90..de900bd9d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,6 +10,7 @@ include(":service.generic") include(":type.generic") include(":type.skyblockgeneric") include(":type.lobby") +include(":type.game") include(":spark") include(":loader") include(":pvp") @@ -40,7 +41,9 @@ include(":type.skywarsgame") include(":type.skywarsconfigurator") include(":type.ravengardgeneric") include(":type.ravengardlobby") +include(":type.mainlobby") +include(":type.replayviewer") include(":service.auctionhouse") include(":service.bazaar") include(":service.itemtracker") @@ -50,6 +53,8 @@ include(":service.party") include(":service.orchestrator") include(":service.darkauction") include(":service.friend") +include(":service.replay") include(":service.punishment") include(":service.elections") +include(":service.guild") include(":anticheat") diff --git a/setup/lib/setup.sh b/setup/lib/setup.sh index ee7c116c3..c0291fa47 100644 --- a/setup/lib/setup.sh +++ b/setup/lib/setup.sh @@ -253,7 +253,7 @@ ${redis_ports} - hypixel_network pico_limbo: - image: ghcr.io/ariksquad/picolimbo:master + image: ghcr.io/quozul/picolimbo:v1.12.2-mc26.1.2 container_name: pico_limbo restart: unless-stopped environment: diff --git a/spark/build.gradle.kts b/spark/build.gradle.kts index 0fe015dfa..5f411f5a3 100644 --- a/spark/build.gradle.kts +++ b/spark/build.gradle.kts @@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { java application - id("com.gradleup.shadow") version "9.3.2" + alias(libs.plugins.shadow) } group = "net.swofty" diff --git a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/TypeBedWarsConfiguratorLoader.java b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/TypeBedWarsConfiguratorLoader.java index dbc62a348..9de225df0 100644 --- a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/TypeBedWarsConfiguratorLoader.java +++ b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/TypeBedWarsConfiguratorLoader.java @@ -60,7 +60,7 @@ private static void loadMapsConfig() { } /** - * Reloads the maps configuration from file + * Reloads the map configuration from the file */ public static void reloadMapsConfig() { if (gson == null) { diff --git a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/AutoSetupSession.java b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/AutoSetupSession.java index 93eb0cb38..e295e79cc 100644 --- a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/AutoSetupSession.java +++ b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/AutoSetupSession.java @@ -3,11 +3,24 @@ import lombok.Getter; import lombok.Setter; import net.minestom.server.instance.Instance; -import net.swofty.commons.bedwars.BedwarsGameType; +import net.swofty.commons.bedwars.BedWarsGameType; import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.*; - -import java.util.*; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.GeneratorSpeed; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapEntry; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MinMax; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TwoBlockPosition; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.commons.mc.Vec3i; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; @Getter @Setter @@ -19,19 +32,15 @@ public class AutoSetupSession { private String mapId; private String mapName; - private final List gameTypes = new ArrayList<>(); + private final List gameTypes = new ArrayList<>(); private Double minX, maxX, minY, maxY, minZ, maxZ; private final Map teams = new EnumMap<>(TeamKey.class); - private final List diamondGenerators = new ArrayList<>(); - private final List emeraldGenerators = new ArrayList<>(); + private final List diamondGenerators = new ArrayList<>(); + private final List emeraldGenerators = new ArrayList<>(); private GeneratorSpeed generatorSpeed = GeneratorSpeed.SLOW; - private int diamondAmount = 1; - private int diamondMax = 4; - private int emeraldAmount = 1; - private int emeraldMax = 2; - private PitchYawPosition waitingLocation; - private PitchYawPosition spectatorLocation; + private HypixelPosition waitingLocation; + private HypixelPosition spectatorLocation; public AutoSetupSession(UUID playerUuid, Instance instance) { this.playerUuid = playerUuid; @@ -79,7 +88,7 @@ public void setBoundsMax(double x, double y, double z) { } public TeamConfig getOrCreateTeam(TeamKey key) { - return teams.computeIfAbsent(key, k -> new TeamConfig()); + return teams.computeIfAbsent(key, _ -> new TeamConfig()); } public void clear() { @@ -91,14 +100,14 @@ public void clear() { diamondGenerators.clear(); emeraldGenerators.clear(); generatorSpeed = GeneratorSpeed.SLOW; - diamondAmount = 1; - diamondMax = 4; - emeraldAmount = 1; - emeraldMax = 2; waitingLocation = null; spectatorLocation = null; } + public void removeTeam(TeamKey key) { + teams.remove(key); + } + public void loadFromMapEntry(BedWarsMapsConfig.MapEntry entry) { clear(); @@ -163,29 +172,25 @@ public void loadFromMapEntry(BedWarsMapsConfig.MapEntry entry) { if (config.getLocations() != null) { var locations = config.getLocations(); if (locations.getWaiting() != null) { - Position w = locations.getWaiting(); - waitingLocation = new PitchYawPosition(w.x(), w.y(), w.z(), 0, 0); + HypixelPosition w = locations.getWaiting(); + waitingLocation = new HypixelPosition(w.x(), w.y(), w.z(), 0, 0); } if (locations.getSpectator() != null) { - Position s = locations.getSpectator(); - spectatorLocation = new PitchYawPosition(s.x(), s.y(), s.z(), 0, 0); + HypixelPosition s = locations.getSpectator(); + spectatorLocation = new HypixelPosition(s.x(), s.y(), s.z(), 0, 0); } } // Load global generators - if (config.getGlobal_generator() != null) { - var diamondGen = config.getGlobal_generator().get("diamond"); + if (config.getGlobalGenerator() != null) { + var diamondGen = config.getGlobalGenerator().get(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND); if (diamondGen != null) { - diamondAmount = diamondGen.getAmount(); - diamondMax = diamondGen.getMax(); if (diamondGen.getLocations() != null) { diamondGenerators.addAll(diamondGen.getLocations()); } } - var emeraldGen = config.getGlobal_generator().get("emerald"); + var emeraldGen = config.getGlobalGenerator().get(BedWarsMapsConfig.GlobalGeneratorKey.EMERALD); if (emeraldGen != null) { - emeraldAmount = emeraldGen.getAmount(); - emeraldMax = emeraldGen.getMax(); if (emeraldGen.getLocations() != null) { emeraldGenerators.addAll(emeraldGen.getLocations()); } @@ -239,33 +244,28 @@ public MapEntry toMapEntry() { // Locations MapEntry.MapConfiguration.MapLocations locations = new MapEntry.MapConfiguration.MapLocations(); if (waitingLocation != null) { - locations.setWaiting(new Position(waitingLocation.x(), waitingLocation.y(), waitingLocation.z())); + locations.setWaiting(new HypixelPosition(waitingLocation.x(), waitingLocation.y(), waitingLocation.z())); } if (spectatorLocation != null) { - locations.setSpectator(new Position(spectatorLocation.x(), spectatorLocation.y(), spectatorLocation.z())); + locations.setSpectator(new HypixelPosition(spectatorLocation.x(), spectatorLocation.y(), spectatorLocation.z())); } config.setLocations(locations); // Global generators - Map globalGenerators = new HashMap<>(); - + Map globalGenerators = new HashMap<>(); if (!diamondGenerators.isEmpty()) { MapEntry.MapConfiguration.GlobalGenerator diamondGen = new MapEntry.MapConfiguration.GlobalGenerator(); - diamondGen.setAmount(diamondAmount); - diamondGen.setMax(diamondMax); diamondGen.setLocations(new ArrayList<>(diamondGenerators)); - globalGenerators.put("diamond", diamondGen); + globalGenerators.put(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND, diamondGen); } if (!emeraldGenerators.isEmpty()) { MapEntry.MapConfiguration.GlobalGenerator emeraldGen = new MapEntry.MapConfiguration.GlobalGenerator(); - emeraldGen.setAmount(emeraldAmount); - emeraldGen.setMax(emeraldMax); emeraldGen.setLocations(new ArrayList<>(emeraldGenerators)); - globalGenerators.put("emerald", emeraldGen); + globalGenerators.put(BedWarsMapsConfig.GlobalGeneratorKey.EMERALD, emeraldGen); } - config.setGlobal_generator(globalGenerators); + config.setGlobalGenerator(globalGenerators); entry.setConfiguration(config); return entry; @@ -274,12 +274,12 @@ public MapEntry toMapEntry() { @Getter @Setter public static class TeamConfig { - private PitchYawPosition spawn; - private Position bedFeet; - private Position bedHead; - private Position generator; - private PitchYawPosition itemShop; - private PitchYawPosition teamShop; + private HypixelPosition spawn; + private Vec3i bedFeet; + private Vec3i bedHead; + private HypixelPosition generator; + private HypixelPosition itemShop; + private HypixelPosition teamShop; } } diff --git a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/DebugMarkerManager.java b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/DebugMarkerManager.java index 3f8a26486..1e5113b47 100644 --- a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/DebugMarkerManager.java +++ b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/DebugMarkerManager.java @@ -10,10 +10,14 @@ import net.minestom.server.instance.Instance; import net.minestom.server.item.Material; import net.minestom.server.timer.TaskSchedule; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.Position; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.commons.mc.HypixelPosition; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; public class DebugMarkerManager { @@ -31,15 +35,15 @@ public static void showMarkers(UUID playerUuid, AutoSetupSession session, Instan // Bed markers if (config.getBedFeet() != null) { - markers.add(createMarker(instance, config.getBedFeet(), teamColor + team.getName() + " Bed (Feet)", Material.RED_BED)); + markers.add(createMarker(instance, config.getBedFeet().asHypixelPosition(), teamColor + team.getName() + " Bed (Feet)", Material.RED_BED)); } if (config.getBedHead() != null) { - markers.add(createMarker(instance, config.getBedHead(), teamColor + team.getName() + " Bed (Head)", Material.RED_BED)); + markers.add(createMarker(instance, config.getBedHead().asHypixelPosition(), teamColor + team.getName() + " Bed (Head)", Material.RED_BED)); } // Spawn marker if (config.getSpawn() != null) { - Position pos = new Position(config.getSpawn().x(), config.getSpawn().y(), config.getSpawn().z()); + HypixelPosition pos = new HypixelPosition(config.getSpawn().x(), config.getSpawn().y(), config.getSpawn().z()); markers.add(createMarker(instance, pos, teamColor + team.getName() + " Spawn", Material.PLAYER_HEAD)); } @@ -50,43 +54,43 @@ public static void showMarkers(UUID playerUuid, AutoSetupSession session, Instan // Shop markers if (config.getItemShop() != null) { - Position pos = new Position(config.getItemShop().x(), config.getItemShop().y(), config.getItemShop().z()); + HypixelPosition pos = new HypixelPosition(config.getItemShop().x(), config.getItemShop().y(), config.getItemShop().z()); markers.add(createMarker(instance, pos, teamColor + team.getName() + " Item Shop", Material.EMERALD)); } if (config.getTeamShop() != null) { - Position pos = new Position(config.getTeamShop().x(), config.getTeamShop().y(), config.getTeamShop().z()); + HypixelPosition pos = new HypixelPosition(config.getTeamShop().x(), config.getTeamShop().y(), config.getTeamShop().z()); markers.add(createMarker(instance, pos, teamColor + team.getName() + " Team Shop", Material.NETHER_STAR)); } } // Diamond generators int diamondIndex = 1; - for (Position pos : session.getDiamondGenerators()) { + for (HypixelPosition pos : session.getDiamondGenerators()) { markers.add(createMarker(instance, pos, "§bDiamond Gen #" + diamondIndex++, Material.DIAMOND_BLOCK)); } // Emerald generators int emeraldIndex = 1; - for (Position pos : session.getEmeraldGenerators()) { + for (HypixelPosition pos : session.getEmeraldGenerators()) { markers.add(createMarker(instance, pos, "§aEmerald Gen #" + emeraldIndex++, Material.EMERALD_BLOCK)); } // Waiting location if (session.getWaitingLocation() != null) { - Position pos = new Position(session.getWaitingLocation().x(), session.getWaitingLocation().y(), session.getWaitingLocation().z()); + HypixelPosition pos = new HypixelPosition(session.getWaitingLocation().x(), session.getWaitingLocation().y(), session.getWaitingLocation().z()); markers.add(createMarker(instance, pos, "§eWaiting Spawn", Material.CLOCK)); } // Spectator location if (session.getSpectatorLocation() != null) { - Position pos = new Position(session.getSpectatorLocation().x(), session.getSpectatorLocation().y(), session.getSpectatorLocation().z()); + HypixelPosition pos = new HypixelPosition(session.getSpectatorLocation().x(), session.getSpectatorLocation().y(), session.getSpectatorLocation().z()); markers.add(createMarker(instance, pos, "§7Spectator Spawn", Material.ENDER_EYE)); } // Bounds markers (corners) if (session.hasBounds()) { - markers.add(createMarker(instance, new Position(session.getMinX(), session.getMinY(), session.getMinZ()), "§8Bounds Min", Material.BARRIER)); - markers.add(createMarker(instance, new Position(session.getMaxX(), session.getMaxY(), session.getMaxZ()), "§8Bounds Max", Material.BARRIER)); + markers.add(createMarker(instance, new HypixelPosition(session.getMinX(), session.getMinY(), session.getMinZ()), "§8Bounds Min", Material.BARRIER)); + markers.add(createMarker(instance, new HypixelPosition(session.getMaxX(), session.getMaxY(), session.getMaxZ()), "§8Bounds Max", Material.BARRIER)); } playerMarkers.put(playerUuid, markers); @@ -101,7 +105,7 @@ public static void hideMarkers(UUID playerUuid) { } } - private static Entity createMarker(Instance instance, Position pos, String label, Material headItem) { + private static Entity createMarker(Instance instance, HypixelPosition pos, String label, Material headItem) { Entity armorStand = new Entity(EntityType.ARMOR_STAND); ArmorStandMeta meta = (ArmorStandMeta) armorStand.getEntityMeta(); @@ -131,7 +135,7 @@ private static Entity createMarker(Instance instance, Position pos, String label } public static Entity createSingleMarker(Instance instance, double x, double y, double z, String label) { - return createMarker(instance, new Position(x, y, z), label, Material.ARMOR_STAND); + return createMarker(instance, new HypixelPosition(x, y, z), label, Material.ARMOR_STAND); } public static void refreshMarkers(UUID playerUuid, AutoSetupSession session, Instance instance) { diff --git a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/WorldScanner.java b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/WorldScanner.java index 9b6cda663..14ae6da81 100644 --- a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/WorldScanner.java +++ b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/autosetup/WorldScanner.java @@ -6,12 +6,17 @@ import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.PitchYawPosition; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.Position; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.commons.mc.Vec3i; import org.tinylog.Logger; -import java.util.*; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; public class WorldScanner { @@ -67,12 +72,12 @@ public ScanResult fullScan() { teamConfig.setBedFeet(bed.feet); teamConfig.setBedHead(bed.head); - Position spawn = findSpawnNearBed(bed); + HypixelPosition spawn = findSpawnNearBed(bed); if (spawn != null) { - teamConfig.setSpawn(new PitchYawPosition(spawn.x(), spawn.y(), spawn.z(), 0, calculateYawTowardsBed(spawn, bed))); + teamConfig.setSpawn(new HypixelPosition(spawn.x(), spawn.y(), spawn.z(), 0, calculateYawTowardsBed(spawn, bed))); } - Position generator = findTeamGenerator(bed, 20); + HypixelPosition generator = findTeamGenerator(bed, 20); if (generator != null) { teamConfig.setGenerator(generator); } @@ -84,13 +89,13 @@ public ScanResult fullScan() { } // Find diamond generators - List diamondGens = findGlobalGenerators(Block.DIAMOND_BLOCK); + List diamondGens = findGlobalGenerators(Block.DIAMOND_BLOCK); session.getDiamondGenerators().clear(); session.getDiamondGenerators().addAll(diamondGens); result.addMessage("Found " + diamondGens.size() + " diamond generators"); // Find emerald generators - List emeraldGens = findGlobalGenerators(Block.EMERALD_BLOCK); + List emeraldGens = findGlobalGenerators(Block.EMERALD_BLOCK); session.getEmeraldGenerators().clear(); session.getEmeraldGenerators().addAll(emeraldGens); result.addMessage("Found " + emeraldGens.size() + " emerald generators"); @@ -126,14 +131,14 @@ public List findBeds() { facing = "south"; // Default facing if not found } - // Calculate head position based on facing - Point headPos = calculateHeadPosition(x, y, z, facing); + // Calculate head HypixelPosition based on facing + Point headPos = calculateHeadHypixelPosition(x, y, z, facing); if (!processedHeads.contains(headPos)) { processedHeads.add(headPos); beds.add(new BedLocation( - new Position(x, y, z), - new Position(headPos.x(), headPos.y(), headPos.z()), + new Vec3i(x, y, z), + new Vec3i((int) headPos.x(), (int) headPos.y(), (int) headPos.z()), facing )); } @@ -146,7 +151,7 @@ public List findBeds() { return beds; } - private Point calculateHeadPosition(int footX, int footY, int footZ, String facing) { + private Point calculateHeadHypixelPosition(int footX, int footY, int footZ, String facing) { return switch (facing) { case "north" -> Pos.ZERO.add(footX, footY, footZ - 1); case "south" -> Pos.ZERO.add(footX, footY, footZ + 1); @@ -199,7 +204,7 @@ private TeamKey getTeamFromWoolBlock(Block block) { } // suitable area around the bed for placeholder - private Position findSpawnNearBed(BedLocation bed) { + private HypixelPosition findSpawnNearBed(BedLocation bed) { int[][] offsets = {{0, 0, 2}, {0, 0, -2}, {2, 0, 0}, {-2, 0, 0}, {0, 0, 3}, {0, 0, -3}, {3, 0, 0}, {-3, 0, 0}}; @@ -217,20 +222,20 @@ private Position findSpawnNearBed(BedLocation bed) { Block head = instance.getBlock(x, y + 1, z); if (ground.isSolid() && feet.isAir() && head.isAir()) { - return new Position(x + 0.5, y, z + 0.5); + return new HypixelPosition(x + 0.5, y, z + 0.5); } } - return new Position(bed.feet.x() + 0.5, bed.feet.y(), bed.feet.z() + 2.5); + return new HypixelPosition(bed.feet.x() + 0.5, bed.feet.y(), bed.feet.z() + 2.5); } - private float calculateYawTowardsBed(Position spawn, BedLocation bed) { + private float calculateYawTowardsBed(HypixelPosition spawn, BedLocation bed) { double dx = bed.feet.x() - spawn.x(); double dz = bed.feet.z() - spawn.z(); return (float) (Math.toDegrees(Math.atan2(-dx, dz))); } - private Position findTeamGenerator(BedLocation bed, int radius) { + private HypixelPosition findTeamGenerator(BedLocation bed, int radius) { int centerX = (int) bed.feet.x(); int centerY = (int) bed.feet.y(); int centerZ = (int) bed.feet.z(); @@ -239,7 +244,7 @@ private Position findTeamGenerator(BedLocation bed, int radius) { for (int y = centerY - 5; y <= centerY + 5; y++) { for (int z = centerZ - radius; z <= centerZ + radius; z++) { if (isSlabPlatform(x, y, z)) { - return new Position(x + 1.5, y + 0.5, z + 0.5); + return new HypixelPosition(x + 1.5, y + 0.5, z + 0.5); } } } @@ -277,8 +282,8 @@ private boolean isSlabBlock(Block block) { return block.name().contains("slab"); } - public List findGlobalGenerators(Block centerBlock) { - List generators = new ArrayList<>(); + public List findGlobalGenerators(Block centerBlock) { + List generators = new ArrayList<>(); // Normalize bounds to handle cases where min > max int minX = Math.min(session.getMinX().intValue(), session.getMaxX().intValue()); @@ -295,7 +300,7 @@ public List findGlobalGenerators(Block centerBlock) { if (block.compare(centerBlock)) { if (hasStairPattern(x, y, z)) { - generators.add(new Position(x + 0.5, y + 1, z + 0.5)); + generators.add(new HypixelPosition(x + 0.5, y + 1, z + 0.5)); } } } @@ -324,7 +329,7 @@ private boolean hasStairPattern(int centerX, int centerY, int centerZ) { return stairCount >= 4; // At least 4 stairs (corners or sides) } - public record BedLocation(Position feet, Position head, String facing) { + public record BedLocation(Vec3i feet, Vec3i head, String facing) { } @Getter diff --git a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/AutoSetupCommand.java b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/AutoSetupCommand.java index 482bf5d8d..10fe86b6b 100644 --- a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/AutoSetupCommand.java +++ b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/AutoSetupCommand.java @@ -3,25 +3,32 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import net.kyori.adventure.text.Component; +import net.minestom.server.command.CommandSender; import net.minestom.server.command.builder.arguments.ArgumentString; import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.arguments.number.ArgumentDouble; import net.minestom.server.command.builder.suggestion.SuggestionEntry; +import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.Player; import net.minestom.server.instance.Instance; -import net.swofty.commons.bedwars.BedwarsGameType; +import net.minestom.server.instance.block.Block; +import net.swofty.commons.Tuple; +import net.swofty.commons.bedwars.BedWarsGameType; import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.GeneratorSpeed; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.PitchYawPosition; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.Position; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.commons.mc.Vec3i; import net.swofty.type.bedwarsconfigurator.TypeBedWarsConfiguratorLoader; import net.swofty.type.bedwarsconfigurator.autosetup.AutoSetupSession; import net.swofty.type.bedwarsconfigurator.autosetup.DebugMarkerManager; import net.swofty.type.bedwarsconfigurator.autosetup.WorldScanner; import net.swofty.type.generic.command.CommandParameters; import net.swofty.type.generic.command.HypixelCommand; +import net.swofty.type.generic.raycast.Ray; +import net.swofty.type.generic.raycast.RayBlockFinder; +import net.swofty.type.generic.raycast.RayIntersection; import net.swofty.type.generic.user.categories.Rank; import org.tinylog.Logger; @@ -30,22 +37,19 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Optional; +import java.util.Set; -@CommandParameters( - aliases = "setup mapsetup", - description = "Automatic BedWars map configuration tool", - usage = "/autosetup ", - permission = Rank.STAFF, - allowsConsole = false -) +@CommandParameters(aliases = "setup mapsetup", description = "Automatic BedWars map configuration tool", usage = "/autosetup ", permission = Rank.STAFF, allowsConsole = false) public class AutoSetupCommand extends HypixelCommand { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); @Override public void registerUsage(MinestomCommand command) { - command.setDefaultExecutor((sender, context) -> { + command.setDefaultExecutor((sender, _) -> { sendHelp(sender); }); @@ -63,7 +67,7 @@ public void registerUsage(MinestomCommand command) { registerMapInfoCommand(command); } - private void sendHelp(net.minestom.server.command.CommandSender sender) { + private void sendHelp(CommandSender sender) { sender.sendMessage(Component.text("§6§l=== BedWars Auto Setup ===")); sender.sendMessage(Component.text("§e/autosetup scan §7- Scan world for beds, generators, etc.")); sender.sendMessage(Component.text("§e/autosetup bounds [x y z] §7- Set map bounds")); @@ -76,12 +80,12 @@ private void sendHelp(net.minestom.server.command.CommandSender sender) { sender.sendMessage(Component.text("§e/autosetup hide §7- Hide debug markers")); sender.sendMessage(Component.text("§e/autosetup status §7- Show current configuration status")); sender.sendMessage(Component.text("§e/autosetup name §7- Set map display name")); - sender.sendMessage(Component.text("§e/autosetup generator §7- Configure generator settings")); + sender.sendMessage(Component.text("§e/autosetup generator §7- Configure generator speed")); sender.sendMessage(Component.text("§e/autosetup save §7- Save configuration to maps.json")); } private void registerScanCommand(MinestomCommand command) { - command.addSyntax((sender, context) -> { + command.addSyntax((sender, _) -> { if (!(sender instanceof Player player)) return; if (!permissionCheck(sender)) return; @@ -126,7 +130,7 @@ private void registerScanCommand(MinestomCommand command) { private void registerBoundsCommand(MinestomCommand command) { var cornerArg = ArgumentType.String("corner"); - cornerArg.setSuggestionCallback((sender, ctx, suggestion) -> { + cornerArg.setSuggestionCallback((_, _, suggestion) -> { suggestion.addEntry(new SuggestionEntry("min")); suggestion.addEntry(new SuggestionEntry("max")); }); @@ -180,7 +184,6 @@ private void registerBoundsCommand(MinestomCommand command) { } DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); - }, ArgumentType.Literal("bounds"), cornerArg, xArg, yArg, zArg); } @@ -193,7 +196,7 @@ private void registerTypeCommand(MinestomCommand command) { var typeArg = ArgumentType.String("typeName"); typeArg.setSuggestionCallback((sender, ctx, suggestion) -> { - for (BedwarsGameType type : BedwarsGameType.values()) { + for (BedWarsGameType type : BedWarsGameType.values()) { suggestion.addEntry(new SuggestionEntry(type.name())); } }); @@ -205,7 +208,7 @@ private void registerTypeCommand(MinestomCommand command) { String action = context.get(actionArg); String typeName = context.get(typeArg); - BedwarsGameType gameType = BedwarsGameType.from(typeName); + BedWarsGameType gameType = BedWarsGameType.from(typeName); if (gameType == null) { player.sendMessage(Component.text("§cInvalid game type: " + typeName)); return; @@ -227,25 +230,47 @@ private void registerTypeCommand(MinestomCommand command) { player.sendMessage(Component.text("§eGame type not in list: " + gameType.getDisplayName())); } } - }, ArgumentType.Literal("type"), actionArg, typeArg); } private void registerTeamCommand(MinestomCommand command) { var teamArg = ArgumentType.String("teamName"); teamArg.setSuggestionCallback((sender, ctx, suggestion) -> { + Set entries = new HashSet<>(); for (TeamKey team : TeamKey.values()) { - suggestion.addEntry(new SuggestionEntry(team.name())); + entries.add(new SuggestionEntry(team.name())); + } + + String input = ctx.getInput(); + String currentInput = input.substring(input.lastIndexOf(" ") + 1).trim().toLowerCase(); + + if (currentInput.isEmpty()) { + entries.forEach(suggestion::addEntry); + return; } + + entries.stream().filter(entry -> entry.getEntry().toLowerCase().startsWith(currentInput)).forEach(suggestion::addEntry); }); var propertyArg = ArgumentType.String("property"); - propertyArg.setSuggestionCallback((sender, ctx, suggestion) -> { - suggestion.addEntry(new SuggestionEntry("spawn")); - suggestion.addEntry(new SuggestionEntry("bed")); - suggestion.addEntry(new SuggestionEntry("generator")); - suggestion.addEntry(new SuggestionEntry("itemshop")); - suggestion.addEntry(new SuggestionEntry("teamshop")); + propertyArg.setSuggestionCallback((_, ctx, suggestion) -> { + Set entries = new HashSet<>(); + entries.add(new SuggestionEntry("spawn")); + entries.add(new SuggestionEntry("bed")); + entries.add(new SuggestionEntry("generator")); + entries.add(new SuggestionEntry("itemshop")); + entries.add(new SuggestionEntry("teamshop")); + entries.add(new SuggestionEntry("remove")); + + String input = ctx.getInput(); + String currentInput = input.substring(input.lastIndexOf(" ") + 1).trim().toLowerCase(); + + if (currentInput.isEmpty()) { + entries.forEach(suggestion::addEntry); + return; + } + + entries.stream().filter(entry -> entry.getEntry().toLowerCase().startsWith(currentInput)).forEach(suggestion::addEntry); }); // /autosetup team - use player position @@ -268,9 +293,8 @@ private void registerTeamCommand(MinestomCommand command) { AutoSetupSession.TeamConfig teamConfig = session.getOrCreateTeam(teamKey); Pos pos = player.getPosition(); - setTeamProperty(player, teamConfig, property, pos); + setTeamProperty(player, teamKey, teamConfig, property, pos); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); - }, ArgumentType.Literal("team"), teamArg, propertyArg); // /autosetup team @@ -300,58 +324,104 @@ private void registerTeamCommand(MinestomCommand command) { AutoSetupSession.TeamConfig teamConfig = session.getOrCreateTeam(teamKey); Pos pos = new Pos(x, y, z, player.getPosition().yaw(), player.getPosition().pitch()); - setTeamProperty(player, teamConfig, property, pos); + setTeamProperty(player, teamKey, teamConfig, property, pos); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); }, ArgumentType.Literal("team"), teamArg, propertyArg, xArg, yArg, zArg); } - private void setTeamProperty(Player player, AutoSetupSession.TeamConfig teamConfig, String property, Pos pos) { + private void setTeamProperty(Player player, TeamKey key, AutoSetupSession.TeamConfig teamConfig, String property, Pos pos) { + final HypixelPosition currentPosition = new HypixelPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw()); switch (property.toLowerCase()) { case "spawn" -> { - teamConfig.setSpawn(new PitchYawPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw())); + teamConfig.setSpawn(currentPosition); player.sendMessage(Component.text("§aSet team spawn to " + formatPos(pos))); } case "bed" -> { - // For bed, we need both feet and head. Use player facing direction - Position feet = new Position(pos.blockX(), pos.blockY(), pos.blockZ()); - Position head = calculateBedHead(pos); - teamConfig.setBedFeet(feet); - teamConfig.setBedHead(head); - player.sendMessage(Component.text("§aSet team bed (feet: " + formatPosition(feet) + ", head: " + formatPosition(head) + ")")); + Optional> positions = calculateBedHead(player); + positions.ifPresentOrElse(position -> { + Vec3i head = position.getKey(); + Vec3i feet = position.getValue(); + + teamConfig.setBedFeet(feet); + teamConfig.setBedHead(head); + player.sendMessage(Component.text("§aSet team bed (feet: " + formatPosition(feet) + ", head: " + formatPosition(head) + ")")); + }, () -> player.sendMessage(Component.text("§cYou must be looking at a bed block to set the bed position."))); } case "generator" -> { - teamConfig.setGenerator(new Position(pos.x(), pos.y(), pos.z())); + teamConfig.setGenerator(new HypixelPosition(pos.x(), pos.y(), pos.z())); player.sendMessage(Component.text("§aSet team generator to " + formatPos(pos))); } case "itemshop" -> { - teamConfig.setItemShop(new PitchYawPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw())); + teamConfig.setItemShop(currentPosition); player.sendMessage(Component.text("§aSet item shop to " + formatPos(pos))); } case "teamshop" -> { - teamConfig.setTeamShop(new PitchYawPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw())); + teamConfig.setTeamShop(currentPosition); player.sendMessage(Component.text("§aSet team shop to " + formatPos(pos))); } + case "remove" -> { + AutoSetupSession.get(player.getUuid()).removeTeam(key); + player.sendMessage(Component.text("§cRemoved all properties for team")); + } default -> player.sendMessage(Component.text("§cUnknown property: " + property)); } } - private Position calculateBedHead(Pos playerPos) { - // Calculate head position based on player yaw (where they're looking) - float yaw = playerPos.yaw(); - int dx = 0, dz = 0; - - if (yaw >= -45 && yaw < 45) { // South - dz = 1; - } else if (yaw >= 45 && yaw < 135) { // West - dx = -1; - } else if (yaw >= 135 || yaw < -135) { // North - dz = -1; - } else { // East - dx = 1; + private Optional> calculateBedHead(Player player) { + Pos start = player.getPosition(); + + Ray ray = new Ray(start, start.direction().mul(5)); + + RayBlockFinder finder = ray.findBlocks(player.getInstance()); + + RayIntersection hit = null; + while (finder.hasNext()) { + RayIntersection result = finder.nextClosest(); + if (result == null) break; + + Block block = result.object(); + if (block.key().value().endsWith("_bed")) { + hit = result; + break; + } + } + + if (hit == null) return Optional.empty(); + + Block bedBlock = hit.object(); + Point hitPoint = hit.point(); + + Vec3i hitPos = new Vec3i(hitPoint.blockX(), hitPoint.blockY(), hitPoint.blockZ()); + + String part = bedBlock.getProperty("part"); + String facing = bedBlock.getProperty("facing"); + + if (part == null || facing == null) { + Logger.warn("Hit bed block missing 'part' or 'facing'"); + return Optional.empty(); + } + + Vec3i offset = switch (facing) { + case "north" -> new Vec3i(0, 0, -1); + case "south" -> new Vec3i(0, 0, 1); + case "west" -> new Vec3i(-1, 0, 0); + case "east" -> new Vec3i(1, 0, 0); + default -> Vec3i.ZERO; + }; + + Vec3i headPos; + Vec3i footPos; + + if ("head".equals(part)) { + headPos = hitPos; + footPos = headPos.sub(offset); + } else { + footPos = hitPos; + headPos = hitPos.add(offset); } - return new Position(playerPos.blockX() + dx, playerPos.blockY(), playerPos.blockZ() + dz); + return Optional.of(new Tuple<>(headPos, footPos)); } private void registerGlobalCommand(MinestomCommand command) { @@ -378,9 +448,7 @@ private void registerGlobalCommand(MinestomCommand command) { Pos pos = player.getPosition(); AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), player.getInstance()); - List generators = genType.equalsIgnoreCase("diamond") - ? session.getDiamondGenerators() - : session.getEmeraldGenerators(); + List generators = genType.equalsIgnoreCase("diamond") ? session.getDiamondGenerators() : session.getEmeraldGenerators(); handleGlobalGeneratorAction(player, generators, action, pos, genType); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); @@ -403,9 +471,7 @@ private void registerGlobalCommand(MinestomCommand command) { double z = context.get(zArg); AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), player.getInstance()); - List generators = genType.equalsIgnoreCase("diamond") - ? session.getDiamondGenerators() - : session.getEmeraldGenerators(); + List generators = genType.equalsIgnoreCase("diamond") ? session.getDiamondGenerators() : session.getEmeraldGenerators(); handleGlobalGeneratorAction(player, generators, action, new Pos(x, y, z), genType); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); @@ -413,19 +479,19 @@ private void registerGlobalCommand(MinestomCommand command) { }, ArgumentType.Literal("global"), genTypeArg, actionArg, xArg, yArg, zArg); } - private void handleGlobalGeneratorAction(Player player, List generators, String action, Pos pos, String genType) { + private void handleGlobalGeneratorAction(Player player, List generators, String action, Pos pos, String genType) { switch (action.toLowerCase()) { case "add" -> { - Position newPos = new Position(pos.x(), pos.y(), pos.z()); + HypixelPosition newPos = new HypixelPosition(pos.x(), pos.y(), pos.z()); generators.add(newPos); player.sendMessage(Component.text("§aAdded " + genType + " generator at " + formatPos(pos) + " (Total: " + generators.size() + ")")); } case "remove" -> { // Remove nearest generator within 2 blocks - Position toRemove = null; + HypixelPosition toRemove = null; double minDist = Double.MAX_VALUE; - for (Position gen : generators) { + for (HypixelPosition gen : generators) { double dist = Math.sqrt(Math.pow(gen.x() - pos.x(), 2) + Math.pow(gen.y() - pos.y(), 2) + Math.pow(gen.z() - pos.z(), 2)); if (dist < minDist && dist < 2) { minDist = dist; @@ -457,7 +523,7 @@ private void registerLocationCommand(MinestomCommand command) { Pos pos = player.getPosition(); AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), player.getInstance()); - session.setWaitingLocation(new PitchYawPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw())); + session.setWaitingLocation(new HypixelPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw())); player.sendMessage(Component.text("§aSet waiting spawn to " + formatPos(pos))); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); @@ -469,7 +535,7 @@ private void registerLocationCommand(MinestomCommand command) { Pos pos = player.getPosition(); AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), player.getInstance()); - session.setSpectatorLocation(new PitchYawPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw())); + session.setSpectatorLocation(new HypixelPosition(pos.x(), pos.y(), pos.z(), pos.pitch(), pos.yaw())); player.sendMessage(Component.text("§aSet spectator spawn to " + formatPos(pos))); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); @@ -489,7 +555,7 @@ private void registerLocationCommand(MinestomCommand command) { double z = context.get(zArg); AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), player.getInstance()); - session.setWaitingLocation(new PitchYawPosition(x, y, z, 0, 0)); + session.setWaitingLocation(new HypixelPosition(x, y, z, 0, 0)); player.sendMessage(Component.text("§aSet waiting spawn to " + x + ", " + y + ", " + z)); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); @@ -504,7 +570,7 @@ private void registerLocationCommand(MinestomCommand command) { double z = context.get(zArg); AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), player.getInstance()); - session.setSpectatorLocation(new PitchYawPosition(x, y, z, 0, 0)); + session.setSpectatorLocation(new HypixelPosition(x, y, z, 0, 0)); player.sendMessage(Component.text("§aSet spectator spawn to " + x + ", " + y + ", " + z)); DebugMarkerManager.refreshMarkers(player.getUuid(), session, player.getInstance()); @@ -618,54 +684,12 @@ private void registerGeneratorSettingsCommand(MinestomCommand command) { try { GeneratorSpeed speed = GeneratorSpeed.valueOf(speedStr.toUpperCase()); session.setGeneratorSpeed(speed); - player.sendMessage(Component.text("§aSet generator speed to " + speed.name() + - " (" + speed.getIronAmount() + " iron/" + speed.getIronDelaySeconds() + "s, " + - speed.getGoldAmount() + " gold/" + speed.getGoldDelaySeconds() + "s)")); + player.sendMessage(Component.text("§aSet generator speed to " + speed.name() + " (" + speed.getIronAmount() + " iron/" + speed.getIronDelaySeconds() + "s, " + speed.getGoldAmount() + " gold/" + speed.getGoldDelaySeconds() + "s)")); } catch (IllegalArgumentException e) { player.sendMessage(Component.text("§cInvalid speed: " + speedStr)); } }, ArgumentType.Literal("generator"), ArgumentType.Literal("speed"), speedArg); - - // Diamond/Emerald settings (unchanged) - var genTypeArg = ArgumentType.String("gentype"); - genTypeArg.setSuggestionCallback((sender, ctx, suggestion) -> { - suggestion.addEntry(new SuggestionEntry("diamond")); - suggestion.addEntry(new SuggestionEntry("emerald")); - }); - - var settingArg = ArgumentType.String("setting"); - settingArg.setSuggestionCallback((sender, ctx, suggestion) -> { - suggestion.addEntry(new SuggestionEntry("amount")); - suggestion.addEntry(new SuggestionEntry("max")); - }); - - ArgumentDouble valueArg = ArgumentType.Double("value"); - - command.addSyntax((sender, context) -> { - if (!(sender instanceof Player player)) return; - if (!permissionCheck(sender)) return; - - String genType = context.get(genTypeArg); - String setting = context.get(settingArg); - int value = context.get(valueArg).intValue(); - - AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), player.getInstance()); - - switch (genType.toLowerCase()) { - case "diamond" -> { - if (setting.equals("amount")) session.setDiamondAmount(value); - else if (setting.equals("max")) session.setDiamondMax(value); - } - case "emerald" -> { - if (setting.equals("amount")) session.setEmeraldAmount(value); - else if (setting.equals("max")) session.setEmeraldMax(value); - } - } - - player.sendMessage(Component.text("§aSet " + genType + " " + setting + " to " + value)); - - }, ArgumentType.Literal("generator"), genTypeArg, settingArg, valueArg); } private void registerSaveCommand(MinestomCommand command) { @@ -773,8 +797,8 @@ private String formatPos(Pos pos) { return String.format("%.2f, %.2f, %.2f", pos.x(), pos.y(), pos.z()); } - private String formatPosition(Position pos) { - return String.format("%.2f, %.2f, %.2f", pos.x(), pos.y(), pos.z()); + private String formatPosition(Vec3i pos) { + return String.format("%d, %d, %d", pos.x(), pos.y(), pos.z()); } } diff --git a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/ChooseMapCommand.java b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/ChooseMapCommand.java index 09b76829a..1c1d97c1a 100644 --- a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/ChooseMapCommand.java +++ b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/commands/ChooseMapCommand.java @@ -5,11 +5,12 @@ import net.minestom.server.MinecraftServer; import net.minestom.server.command.builder.arguments.ArgumentType; import net.minestom.server.command.builder.suggestion.SuggestionEntry; +import net.minestom.server.entity.GameMode; import net.minestom.server.entity.Player; import net.minestom.server.instance.InstanceContainer; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.type.bedwarsconfigurator.TypeBedWarsConfiguratorLoader; import net.swofty.type.bedwarsconfigurator.autosetup.AutoSetupSession; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.type.generic.command.CommandParameters; import net.swofty.type.generic.command.HypixelCommand; import net.swofty.type.generic.user.categories.Rank; @@ -20,88 +21,104 @@ import java.util.Set; @CommandParameters(aliases = "choose choosemap selectmap select", - description = "Choose a BedWars map to configure", - usage = "/choosemap ", - permission = Rank.STAFF, - allowsConsole = false) + description = "Choose a BedWars map to configure", + usage = "/choosemap ", + permission = Rank.STAFF, + allowsConsole = false) public class ChooseMapCommand extends HypixelCommand { - @Override - public void registerUsage(MinestomCommand command) { - var mapArg = ArgumentType.String("map"); - mapArg.setSuggestionCallback((sender, context, suggestion) -> { - Set addedIds = new HashSet<>(); - for (BedWarsMapsConfig.MapEntry entry : TypeBedWarsConfiguratorLoader.getMapsConfig().getMaps()) { - suggestion.addEntry(new SuggestionEntry(entry.getId(), Component.text(entry.getName() + " §7(configured)"))); - addedIds.add(entry.getId().toLowerCase()); - } - - File bedwarsDir = new File("./configuration/bedwars/"); - if (bedwarsDir.exists() && bedwarsDir.isDirectory()) { - File[] polarFiles = bedwarsDir.listFiles((dir, name) -> name.endsWith(".polar")); - if (polarFiles != null) { - for (File polarFile : polarFiles) { - String mapId = polarFile.getName().replace(".polar", ""); - if (!addedIds.contains(mapId.toLowerCase())) { - suggestion.addEntry(new SuggestionEntry(mapId, Component.text(mapId + " §e(unconfigured)"))); - } - } - } - } - }); - - command.addSyntax((sender, context) -> { - if (!(sender instanceof Player player)) { - sender.sendMessage(Component.text("§cThis command can only be executed by a player.")); - return; - } - String mapId = context.get("map"); - - BedWarsMapsConfig.MapEntry selectedMap = null; - for (BedWarsMapsConfig.MapEntry entry : TypeBedWarsConfiguratorLoader.getMapsConfig().getMaps()) { - if (entry.getId().equalsIgnoreCase(mapId)) { - selectedMap = entry; - break; - } - } - - File polarFile = new File("./configuration/bedwars/" + mapId + ".polar"); - if (!polarFile.exists()) { - sender.sendMessage(Component.text("§cNo polar file found for map: " + mapId)); - return; - } - - InstanceContainer mapInstance = MinecraftServer.getInstanceManager().createInstanceContainer(); - try { - mapInstance.setChunkLoader(new PolarLoader(polarFile.toPath())); - } catch (IOException e) { - sender.sendMessage(Component.text("§cFailed to load map: " + mapId)); - return; - } - - AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), mapInstance); - session.setMapId(mapId); - - if (selectedMap != null) { - session.setMapName(selectedMap.getName()); - - if (selectedMap.getConfiguration() != null) { - session.loadFromMapEntry(selectedMap); - sender.sendMessage(Component.text("§aLoaded existing configuration for: " + selectedMap.getName())); - } else { - sender.sendMessage(Component.text("§eSelected map: " + selectedMap.getName() + " §7(no existing config)")); - } - } else { - session.setMapName(mapId); - session.clear(); - session.setMapId(mapId); - session.setMapName(mapId); - sender.sendMessage(Component.text("§eLoaded unconfigured map: §f" + mapId + " §7(starting fresh)")); - sender.sendMessage(Component.text("§7Use §b/autosetup §7to automatically configure the map, or set things manually.")); - } - - player.setInstance(mapInstance); - }, mapArg); - } + @Override + public void registerUsage(MinestomCommand command) { + var mapArg = ArgumentType.String("map"); + mapArg.setSuggestionCallback((sender, context, suggestion) -> { + Set addedIds = new HashSet<>(); + Set suggestions = new HashSet<>(); + + for (BedWarsMapsConfig.MapEntry entry : TypeBedWarsConfiguratorLoader.getMapsConfig().getMaps()) { + suggestions.add(new SuggestionEntry(entry.getId(), Component.text(entry.getName() + " §7(configured)"))); + addedIds.add(entry.getId().toLowerCase()); + } + + File bedwarsDir = new File("./configuration/bedwars/"); + if (bedwarsDir.exists() && bedwarsDir.isDirectory()) { + File[] polarFiles = bedwarsDir.listFiles((_, name) -> name.endsWith(".polar")); + if (polarFiles != null) { + for (File polarFile : polarFiles) { + String mapId = polarFile.getName().replace(".polar", ""); + if (!addedIds.contains(mapId.toLowerCase())) { + suggestions.add(new SuggestionEntry(mapId, Component.text(mapId + " §e(unconfigured)"))); + } + } + } + } + + String input = context.getInput(); + String currentInput = input.substring(input.lastIndexOf(" ") + 1).trim().toLowerCase(); + + if (currentInput.isEmpty()) { + suggestions.forEach(suggestion::addEntry); + return; + } + + suggestions.stream() + .filter(entry -> entry.getEntry().toLowerCase().startsWith(currentInput)) + .forEach(suggestion::addEntry); + }); + + command.addSyntax((sender, context) -> { + if (!(sender instanceof Player player)) { + sender.sendMessage(Component.text("§cThis command can only be executed by a player.")); + return; + } + String mapId = context.get("map"); + + BedWarsMapsConfig.MapEntry selectedMap = null; + for (BedWarsMapsConfig.MapEntry entry : TypeBedWarsConfiguratorLoader.getMapsConfig().getMaps()) { + if (entry.getId().equalsIgnoreCase(mapId)) { + selectedMap = entry; + break; + } + } + + File polarFile = new File("./configuration/bedwars/" + mapId + ".polar"); + if (!polarFile.exists()) { + sender.sendMessage(Component.text("§cNo polar file found for map: " + mapId)); + return; + } + + InstanceContainer mapInstance = MinecraftServer.getInstanceManager().createInstanceContainer(); + try { + mapInstance.setChunkLoader(new PolarLoader(polarFile.toPath())); + } catch (IOException e) { + sender.sendMessage(Component.text("§cFailed to load map: " + mapId)); + return; + } + + AutoSetupSession session = AutoSetupSession.getOrCreate(player.getUuid(), mapInstance); + session.setMapId(mapId); + + if (selectedMap != null) { + session.setMapName(selectedMap.getName()); + + if (selectedMap.getConfiguration() != null) { + session.loadFromMapEntry(selectedMap); + player.sendMessage(Component.text("§aLoaded existing configuration for: " + selectedMap.getName())); + } else { + player.sendMessage(Component.text("§eSelected map: " + selectedMap.getName() + " §7(no existing config)")); + } + } else { + player.setGameMode(GameMode.CREATIVE); + player.setFlying(true); + session.setMapName(mapId); + session.clear(); + session.setMapId(mapId); + session.setMapName(mapId); + player.sendMessage(Component.text("§eLoaded unconfigured map: §f" + mapId + " §7(starting fresh)")); + player.sendMessage(Component.text("§7Use §b/autosetup §7to automatically configure the map, or set things manually.")); + } + + player.setInstance(mapInstance); + }, mapArg); + } } diff --git a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/events/ActionPlayerJoin.java b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/events/ActionPlayerJoin.java index 9b316ab7c..20702bc41 100644 --- a/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/events/ActionPlayerJoin.java +++ b/type.bedwarsconfigurator/src/main/java/net/swofty/type/bedwarsconfigurator/events/ActionPlayerJoin.java @@ -17,7 +17,7 @@ public void run(AsyncPlayerConfigurationEvent event) { final HypixelPlayer player = (HypixelPlayer) event.getPlayer(); event.setSpawningInstance(HypixelConst.getEmptyInstance()); - Logger.info("Player " + player.getUsername() + " joined the server from origin server " + player.getOriginServer()); + Logger.info("Player " + player.getUsername() + " joined the server from start server " + player.getOriginServer()); player.setRespawnPoint(HypixelConst.getTypeLoader() .getLoaderValues() .spawnPosition() diff --git a/type.bedwarsgame/build.gradle.kts b/type.bedwarsgame/build.gradle.kts index 6b997f9e2..7ed348025 100644 --- a/type.bedwarsgame/build.gradle.kts +++ b/type.bedwarsgame/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(project(":commons")) implementation(project(":proxy.api")) implementation(project(":pvp")) + implementation(project(":type.game")) implementation(libs.mongodb.bson) implementation(libs.adventure.text.minimessage) implementation(libs.polar) diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java index 29f9b93d4..61cb22169 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameScoreboard.java @@ -1,14 +1,18 @@ package net.swofty.type.bedwarsgame; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.tag.resolver.Formatter; +import net.kyori.adventure.text.minimessage.translation.Argument; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.timer.Scheduler; import net.minestom.server.timer.TaskSchedule; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.commons.VersionConst; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGameEventManager; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.HypixelConst; import net.swofty.type.generic.data.HypixelDataHandler; import net.swofty.type.generic.data.handlers.BedWarsDataHandler; @@ -16,117 +20,143 @@ import net.swofty.type.generic.scoreboard.HypixelScoreboard; import net.swofty.type.generic.user.HypixelPlayer; -import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.ArrayList; -import java.util.Date; import java.util.List; -import java.util.Locale; -import java.util.Map; public class BedWarsGameScoreboard { - private static final HypixelScoreboard scoreboard = new HypixelScoreboard(); - private static Integer prototypeName = 0; - - public static void start(Game game) { - Scheduler scheduler = MinecraftServer.getSchedulerManager(); - scheduler.submitTask(() -> { - if (game == null) { - return TaskSchedule.stop(); - } - - prototypeName++; - if (prototypeName > 50) { - prototypeName = 0; - } - - for (HypixelPlayer player : game.getPlayers()) { - if (player.joined - System.currentTimeMillis() > 5000) { - continue; - } - Locale l = player.getLocale(); - HypixelDataHandler dataHandler = player.getDataHandler(); - BedWarsDataHandler bwDataHandler = BedWarsDataHandler.getUser(player); - - if (dataHandler == null || bwDataHandler == null) { - continue; - } - - String date = new SimpleDateFormat(I18n.string("scoreboard.common.date_format", l)).format(new Date()); - - List lines = new ArrayList<>(); - lines.add(I18n.t("scoreboard.common.date_line", Component.text(date), Component.text(HypixelConst.getServerName()))); - lines.add(Component.text("§7 ")); - - if (game.getGameStatus() == GameStatus.WAITING) { - lines.add(I18n.t("scoreboard.bedwars_game.map_line", Component.text(game.getMapEntry().getName()))); - lines.add(I18n.t("scoreboard.bedwars_game.players_line", - Component.text(String.valueOf(game.getPlayers().size())), - Component.text(String.valueOf(game.getMapEntry().getConfiguration().getTeams().size())))); - lines.add(Component.text("§7 ")); - lines.add(I18n.t("scoreboard.bedwars_game.starting_in_line", - Component.text(String.valueOf(game.getCountdown().getRemainingSeconds())))); - lines.add(Component.text("§7 ")); - lines.add(I18n.t("scoreboard.bedwars_game.mode_line", Component.text(game.getBedwarsGameType().getDisplayName()))); - lines.add(I18n.t("scoreboard.bedwars_game.version_label")); - } else { - String eventName = game.getEventManager().getNextEvent() != null - ? game.getEventManager().getNextEvent().getDisplayName() - : game.getEventManager().getCurrentEvent().getDisplayName(); - long seconds = game.getEventManager().getSecondsUntilNextEvent(); - long minutesPart = seconds / 60; - long secondsPart = seconds % 60; - String timeLeft = String.format("%d:%02d", minutesPart, secondsPart); - lines.add(I18n.t("scoreboard.bedwars_game.event_in_line", - Component.text(eventName), - Component.text(timeLeft))); - lines.add(Component.text("§7 ")); - for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { - TeamKey teamKey = entry.getKey(); - String teamName = teamKey.getName(); - String teamInitial = teamName.substring(0, 1).toUpperCase(); - - Component bedStatus = game.getTeamManager().isBedAlive(teamKey) - ? I18n.t("scoreboard.bedwars_game.bed_alive") - : I18n.t("scoreboard.bedwars_game.bed_dead"); - lines.add(I18n.t("scoreboard.bedwars_game.team_status_line", - Component.text(teamKey.chatColor() + teamInitial), - Component.text(teamName), - bedStatus)); - } - } - lines.add(Component.text("§7 ")); - lines.add(I18n.t("scoreboard.common.footer")); + private static final HypixelScoreboard scoreboard = new HypixelScoreboard(); + private static Integer prototypeName = 0; + + public static void start(BedWarsGame game) { + Scheduler scheduler = MinecraftServer.getSchedulerManager(); + scheduler.submitTask(() -> { + if (game == null) { + return TaskSchedule.stop(); + } + + prototypeName++; + if (prototypeName > 50) { + prototypeName = 0; + } + + for (HypixelPlayer player : game.getPlayers()) { + if (player.joined - System.currentTimeMillis() > 5000) { + continue; + } + + + HypixelDataHandler dataHandler = player.getDataHandler(); + BedWarsDataHandler bwDataHandler = BedWarsDataHandler.getUser(player); + + if (dataHandler == null || bwDataHandler == null) { + continue; + } + + String tag = ""; + if (game.getGameType().isDream()) { + tag = " §8[D]"; + } + + List lines = new ArrayList<>(); + lines.add(I18n.t("scoreboard.bedwars_game.date_line", Argument.tagResolver(Formatter.date("date", LocalDateTime.now(ZoneId.systemDefault()))), Argument.string("id", HypixelConst.getServerName()), Argument.string("tag", tag))); + lines.add(Component.space()); + + if (game.getState().isWaiting()) { + lines.add(I18n.t("scoreboard.bedwars_game.map_line", Component.text(game.getMapEntry().getName()))); + lines.add(I18n.t("scoreboard.bedwars_game.players_line", + Component.text(String.valueOf(game.getPlayers().size())), + Component.text(String.valueOf(game.getMapEntry().getConfiguration().getTeams().size())))); + lines.add(Component.space()); + + if (game.getState() == GameState.COUNTDOWN) { + long seconds = game.getCountdown().getRemainingSeconds(); + lines.add(Component.text("§fStarting in §a" + seconds + "s")); + } else { + lines.add(Component.text("§fWaiting...")); + } + lines.add(Component.space()); + lines.add(I18n.t("scoreboard.bedwars_game.mode_line", Component.text(game.getGameType().getDisplayName()))); + lines.add(Component.text("§fVersion: §7v" + VersionConst.BED_WARS_VERSION)); + } else { + BedWarsGameEventManager.GamePhase nextGamePhase = game.getGameType().isOneBlock() + ? BedWarsGameEventManager.GamePhase.GAME_END + : game.getGameEventManager().getCurrentPhase().next(); + String eventName = nextGamePhase != null + ? nextGamePhase.getDisplayName() + : game.getGameEventManager().getCurrentEvent().getDisplayName(); + long seconds = game.getGameEventManager().getSecondsUntilNextPhase(); + long minutesPart = seconds / 60; + long secondsPart = seconds % 60; + String timeLeft = String.format("%d:%02d", minutesPart, secondsPart); + lines.add(I18n.t("scoreboard.bedwars_game.event_in_line", + Component.text(eventName), + Component.text(timeLeft))); + lines.add(Component.space()); + + for (BedWarsTeam team : game.getTeams()) { + TeamKey teamKey = team.getTeamKey(); + String teamName = teamKey.getName(); + String teamInitial = teamName.substring(0, 1).toUpperCase(); + + String bedStatus; + if (!team.hasPlayers()) { + bedStatus = "§c✖"; + } else if (team.isBedAlive()) { + bedStatus = "§a✔"; + } else { + int alivePlayers = game.getPlayersOnTeam(teamKey).stream() + .filter(p -> !Boolean.TRUE.equals(p.getTag(BedWarsGame.ELIMINATED_TAG))) + .toList() + .size(); + if (alivePlayers > 0) { + bedStatus = "§c" + alivePlayers; + } else { + bedStatus = "§c✖"; + } + } + boolean isYourTeam = game.getPlayerTeam(player.getUuid()) + .map(t -> t.getTeamKey() == teamKey) + .orElse(false); + String isYourTeamSuffix = isYourTeam ? " §7YOU" : ""; + lines.add(Component.text(String.format("%s%s §f%s %s%s", teamKey.chatColor(), teamInitial, teamName, bedStatus, isYourTeamSuffix))); + } + } + + lines.add(Component.space()); + lines.add(I18n.t("scoreboard.common.footer")); if (!scoreboard.hasScoreboard(player)) { - scoreboard.createScoreboard(player, Component.text(getSidebarName(prototypeName, l))); + scoreboard.createScoreboard(player, getSidebarName(prototypeName)); } scoreboard.updateLines(player, lines); - scoreboard.updateTitle(player, Component.text(getSidebarName(prototypeName, l))); + scoreboard.updateTitle(player, getSidebarName(prototypeName)); } return TaskSchedule.tick(4); }); } - public static void removeCache(Player player) { - scoreboard.removeScoreboard(player); - } + public static void removeCache(Player player) { + scoreboard.removeScoreboard(player); + } - private static String getSidebarName(int counter, Locale locale) { - String baseText = I18n.string("scoreboard.bedwars_game.title_base", locale); + private static Component getSidebarName(int counter) { + String baseText = "BED WARS"; String[] colors = {"§f§l", "§6§l", "§e§l"}; String endColor = "§a§l"; - if (counter > 0 && counter <= 8) { - return colors[0] + baseText.substring(0, counter - 1) + - colors[1] + baseText.charAt(counter - 1) + - colors[2] + baseText.substring(counter) + - endColor; - } else if ((counter >= 9 && counter <= 19) || - (counter >= 25 && counter <= 29)) { - return colors[0] + baseText + endColor; - } else { - return colors[2] + baseText + endColor; - } - } + if (counter > 0 && counter <= 8) { + return Component.text(colors[0] + baseText.substring(0, counter - 1) + + colors[1] + baseText.charAt(counter - 1) + + colors[2] + baseText.substring(counter) + + endColor); + } else if ((counter >= 9 && counter <= 19) || + (counter >= 25 && counter <= 29)) { + return Component.text(colors[0] + baseText + endColor); + } else { + return Component.text(colors[2] + baseText + endColor); + } + } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameTabListModule.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameTabListModule.java new file mode 100644 index 000000000..994eb41a2 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/BedWarsGameTabListModule.java @@ -0,0 +1,82 @@ +package net.swofty.type.bedwarsgame; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minestom.server.entity.PlayerSkin; +import net.swofty.commons.party.FullParty; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.generic.party.PartyManager; +import net.swofty.type.generic.tab.CustomTablistSkin; +import net.swofty.type.generic.tab.TablistModule; +import net.swofty.type.generic.tab.TablistSkin; +import net.swofty.type.generic.tab.TablistSkinRegistry; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.Collection; +import java.util.List; +import java.util.Random; +import java.util.UUID; + +public class BedWarsGameTabListModule extends TablistModule { + + @Override + public List getEntries(HypixelPlayer p) { + BedWarsPlayer player = (BedWarsPlayer) p; + BedWarsGame game = player.getGame(); + if (game == null) { + return List.of(); + } + + Collection players = game.getPlayers(); + if (game.getState().isWaiting()) { + TablistEntry[] entries = new TablistEntry[players.size()]; + int index = 0; + for (BedWarsPlayer bedWarsPlayer : players) { + boolean shouldObfuscate = bedWarsPlayer.getUuid().compareTo(player.getUuid()) != 0; + FullParty party = PartyManager.getPartyFromPlayer(player); + if (party != null && !shouldObfuscate) { + shouldObfuscate = !party.getParticipants().contains(p.getUuid()); + } + + TablistSkin skin; + PlayerSkin playerSkin = bedWarsPlayer.getSkin(); + + if (shouldObfuscate) { + skin = TablistSkinRegistry.GRAY; + } else if (playerSkin == null) { + skin = TablistSkinRegistry.GRAY; + } else { + skin = new CustomTablistSkin(playerSkin); + } + + String displayName = shouldObfuscate + ? "§k" + UUID.randomUUID().toString().replaceAll("-", "").substring(0, new Random().nextInt(10) + 4) + : LegacyComponentSerializer.legacySection().serialize(bedWarsPlayer.getColouredName()); + entries[index++] = new TablistEntry(displayName, skin); + } + return List.of(entries); + } else if (game.getState().isInProgress()) { + TablistEntry[] entries = new TablistEntry[players.size()]; + int index = 0; + for (BedWarsPlayer bedWarsPlayer : players) { + Component displayName = bedWarsPlayer.getDisplayName(); + if (displayName == null) { + displayName = Component.text(bedWarsPlayer.getUsername()); + } + String name = LegacyComponentSerializer.legacySection().serialize(displayName); + TablistSkin skin; + PlayerSkin playerSkin = bedWarsPlayer.getSkin(); + if (playerSkin == null) { + skin = TablistSkinRegistry.GRAY; + } else { + skin = new CustomTablistSkin(playerSkin); + } + entries[index++] = new TablistEntry(name, skin); + } + return List.of(entries); + } + + return List.of(); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/TypeBedWarsGameLoader.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/TypeBedWarsGameLoader.java index 683844e13..ec61b7c2b 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/TypeBedWarsGameLoader.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/TypeBedWarsGameLoader.java @@ -2,25 +2,33 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonParseException; import lombok.Getter; import lombok.SneakyThrows; import net.hollowcube.polar.PolarLoader; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.minestom.server.MinecraftServer; +import net.minestom.server.color.Color; import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.Player; +import net.minestom.server.entity.Entity; +import net.minestom.server.instance.Instance; import net.minestom.server.instance.InstanceContainer; import net.minestom.server.instance.InstanceManager; +import net.minestom.server.network.packet.server.play.EntityAnimationPacket; +import net.minestom.server.network.packet.server.play.ParticlePacket; import net.minestom.server.registry.RegistryKey; import net.minestom.server.tag.Tag; import net.minestom.server.timer.TaskSchedule; import net.minestom.server.utils.time.TimeUnit; import net.minestom.server.world.DimensionType; -import net.swofty.commons.bedwars.BedwarsGameType; +import net.minestom.server.world.attribute.EnvironmentAttribute; import net.swofty.commons.CustomWorlds; import net.swofty.commons.ServerType; import net.swofty.commons.ServiceType; +import net.swofty.commons.bedwars.BedWarsGameType; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.commons.protocol.objects.orchestrator.GameHeartbeatProtocolObject; import net.swofty.proxyapi.ProxyService; import net.swofty.proxyapi.redis.TypedProxyHandler; @@ -30,24 +38,25 @@ import net.swofty.pvp.feature.CombatFeatures; import net.swofty.pvp.feature.FeatureType; import net.swofty.pvp.utils.CombatVersion; -import net.swofty.type.bedwarsgame.game.Game; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.item.SimpleInteractableItem; +import net.swofty.type.bedwarsgame.item.SimpleInteractableItemHandler; import net.swofty.type.bedwarsgame.shop.ShopManager; import net.swofty.type.bedwarsgame.shop.TeamShopManager; import net.swofty.type.bedwarsgame.shop.TrapManager; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.type.bedwarsgame.item.SimpleInteractableItem; -import net.swofty.type.bedwarsgame.item.SimpleInteractableItemHandler; +import net.swofty.type.game.game.GameObject; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.HypixelConst; -import net.swofty.type.generic.data.GameDataHandler; -import net.swofty.type.generic.data.handlers.BedWarsDataHandler; import net.swofty.type.generic.HypixelGenericLoader; import net.swofty.type.generic.HypixelTypeLoader; +import net.swofty.type.generic.collectibles.bedwars.BedWarsCollectibleCatalog; import net.swofty.type.generic.command.HypixelCommand; +import net.swofty.type.generic.data.GameDataHandler; +import net.swofty.type.generic.data.handlers.BedWarsDataHandler; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.generic.redis.RedisOriginServer; -import net.swofty.type.generic.tab.EmptyTabModule; import net.swofty.type.generic.tab.TablistManager; import net.swofty.type.generic.tab.TablistModule; import net.swofty.type.generic.user.HypixelPlayer; @@ -63,262 +72,354 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.UUID; +import java.util.stream.Stream; import static net.swofty.pvp.feature.CombatFeatures.*; import static net.swofty.type.generic.HypixelGenericLoader.getLoadedPlayers; public class TypeBedWarsGameLoader implements HypixelTypeLoader { - public static final int MAX_GAMES = 8; - - @Getter - public static final List games = new ArrayList<>(); - - @Getter - public static final ShopManager shopManager = new ShopManager(); - @Getter - public static final TeamShopManager teamShopManager = new TeamShopManager(); - @Getter - public static final TrapManager trapManager = new TrapManager(); - @Getter - public static final SimpleInteractableItemHandler itemHandler = new SimpleInteractableItemHandler(); - - public static final Tag<@NotNull Boolean> PLAYER_PLACED_TAG = Tag.Boolean("player_placed"); - public static final Tag<@NotNull Integer> ARMOR_LEVEL_TAG = Tag.Integer("armor_level"); - - static CombatFeatureSet combatFeatures = CombatFeatures.empty().version(CombatVersion.LEGACY).addAll(List.of( - VANILLA_ARMOR, VANILLA_ATTACK, VANILLA_CRITICAL, //VANILLA_SWEEPING, - VANILLA_EQUIPMENT, VANILLA_BLOCK, VANILLA_ATTACK_COOLDOWN, VANILLA_ITEM_COOLDOWN, - VANILLA_DAMAGE, VANILLA_EFFECT, VANILLA_ENCHANTMENT, VANILLA_EXPLOSION, - VANILLA_EXPLOSIVE, VANILLA_FALL, VANILLA_FOOD, LEGACY_VANILLA_BLOCK, - VANILLA_REGENERATION, VANILLA_KNOCKBACK, VANILLA_POTION, //VANILLA_BOW, - VANILLA_CROSSBOW, VANILLA_FISHING_ROD, VANILLA_MISC_PROJECTILE, - VANILLA_PROJECTILE_ITEM, VANILLA_TRIDENT, VANILLA_SPECTATE, - VANILLA_PLAYER_STATE, VANILLA_TOTEM//, VANILLA_DEATH_MESSAGE - )).build(); - - @Getter - private static BedWarsMapsConfig mapsConfig; - private static InstanceManager instanceManager; - private static RegistryKey<@NotNull DimensionType> fullbrightDimension; - private static int nextMapIndex = 0; - private static List filteredMaps = new ArrayList<>(); - private Gson gson; - - public static Game getGameById(@NotNull String gameId) { - return games.stream() - .filter(game -> game.getGameId().equals(gameId)) - .findFirst() - .orElse(null); - } + public static final int MAX_GAMES = 12; - @SneakyThrows - public static Game createGame(BedWarsMapsConfig.MapEntry entry) { - if (games.size() >= MAX_GAMES) { - return null; - } - InstanceContainer mapInstance = instanceManager.createInstanceContainer(fullbrightDimension); - mapInstance.setChunkLoader(new PolarLoader(new File("./configuration/bedwars/" + entry.getId() + ".polar").toPath())); - mapInstance.setExplosionSupplier(combatFeatures.get(FeatureType.EXPLOSION).getExplosionSupplier()); - - Game game = new Game(entry, mapInstance); - games.add(game); - return game; - } + @Getter + public static final List games = new ArrayList<>(); - private static synchronized BedWarsMapsConfig.MapEntry nextMapEntry() { - if (filteredMaps == null || filteredMaps.isEmpty()) return null; - if (nextMapIndex >= filteredMaps.size()) nextMapIndex = 0; - return filteredMaps.get(nextMapIndex++); - } + @Getter + public static final ShopManager shopManager = new ShopManager(); + @Getter + public static final TeamShopManager teamShopManager = new TeamShopManager(); + @Getter + public static final TrapManager trapManager = new TrapManager(); + @Getter + public static final SimpleInteractableItemHandler itemHandler = new SimpleInteractableItemHandler(); - private static Component header() { - return MiniMessage.miniMessage().deserialize("You are playing on MC.HYPIXEL.NET"); - } + public static final Tag<@NotNull Boolean> PLAYER_PLACED_TAG = Tag.Boolean("player_placed"); + public static final Tag<@NotNull Integer> ARMOR_LEVEL_TAG = Tag.Integer("armor_level"); - private static Component footer(HypixelPlayer player) { - Component start = Component.empty(); - BedWarsPlayer bwPlayer = (BedWarsPlayer) player; - if (bwPlayer.getGame() != null) { - start = start.append(MiniMessage.miniMessage().deserialize("Kills: 0 Final Kills: 0 Beds Broken: 0")).appendNewline(); - } - return start - .append(Component.text("§aRanks, Boosters & MORE! §c§lSTORE.HYPIXEL.NET")); - } + @Deprecated // please remember to remove this ARI + public static void printHierarchy(Class clazz) { + if (clazz == null) return; - @Override - public ServerType getType() { - return ServerType.BEDWARS_GAME; - } + System.out.println(clazz.getName()); - @Override - public void onInitialize(MinecraftServer server) { - gson = new GsonBuilder().create(); - instanceManager = MinecraftServer.getInstanceManager(); - fullbrightDimension = MinecraftServer.getDimensionTypeRegistry().register("fullbright", DimensionType.builder().ambientLight(0.9f).build()); - MinecraftServer.getGlobalEventHandler().addChild(combatFeatures.createNode()); - - Path mapsPath = Path.of("./configuration/bedwars/maps.json"); - if (!Files.exists(mapsPath)) { - Logger.error("maps.json not found at {}", mapsPath.toAbsolutePath()); - return; - } - try (InputStream in = Files.newInputStream(mapsPath)) { - byte[] bytes = in.readAllBytes(); - String json = new String(bytes, StandardCharsets.UTF_8); - mapsConfig = gson.fromJson(json, BedWarsMapsConfig.class); - filteredMaps = new ArrayList<>(); - if (mapsConfig != null && mapsConfig.getMaps() != null) { - for (BedWarsMapsConfig.MapEntry e : mapsConfig.getMaps()) { - var cfg = e.getConfiguration(); - List types = (cfg != null) ? cfg.getTypes() : null; - boolean allowed; - if (types == null || types.isEmpty()) { - allowed = true; - } else { - allowed = types.contains(BedwarsGameType.SOLO); - } - if (allowed) filteredMaps.add(e); - createGame(e); - } - } - } catch (Exception e) { - Logger.error("Failed to load maps.json", e); - return; - } - - MinecraftServer.getConnectionManager().setPlayerProvider((gameProfile, playerConnection) -> { - BedWarsPlayer player = new BedWarsPlayer(gameProfile, playerConnection); - - UUID uuid = gameProfile.getPlayer().getUuid(); - String username = gameProfile.getPlayer().getUsername(); - - if (RedisOriginServer.origin.containsKey(uuid)) { - player.setOriginServer(RedisOriginServer.origin.get(uuid)); - RedisOriginServer.origin.remove(uuid); - } - - Logger.info("Received new player: " + username + " (" + uuid + ")"); - - return player; - }); - } + for (Class iface : clazz.getInterfaces()) { + System.out.println(" Implements: " + iface.getName()); + } - @Override - public void afterInitialize(MinecraftServer server) { - HypixelGenericLoader.loopThroughPackage("net.swofty.type.bedwarsgame.commands", HypixelCommand.class).forEach(command -> { - try { - MinecraftServer.getCommandManager().register(command.getCommand()); - } catch (Exception e) { - Logger.error(e, "Failed to register command " + command.getCommand().getName() + " in class " + command.getClass().getSimpleName()); - } - }); - HypixelGenericLoader.loopThroughPackage("net.swofty.type.bedwarsgame.item.impl", SimpleInteractableItem.class).forEach(itemHandler::add); - MinestomPvP.init(); - - // heartbeat to orchestrator with supported maps and current load - MinecraftServer.getSchedulerManager().buildTask(() -> { - UUID uuid = HypixelConst.getServerUUID(); - String shortName = HypixelConst.getShortenedServerName(); - int maxPlayers = HypixelConst.getMaxPlayers(); - int onlinePlayers = MinecraftServer.getConnectionManager().getOnlinePlayers().size(); - - // Convert internal Game objects to commons Game objects - List commonsGames = new ArrayList<>(); - for (Game internalGame : TypeBedWarsGameLoader.getGames()) { - net.swofty.commons.game.Game commonsGame = new net.swofty.commons.game.Game(); - commonsGame.setGameId(UUID.fromString(internalGame.getGameId())); - commonsGame.setType(ServerType.BEDWARS_GAME); - commonsGame.setMap(internalGame.getMapEntry().getName()); - commonsGame.setGameTypeName(internalGame.getBedwarsGameType().name()); - - // Get involved players from the internal game - List playerUuids = new ArrayList<>(); - for (Player player : internalGame.getPlayers()) { - playerUuids.add(player.getUuid()); - } - commonsGame.setInvolvedPlayers(playerUuids); - - // Add disconnected players for rejoin system - commonsGame.setDisconnectedPlayers(internalGame.getDisconnectedPlayerUuids()); - - commonsGames.add(commonsGame); - } - - var heartbeat = new GameHeartbeatProtocolObject.HeartbeatMessage( - uuid, - shortName, - getType(), - maxPlayers, - onlinePlayers, - commonsGames - ); - new ProxyService(ServiceType.ORCHESTRATOR).handleRequest(heartbeat); - }).delay(TaskSchedule.seconds(5)).repeat(TaskSchedule.seconds(1)).schedule(); - - MinecraftServer.getSchedulerManager().buildTask(() -> { - Collection players = getLoadedPlayers(); - if (players.isEmpty()) - return; - for (HypixelPlayer player : players) { - player.sendPlayerListHeaderAndFooter(header(), footer(player)); - } - }).repeat(10, TimeUnit.SERVER_TICK).schedule(); - } + printHierarchy(clazz.getSuperclass()); + } - @Override - public List getRequiredServices() { - return List.of(ServiceType.ORCHESTRATOR); - } + static CombatFeatureSet combatFeatures = CombatFeatures.empty().version(CombatVersion.LEGACY).addAll(List.of( + VANILLA_ARMOR, VANILLA_ATTACK, VANILLA_CRITICAL, //VANILLA_SWEEPING, + VANILLA_EQUIPMENT, VANILLA_BLOCK, VANILLA_ATTACK_COOLDOWN, VANILLA_ITEM_COOLDOWN, + VANILLA_DAMAGE, VANILLA_EFFECT, VANILLA_ENCHANTMENT, VANILLA_EXPLOSION, + VANILLA_EXPLOSIVE, VANILLA_FALL, VANILLA_FOOD, LEGACY_VANILLA_BLOCK, + VANILLA_REGENERATION, VANILLA_KNOCKBACK, VANILLA_POTION, VANILLA_BOW, + VANILLA_CROSSBOW, VANILLA_FISHING_ROD, VANILLA_MISC_PROJECTILE, + VANILLA_PROJECTILE_ITEM, VANILLA_TRIDENT, VANILLA_SPECTATE, + VANILLA_PLAYER_STATE, VANILLA_TOTEM//, VANILLA_DEATH_MESSAGE + )).soundProvider((audience, original, x, y, z) -> { + printHierarchy(audience.getClass()); + audience.playSound(original, x, y, z); + // Try to get the game from the audience context + BedWarsGame game = null; + if (audience instanceof BedWarsPlayer player) { + game = player.getGame(); + } else if (audience instanceof net.minestom.server.entity.Entity entity) { + game = TypeBedWarsGameLoader.getGameByInstance(entity.getInstance()); + } + if (game != null && game.getReplayManager().isRecording()) { + game.getReplayManager().recordSound(original, x, y, z); + } + }).packetProvider((viewable, packet) -> { + printHierarchy(viewable.getClass()); + viewable.sendPacketToViewersAndSelf(packet); + BedWarsGame game = null; + if (viewable instanceof BedWarsPlayer bwPlayer) { + game = bwPlayer.getGame(); + } else if (viewable instanceof Entity entity) { + game = TypeBedWarsGameLoader.getGameByInstance(entity.getInstance()); + } + if (game == null || !game.getReplayManager().isRecording()) { + return; + } + + if (packet instanceof ParticlePacket particlePacket) { + game.getReplayManager().recordParticle(particlePacket); + } else if (packet instanceof EntityAnimationPacket animationPacket) { + game.getReplayManager().recordEntityAnimation(animationPacket); + } + }).build(); + + @Getter + private static BedWarsMapsConfig mapsConfig; + private static InstanceManager instanceManager; + private static RegistryKey<@NotNull DimensionType> fullbrightDimension; + private Gson gson; + + @Nullable + public static BedWarsGame getGameById(@NotNull String gameId) { + return games.stream() + .filter(game -> game.getGameId().equals(gameId)) + .findFirst() + .orElse(null); + } - @Override - public TablistManager getTablistManager() { - return new TablistManager() { - @Override - public List getModules() { - return List.of( - new EmptyTabModule(), - new EmptyTabModule(), - new EmptyTabModule(), - new EmptyTabModule() - ); - } - }; - } + @Nullable + public static BedWarsGame getGameByInstance(@NotNull Instance instance) { + return games.stream() + .filter(game -> game.getInstance().equals(instance)) + .findFirst() + .orElse(null); + } - @Override - public LoaderValues getLoaderValues() { - return new LoaderValues( - (_) -> new Pos(-39.5, 72, 0, -90, 0), // Spawn position - false // Announce death messages - ); - } + @SneakyThrows + public static synchronized BedWarsGame createGame(@NotNull BedWarsMapsConfig.MapEntry entry, @NotNull BedWarsGameType type) { + if (games.size() >= MAX_GAMES) { + return null; + } + InstanceContainer mapInstance = instanceManager.createInstanceContainer(fullbrightDimension); + mapInstance.setChunkLoader(new PolarLoader(new File("./configuration/bedwars/" + entry.getId() + ".polar").toPath())); + mapInstance.setExplosionSupplier(combatFeatures.get(FeatureType.EXPLOSION).getExplosionSupplier()); + + BedWarsGame game = new BedWarsGame(entry, mapInstance, type); + games.add(game); + return game; + } - @Override - public List getTraditionalEvents() { - return HypixelGenericLoader.loopThroughPackage( - "net.swofty.type.bedwarsgame.events", - HypixelEventClass.class - ).toList(); - } + private static List getSupportedTypes(BedWarsMapsConfig.MapEntry mapEntry) { + BedWarsMapsConfig.MapEntry.MapConfiguration config = mapEntry.getConfiguration(); + if (config == null || config.getTypes() == null) { + return List.of(); + } + return config.getTypes().stream() + .filter(Objects::nonNull) + .flatMap(type -> Stream.concat(Stream.of(type), BedWarsGameType.getDreamTypes().stream() + .filter(dreamType -> dreamType.getMapCompatibilityType() == type))) + .distinct() + .toList(); + } - @Override - public List getCustomEvents() { - return HypixelGenericLoader.loopThroughPackage( - "net.swofty.type.bedwarsgame.events.custom", - HypixelEventClass.class - ).toList(); - } + private static Component header() { + return MiniMessage.miniMessage().deserialize("You are playing on MC.HYPIXEL.NET"); + } - @Override - public List getNPCs() { - return HypixelGenericLoader.loopThroughPackage( - "net.swofty.type.bedwarsgame.npcs", - HypixelNPC.class - ).toList(); - } + private static Component footer(BedWarsPlayer player) { + Component start = Component.empty(); + if (player.getGame() != null) { + start = start.append(MiniMessage.miniMessage().deserialize("Kills: 0 Final Kills: 0 Beds Broken: 0")).appendNewline(); + } + return start + .append(Component.text("§aRanks, Boosters & MORE! §c§lSTORE.HYPIXEL.NET")); + } + + @Override + public ServerType getType() { + return ServerType.BEDWARS_GAME; + } + + @Override + public void onInitialize(MinecraftServer server) { + BedWarsCollectibleCatalog.initialize(); + gson = new GsonBuilder() + .registerTypeAdapter(BedWarsGameType.class, (JsonDeserializer) (json, _, _) -> { + String value = json.getAsString(); + BedWarsGameType gameType = BedWarsGameType.from(value); + if (gameType == null) { + throw new JsonParseException("Unknown BedWars game type: " + value); + } + return gameType; + }) + .create(); + instanceManager = MinecraftServer.getInstanceManager(); + fullbrightDimension = MinecraftServer.getDimensionTypeRegistry().register("fullbright", DimensionType.builder().ambientLight(1f).setAttribute(EnvironmentAttribute.AMBIENT_LIGHT_COLOR, Color.WHITE).build()); + MinecraftServer.getGlobalEventHandler().addChild(combatFeatures.createNode()); + + Path mapsPath = Path.of("./configuration/bedwars/maps.json"); + if (!Files.exists(mapsPath)) { + Logger.error("maps.json not found at {}", mapsPath.toAbsolutePath()); + return; + } + try (InputStream in = Files.newInputStream(mapsPath)) { + byte[] bytes = in.readAllBytes(); + String json = new String(bytes, StandardCharsets.UTF_8); + mapsConfig = gson.fromJson(json, BedWarsMapsConfig.class); + if (mapsConfig == null || mapsConfig.getMaps() == null) { + Logger.warn("maps.json was loaded but contained no BedWars maps"); + } + } catch (Exception e) { + Logger.error("Failed to load maps.json"); + e.printStackTrace(); + return; + } + + MinecraftServer.getConnectionManager().setPlayerProvider((gameProfile, playerConnection) -> { + BedWarsPlayer player = new BedWarsPlayer(gameProfile, playerConnection); + + UUID uuid = gameProfile.getPlayer().getUuid(); + String username = gameProfile.getPlayer().getUsername(); + + if (RedisOriginServer.origin.containsKey(uuid)) { + player.setOriginServer(RedisOriginServer.origin.get(uuid)); + RedisOriginServer.origin.remove(uuid); + } + + Logger.info("Received new player: " + username + " (" + uuid + ")"); + + return player; + }); + } + + @Override + public void afterInitialize(MinecraftServer server) { + HypixelGenericLoader.loopThroughPackage("net.swofty.type.bedwarsgame.commands", HypixelCommand.class).forEach(command -> { + try { + MinecraftServer.getCommandManager().register(command.getCommand()); + } catch (Exception e) { + Logger.error(e, "Failed to register command " + command.getCommand().getName() + " in class " + command.getClass().getSimpleName()); + } + }); + HypixelGenericLoader.loopThroughPackage("net.swofty.type.bedwarsgame.item.impl", SimpleInteractableItem.class).forEach(itemHandler::add); + itemHandler.getShopBackedItems().forEach(shopManager::addInteractableItem); + MinestomPvP.init(); + + // heartbeat to orchestrator with supported maps and current load + MinecraftServer.getSchedulerManager().buildTask(() -> { + UUID uuid = HypixelConst.getServerUUID(); + String shortName = HypixelConst.getShortenedServerName(); + int maxPlayers = HypixelConst.getMaxPlayers(); + int onlinePlayers = MinecraftServer.getConnectionManager().getOnlinePlayers().size(); + + // Convert BedWarsGame objects to commons Game objects + List commonsGames = new ArrayList<>(); + for (BedWarsGame game : TypeBedWarsGameLoader.getGames()) { + GameObject commonsGame = new GameObject(); + commonsGame.setGameId(UUID.fromString(game.getGameId())); + commonsGame.setType(ServerType.BEDWARS_GAME); + commonsGame.setMap(game.getMapEntry().getName()); + commonsGame.setGameTypeName(game.getGameType().name()); + commonsGame.setAcceptingJoins(game.getState() == GameState.WAITING || game.getState() == GameState.COUNTDOWN); + + // Get involved players from the game + List playerUuids = new ArrayList<>(); + for (BedWarsPlayer player : game.getPlayers()) { + playerUuids.add(player.getUuid()); + } + commonsGame.setInvolvedPlayers(playerUuids); + + // Add disconnected players for rejoin system + commonsGame.setDisconnectedPlayers(game.getDisconnectedPlayerUuids()); + + commonsGames.add(commonsGame); + } + + List mapAdvertisements = new ArrayList<>(); + if (mapsConfig != null && mapsConfig.getMaps() != null) { + for (BedWarsMapsConfig.MapEntry entry : mapsConfig.getMaps()) { + String mapId = entry.getId(); + String mapName = entry.getName(); + if (mapId == null && mapName == null) { + continue; + } + if (mapId == null) { + mapId = mapName; + } + if (mapName == null) { + mapName = mapId; + } + + List supportedModes = getSupportedTypes(entry).stream() + .map(BedWarsGameType::name) + .toList(); + mapAdvertisements.add(new GameHeartbeatProtocolObject.MapAdvertisement(mapId, mapName, supportedModes)); + } + } + + int remainingGameSlots = Math.max(0, MAX_GAMES - TypeBedWarsGameLoader.getGames().size()); + + var heartbeat = new GameHeartbeatProtocolObject.HeartbeatMessage( + uuid, + shortName, + getType(), + maxPlayers, + onlinePlayers, + commonsGames, + mapAdvertisements, + remainingGameSlots + ); + new ProxyService(ServiceType.ORCHESTRATOR).handleRequest(heartbeat); + }).delay(TaskSchedule.seconds(5)).repeat(TaskSchedule.seconds(1)).schedule(); + + MinecraftServer.getSchedulerManager().buildTask(() -> { + Collection players = getLoadedPlayers(); + if (players.isEmpty()) + return; + for (HypixelPlayer player : players) { + player.sendPlayerListHeaderAndFooter(header(), footer((BedWarsPlayer) player)); + } + }).repeat(10, TimeUnit.SERVER_TICK).schedule(); + } + + @Override + public List getRequiredServices() { + return List.of(ServiceType.ORCHESTRATOR); + } + @Override + public TablistManager getTablistManager() { + return new TablistManager() { + @Override + public List getModules() { + return List.of( + new BedWarsGameTabListModule() + ); + } + }; + } + + @Override + public LoaderValues getLoaderValues() { + return new LoaderValues( + (_) -> new Pos(-39.5, 72, 0, -90, 0), // Spawn position + false // Announce death messages + ); + } + + @Override + public List getTraditionalEvents() { + return Stream.concat( + HypixelGenericLoader.loopThroughPackage( + "net.swofty.type.bedwarsgame.events", + HypixelEventClass.class + ), + HypixelGenericLoader.loopThroughPackage( + "net.swofty.type.bedwarsgame.game.v2.listener", + HypixelEventClass.class + ) + ).toList(); + } + + @Override + public List getCustomEvents() { + return Stream.concat(HypixelGenericLoader.loopThroughPackage( + "net.swofty.type.bedwarsgame.events.custom", + HypixelEventClass.class + ), + HypixelGenericLoader.loopThroughPackage( + "net.swofty.type.game.game.event", + HypixelEventClass.class + )).toList(); + } + + @Override + public List getNPCs() { + return HypixelGenericLoader.loopThroughPackage( + "net.swofty.type.bedwarsgame.npcs", + HypixelNPC.class + ).toList(); + } @Override @SuppressWarnings("unchecked") @@ -338,13 +439,13 @@ public List getNPCs() { ).toList(); } - @Override - public @Nullable CustomWorlds getMainInstance() { - return null; - } + @Override + public @Nullable CustomWorlds getMainInstance() { + return null; + } - @Override - public List> getAdditionalDataHandlers() { - return List.of(BedWarsDataHandler.class); - } + @Override + public List> getAdditionalDataHandlers() { + return List.of(BedWarsDataHandler.class); + } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/BedWarsAdminCommand.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/BedWarsAdminCommand.java new file mode 100644 index 000000000..12cd28d6d --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/BedWarsAdminCommand.java @@ -0,0 +1,203 @@ +package net.swofty.type.bedwarsgame.commands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; +import net.swofty.type.game.game.event.GameTeamWinConditionEvent; +import net.swofty.type.generic.command.CommandParameters; +import net.swofty.type.generic.command.HypixelCommand; +import net.swofty.type.generic.user.categories.Rank; + +import java.util.Optional; + +@CommandParameters(aliases = "bwadmin", + description = "Admin commands for BedWars game management.", + usage = "/bwadmin [team]", + permission = Rank.STAFF, + allowsConsole = false) +public class BedWarsAdminCommand extends HypixelCommand { + + @Override + public void registerUsage(HypixelCommand.MinestomCommand command) { + // /bwadmin breakbed + command.addSyntax((sender, context) -> { + if (!permissionCheck(sender)) return; + if (!(sender instanceof BedWarsPlayer player)) return; + + String teamName = context.get("team"); + BedWarsGame game = player.getGame(); + + if (game == null) { + player.sendMessage(Component.text("You are not in a game!", NamedTextColor.RED)); + return; + } + + TeamKey teamKey; + try { + teamKey = TeamKey.valueOf(teamName.toUpperCase()); + } catch (IllegalArgumentException e) { + player.sendMessage(Component.text("Invalid team: " + teamName, NamedTextColor.RED)); + return; + } + + if (!game.isBedAlive(teamKey)) { + player.sendMessage(Component.text("That team's bed is already destroyed!", NamedTextColor.RED)); + return; + } + + game.onBedDestroyed(teamKey, player); + }, ArgumentType.Literal("breakbed"), ArgumentType.String("team")); + + // /bwadmin respawnbed + command.addSyntax((sender, context) -> { + if (!permissionCheck(sender)) return; + if (!(sender instanceof BedWarsPlayer player)) return; + + String teamName = context.get("team"); + BedWarsGame game = player.getGame(); + + if (game == null) { + player.sendMessage(Component.text("You are not in a game!", NamedTextColor.RED)); + return; + } + + TeamKey teamKey; + try { + teamKey = TeamKey.valueOf(teamName.toUpperCase()); + } catch (IllegalArgumentException e) { + player.sendMessage(Component.text("Invalid team: " + teamName, NamedTextColor.RED)); + return; + } + + if (game.isBedAlive(teamKey)) { + player.sendMessage(Component.text("That team's bed is already alive!", NamedTextColor.RED)); + return; + } + + game.respawnBed(teamKey); + + }, ArgumentType.Literal("respawnbed"), ArgumentType.String("team")); + + // /bwadmin endgame [winner] + command.addSyntax((sender, context) -> { + if (!permissionCheck(sender)) return; + if (!(sender instanceof BedWarsPlayer player)) return; + + BedWarsGame game = player.getGame(); + + if (game == null) { + player.sendMessage(Component.text("You are not in a game!", NamedTextColor.RED)); + return; + } + + String winnerTeam = context.get("winner"); + TeamKey winnerKey = null; + + if (winnerTeam != null && !winnerTeam.isEmpty()) { + try { + winnerKey = TeamKey.valueOf(winnerTeam.toUpperCase()); + } catch (IllegalArgumentException e) { + player.sendMessage(Component.text("Invalid team: " + winnerTeam, NamedTextColor.RED)); + return; + } + } + + if (winnerKey != null) { + BedWarsTeam team = game.getTeam(winnerKey.name()).orElse(null); + game.getEventDispatcher().accept( + new GameTeamWinConditionEvent<>( + game.getGameId(), + Optional.ofNullable(team) + ) + ); + } else { + game.getEventDispatcher().accept( + new GameTeamWinConditionEvent<>( + game.getGameId(), + Optional.empty() + ) + ); + } + + }, ArgumentType.Literal("endgame"), ArgumentType.String("winner").setDefaultValue("")); + + // /bwadmin endgame (no args version) + command.addSyntax((sender, _) -> { + if (!permissionCheck(sender)) return; + if (!(sender instanceof BedWarsPlayer player)) return; + + BedWarsGame game = player.getGame(); + + if (game == null) { + player.sendMessage(Component.text("You are not in a game!", NamedTextColor.RED)); + return; + } + + game.getEventDispatcher().accept( + new GameTeamWinConditionEvent<>( + game.getGameId(), + Optional.empty() + ) + ); + }, ArgumentType.Literal("endgame")); + + // /bwadmin info + command.addSyntax((sender, context) -> { + if (!permissionCheck(sender)) return; + if (!(sender instanceof BedWarsPlayer player)) return; + + BedWarsGame game = player.getGame(); + + if (game == null) { + player.sendMessage(Component.text("You are not in a game!", NamedTextColor.RED)); + return; + } + + player.sendMessage(Component.text("=== Game Info ===", NamedTextColor.GOLD)); + player.sendMessage(Component.text("Game ID: " + game.getGameId(), NamedTextColor.YELLOW)); + player.sendMessage(Component.text("State: " + game.getState(), NamedTextColor.YELLOW)); + player.sendMessage(Component.text("Map: " + game.getMapEntry().getName(), NamedTextColor.YELLOW)); + player.sendMessage(Component.text("Players: " + game.getPlayers().size() + "/" + game.getMaxPlayers(), NamedTextColor.YELLOW)); + player.sendMessage(Component.text("Recording: " + game.getReplayManager().isRecording(), NamedTextColor.YELLOW)); + + player.sendMessage(Component.text("=== Teams ===", NamedTextColor.GOLD)); + for (BedWarsTeam team : game.getTeams()) { + String bedStatus = team.isBedAlive() ? "§a✔" : "§c✖"; + player.sendMessage(Component.text(team.getColorCode() + team.getName() + " " + bedStatus + + " §7(" + team.getPlayerCount() + " players)", NamedTextColor.WHITE)); + } + }, ArgumentType.Literal("info")); + + command.addSyntax((sender, context) -> { + if (!permissionCheck(sender)) return; + BedWarsPlayer player = (BedWarsPlayer) sender; + BedWarsGame game = player.getGame(); + if (game == null) { + player.sendMessage("§cYou are not in a game."); + return; + } + + game.getReplayManager().stopRecording(); + }); + + command.addSyntax((sender, _) -> { + if (!permissionCheck(sender)) return; + BedWarsPlayer player = (BedWarsPlayer) sender; + BedWarsGame game = player.getGame(); + if (game == null) { + player.sendMessage("§cYou are not in a game."); + return; + } + if (game.getState() != GameState.WAITING && game.getState() != GameState.COUNTDOWN) { + player.sendMessage("§cYou can only force start a game that is waiting."); + return; + } + game.start(); + }, ArgumentType.Literal("forcestart")); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/ForceStartCommand.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/ForceStartCommand.java deleted file mode 100644 index 7286b576f..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/ForceStartCommand.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.swofty.type.bedwarsgame.commands; - -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; -import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import net.swofty.type.generic.command.CommandParameters; -import net.swofty.type.generic.command.HypixelCommand; -import net.swofty.type.generic.user.categories.Rank; - -@CommandParameters(aliases = "forcestart", - description = "Starts a bedwars game immediately.", - usage = "/forcestart", - permission = Rank.STAFF, - allowsConsole = false) -public class ForceStartCommand extends HypixelCommand { - - @Override - public void registerUsage(MinestomCommand command) { - command.addSyntax((sender, context) -> { - if (!permissionCheck(sender)) return; - BedWarsPlayer player = (BedWarsPlayer) sender; - Game game = player.getGame(); - if (game == null) { - player.sendMessage("§cYou are not in a game."); - return; - } - if (game.getGameStatus() != GameStatus.WAITING) { - player.sendMessage("§cYou can only force start a game that is waiting."); - return; - } - game.startGame(); - }); - } - -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/GameStateCommand.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/GameStateCommand.java deleted file mode 100644 index 74ecb63d9..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/GameStateCommand.java +++ /dev/null @@ -1,35 +0,0 @@ -package net.swofty.type.bedwarsgame.commands; - -import net.minestom.server.command.builder.arguments.ArgumentString; -import net.minestom.server.command.builder.arguments.ArgumentType; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import net.swofty.type.generic.command.CommandParameters; -import net.swofty.type.generic.command.HypixelCommand; -import net.swofty.type.generic.user.categories.Rank; - -@CommandParameters(aliases = "gamestate", - description = "Changes something about the game state.", - usage = "/gamestate ", - permission = Rank.STAFF, - allowsConsole = false) -public class GameStateCommand extends HypixelCommand { - @Override - public void registerUsage(MinestomCommand command) { - ArgumentString teamArg = ArgumentType.String("team"); - command.addSyntax((sender, context) -> { - if (!permissionCheck(sender)) return; - if (!(sender instanceof BedWarsPlayer player)) return; - String team = context.get("team"); - Game game = player.getGame(); - - if (game == null) { - player.sendMessage("§cYou are not in a game."); - return; - } - - game.recordBedDestroyed(BedWarsMapsConfig.TeamKey.valueOf(team)); - }, ArgumentType.Literal("breakBed"), teamArg); - } -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/ShoutCommand.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/ShoutCommand.java index 294450c4b..e55a94e67 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/ShoutCommand.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/commands/ShoutCommand.java @@ -1,10 +1,10 @@ package net.swofty.type.bedwarsgame.commands; import net.minestom.server.command.builder.arguments.ArgumentType; -import net.swofty.commons.bedwars.BedwarsGameType; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.commons.bedwars.BedWarsGameType; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.command.CommandParameters; import net.swofty.type.generic.command.HypixelCommand; import net.swofty.type.generic.user.categories.Rank; @@ -25,16 +25,16 @@ public void registerUsage(MinestomCommand command) { if (!permissionCheck(sender)) return; BedWarsPlayer player = (BedWarsPlayer) sender; - Game game = player.getGame(); + BedWarsGame game = player.getGame(); if (game == null) { player.sendMessage("§cYou are not in a game."); return; } - if (game.getBedwarsGameType() == BedwarsGameType.SOLO) { + if (game.getGameType() == BedWarsGameType.ONE_EIGHT) { player.sendMessage("§cThis command is unavailable."); return; } - if (game.getGameStatus() != GameStatus.IN_PROGRESS) { + if (game.getState() != GameState.IN_PROGRESS) { player.sendMessage("§cYou can only shout messages during an active game."); return; } @@ -45,9 +45,13 @@ public void registerUsage(MinestomCommand command) { for (BedWarsPlayer receiver : game.getPlayers()) { receiver.sendMessage("§6[SHOUT] §r" + player.getFullDisplayName() + "§r: " + message); } + + if (game.getReplayManager().isRecording()) { + game.getReplayManager().recordPlayerChat(player, message, true); + } }, messageArg); - command.setDefaultExecutor((sender, context) -> { + command.setDefaultExecutor((sender, _) -> { sender.sendMessage("§cPlease provide a message to shout."); }); } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathHandler.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathHandler.java index 435f1ac40..ff15dd660 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathHandler.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathHandler.java @@ -3,216 +3,120 @@ import net.kyori.adventure.text.Component; import net.kyori.adventure.text.minimessage.MiniMessage; import net.minestom.server.entity.Entity; -import net.minestom.server.entity.damage.Damage; -import net.minestom.server.entity.damage.DamageType; -import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.game.Game; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class BedWarsDeathHandler { +public final class BedWarsDeathHandler { + private static final MiniMessage MM = MiniMessage.miniMessage(); - private static final int VOID_Y_THRESHOLD = 1; - public static BedWarsDeathResult calculateDeath(@NotNull BedWarsPlayer victim, @NotNull Game game) { + private BedWarsDeathHandler() { + } + + public static BedWarsDeathResult calculateDeath(@NotNull BedWarsPlayer victim, @NotNull BedWarsGame game, boolean isVoidKill) { TeamKey teamKey = victim.getTeamKey(); - boolean isFinalKill = teamKey != null && !game.getTeamManager().isBedAlive(teamKey); + boolean isFinalKill = teamKey != null && !game.isBedAlive(teamKey); - Damage lastDamage = victim.getLastDamageSource(); BedWarsPlayer recentAttacker = BedWarsCombatTracker.getRecentAttacker(victim); + Material lastAttackerWeapon = BedWarsCombatTracker.getLastAttackerWeapon(victim); BedWarsDeathResult.Builder builder = BedWarsDeathResult.builder() - .victim(victim) - .isFinalKill(isFinalKill); - - // No damage source at all - if (lastDamage == null) { - return handleNoDamageSource(builder, victim, recentAttacker); - } - - Entity attacker = lastDamage.getAttacker(); - DamageType damageType = lastDamage.getType().asValue(); - - // Direct player kill - if (attacker instanceof BedWarsPlayer killer) { - return handlePlayerKill(builder, victim, killer, damageType); - } + .victim(victim) + .isFinalKill(isFinalKill) + .weaponUsed(lastAttackerWeapon); - // Mob kill - if (attacker != null) { - return handleMobKill(builder, attacker); - } - - // Environmental death - check for assist - return handleEnvironmentalDeath(builder, victim, damageType, recentAttacker); - } - - private static BedWarsDeathResult handleNoDamageSource(BedWarsDeathResult.Builder builder, - BedWarsPlayer victim, - @Nullable BedWarsPlayer recentAttacker) { - boolean isInVoid = victim.getPosition().y() <= VOID_Y_THRESHOLD; - - if (isInVoid) { + if (isVoidKill) { if (recentAttacker != null) { return builder - .deathType(BedWarsDeathType.VOID_ASSISTED) - .assistPlayer(recentAttacker) - .weaponUsed(BedWarsCombatTracker.getLastAttackerWeapon(victim)) - .build(); + .deathType(BedWarsDeathType.VOID_ASSISTED) + .assistPlayer(recentAttacker) + .build(); } - return builder.deathType(BedWarsDeathType.VOID).build(); - } - - return builder.deathType(BedWarsDeathType.GENERIC).build(); - } - - private static BedWarsDeathResult handlePlayerKill(BedWarsDeathResult.Builder builder, - BedWarsPlayer victim, - BedWarsPlayer killer, - DamageType damageType) { - BedWarsDeathType deathType; - - if (damageType == DamageType.OUT_OF_WORLD.asValue() || victim.getPosition().y() <= VOID_Y_THRESHOLD) { - deathType = BedWarsDeathType.PLAYER_VOID_KNOCK; - } else if (damageType == DamageType.FALL.asValue()) { - deathType = BedWarsDeathType.PLAYER_FALL_KNOCK; - } else if (damageType == DamageType.ARROW.asValue() || damageType == DamageType.TRIDENT.asValue()) { - deathType = BedWarsDeathType.PLAYER_PROJECTILE; - } else if (damageType == DamageType.EXPLOSION.asValue() || damageType == DamageType.PLAYER_EXPLOSION.asValue()) { - deathType = BedWarsDeathType.PLAYER_EXPLOSION; - } else if (damageType == DamageType.ON_FIRE.asValue() || damageType == DamageType.IN_FIRE.asValue()) { - deathType = BedWarsDeathType.PLAYER_FIRE; - } else { - deathType = BedWarsDeathType.PLAYER_MELEE; + return builder + .deathType(BedWarsDeathType.VOID) + .build(); } - Material weaponUsed = null; - ItemStack weapon = killer.getItemInMainHand(); - if (weapon != null && !weapon.isAir()) { - weaponUsed = weapon.material(); + if (recentAttacker != null) { + BedWarsDeathType type = isRangedWeapon(lastAttackerWeapon) ? BedWarsDeathType.BOW : BedWarsDeathType.GENERIC_ASSISTED; + return builder + .deathType(type) + .killer(recentAttacker) + .build(); } return builder - .deathType(deathType) - .killer(killer) - .weaponUsed(weaponUsed) - .build(); + .deathType(BedWarsDeathType.GENERIC) + .build(); } - private static BedWarsDeathResult handleMobKill(BedWarsDeathResult.Builder builder, Entity attacker) { - return builder - .deathType(BedWarsDeathType.MOB_KILL) - .attackerEntity(attacker) - .build(); + private static boolean isRangedWeapon(@Nullable Material weapon) { + if (weapon == null) return false; + return weapon == Material.BOW + || weapon == Material.CROSSBOW + || weapon == Material.TRIDENT; } - private static BedWarsDeathResult handleEnvironmentalDeath(BedWarsDeathResult.Builder builder, - BedWarsPlayer victim, - DamageType damageType, - @Nullable BedWarsPlayer recentAttacker) { - boolean isInVoid = victim.getPosition().y() <= VOID_Y_THRESHOLD; - - // Void death - if (damageType == DamageType.OUT_OF_WORLD.asValue() || isInVoid) { - if (recentAttacker != null) { - return builder - .deathType(BedWarsDeathType.VOID_ASSISTED) - .assistPlayer(recentAttacker) - .weaponUsed(BedWarsCombatTracker.getLastAttackerWeapon(victim)) - .build(); + public static Component createDeathMessage(@NotNull BedWarsDeathResult result) { + BedWarsPlayer victim = result.victim(); + Component victimDisplay = colorizeName(victim); + + Component message = switch (result.deathType()) { + case VOID -> MM.deserialize("").append(victimDisplay).append(MM.deserialize(" fell into the void.")); + case VOID_ASSISTED -> { + Component assistDisplay = colorizeName(result.assistPlayer()); + yield MM.deserialize("") + .append(victimDisplay) + .append(MM.deserialize(" was knocked into the void by ")) + .append(assistDisplay) + .append(MM.deserialize(".")); } - return builder.deathType(BedWarsDeathType.VOID).build(); - } - - // Fall death - if (damageType == DamageType.FALL.asValue()) { - if (recentAttacker != null) { - return builder - .deathType(BedWarsDeathType.FALL_ASSISTED) - .assistPlayer(recentAttacker) - .weaponUsed(BedWarsCombatTracker.getLastAttackerWeapon(victim)) - .build(); + case GENERIC -> MM.deserialize("").append(victimDisplay).append(MM.deserialize(" died.")); + case GENERIC_ASSISTED -> { + Component killerDisplay = colorizeName(result.getKillCreditPlayer()); + yield MM.deserialize("") + .append(victimDisplay) + .append(MM.deserialize(" was killed by ")) + .append(killerDisplay) + .append(MM.deserialize(".")); } - return builder.deathType(BedWarsDeathType.FALL).build(); - } - - // Fire death - if (damageType == DamageType.ON_FIRE.asValue() || damageType == DamageType.IN_FIRE.asValue() - || damageType == DamageType.LAVA.asValue()) { - return builder.deathType(BedWarsDeathType.FIRE).build(); - } - - // Explosion death - if (damageType == DamageType.EXPLOSION.asValue()) { - return builder.deathType(BedWarsDeathType.EXPLOSION).build(); - } - - return builder.deathType(BedWarsDeathType.GENERIC).build(); - } - - public static Component createDeathMessage(@NotNull BedWarsDeathResult result) { - String victimName = result.victim().getUsername(); - String victimColor = getTeamColor(result.victim()); - BedWarsDeathType deathType = result.deathType(); - String messageFormat = deathType.getMessageFormat(); - - Component message; - if (deathType.involvesPlayer()) { - BedWarsPlayer involvedPlayer = deathType.isAssisted() ? result.assistPlayer() : result.killer(); - message = createPlayerInvolvedMessage(victimName, victimColor, involvedPlayer, messageFormat); - } else if (deathType == BedWarsDeathType.MOB_KILL) { - message = createMobKillMessage(victimName, victimColor, messageFormat, result.attackerEntity()); - } else { - message = createSingleMessage(victimName, victimColor, messageFormat); - } + case BOW -> { + Component killerDisplay = colorizeName(result.getKillCreditPlayer()); + yield MM.deserialize("") + .append(victimDisplay) + .append(MM.deserialize(" was shot by ")) + .append(killerDisplay) + .append(MM.deserialize(".")); + } + case ENTITY -> { + Entity entity = result.attackerEntity(); + String entityName = entity != null ? entity.getEntityType().name() : "an entity"; + BedWarsPlayer killer = result.killer(); + Component killerDisplay = colorizeName(killer); + yield MM.deserialize("") + .append(victimDisplay) + .append(MM.deserialize(" was slain by ")) + .append(killerDisplay) + .append(MM.deserialize("'s " + entityName + ".")); + } + }; - // Append FINAL KILL if applicable if (result.isFinalKill()) { - message = message.append( - MiniMessage.miniMessage().deserialize(" FINAL KILL!") - ); + message = message.append(MM.deserialize(" FINAL KILL!")); } - return message; } - private static Component createPlayerInvolvedMessage(String victimName, String victimColor, - @Nullable BedWarsPlayer otherPlayer, - String messageFormat) { - if (otherPlayer == null) { - return createSingleMessage(victimName, victimColor, messageFormat); - } - - String otherColor = getTeamColor(otherPlayer); - return Component.text(victimColor + victimName + "§7" + messageFormat + otherColor + otherPlayer.getUsername() + "§7."); - } - - private static Component createSingleMessage(String victimName, String victimColor, String messageFormat) { - return Component.text(victimColor + victimName + "§7" + messageFormat); - } - - private static Component createMobKillMessage(String victimName, String victimColor, String messageFormat, - @Nullable Entity mob) { - String mobName = mob != null - ? mob.getEntityType().name().toLowerCase().replace("_", " ") - : "a mob"; - - return Component.text(victimColor + victimName + "§7" + messageFormat + mobName + "§7."); - } - - private static String getTeamColor(@Nullable BedWarsPlayer player) { + private static Component colorizeName(@Nullable BedWarsPlayer player) { if (player == null) { - return "§7"; + return MM.deserialize("Unknown"); } TeamKey teamKey = player.getTeamKey(); - if (teamKey == null) { - return "§7"; - } - - return teamKey.chatColor(); + String legacyColor = teamKey != null ? teamKey.chatColor() : "§7"; + return Component.text(legacyColor + player.getUsername()); } } - diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathResult.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathResult.java index f31ff0d55..c07f86036 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathResult.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathResult.java @@ -7,36 +7,20 @@ import org.jetbrains.annotations.Nullable; public record BedWarsDeathResult( - @NotNull BedWarsDeathType deathType, - @NotNull BedWarsPlayer victim, - @Nullable BedWarsPlayer killer, - @Nullable BedWarsPlayer assistPlayer, - @Nullable Entity attackerEntity, - @Nullable Material weaponUsed, - boolean isFinalKill + @NotNull BedWarsDeathType deathType, + @NotNull BedWarsPlayer victim, + @Nullable BedWarsPlayer killer, + @Nullable BedWarsPlayer assistPlayer, + @Nullable Entity attackerEntity, + @Nullable Material weaponUsed, + boolean isFinalKill ) { @Nullable public BedWarsPlayer getKillCreditPlayer() { return killer != null ? killer : assistPlayer; } - public boolean hasPlayerInvolvement() { - return killer != null || assistPlayer != null; - } - - public boolean isDirectKill() { - return killer != null && assistPlayer == null; - } - - public boolean isAssistedKill() { - return assistPlayer != null && killer == null; - } - - public boolean wasKilledWith(Material material) { - return weaponUsed != null && weaponUsed == material; - } - - public static class Builder { + public static final class Builder { private BedWarsDeathType deathType = BedWarsDeathType.GENERIC; private BedWarsPlayer victim; private BedWarsPlayer killer; @@ -84,6 +68,30 @@ public BedWarsDeathResult build() { if (victim == null) { throw new IllegalStateException("Victim must be set"); } + + switch (deathType) { + case VOID_ASSISTED, GENERIC_ASSISTED -> { + if (assistPlayer == null && killer == null) { + throw new IllegalStateException(deathType + " requires a credited player (assistPlayer or killer)"); + } + } + case BOW -> { + if (killer == null && assistPlayer == null) { + throw new IllegalStateException("BOW requires a credited player (killer or assistPlayer)"); + } + } + case ENTITY -> { + if (attackerEntity == null) { + throw new IllegalStateException("ENTITY requires attackerEntity"); + } + if (killer == null) { + throw new IllegalStateException("ENTITY requires killer"); + } + } + case VOID, GENERIC -> { + } + } + return new BedWarsDeathResult(deathType, victim, killer, assistPlayer, attackerEntity, weaponUsed, isFinalKill); } } @@ -92,4 +100,3 @@ public static Builder builder() { return new Builder(); } } - diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathType.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathType.java index 647204f83..da021290c 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathType.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/death/BedWarsDeathType.java @@ -4,53 +4,11 @@ @Getter public enum BedWarsDeathType { - PLAYER_MELEE(" was slain by "), - PLAYER_VOID_KNOCK(" was knocked into the void by "), - PLAYER_FALL_KNOCK(" was knocked off by "), - PLAYER_PROJECTILE(" was shot by "), - PLAYER_EXPLOSION(" was blown up by "), - PLAYER_FIRE(" was burned to death by "), - - VOID_ASSISTED(" was knocked into the void by "), - FALL_ASSISTED(" was knocked off by "), - - VOID(" fell into the void."), - FALL(" fell from a high place."), - FIRE(" burned to death."), - EXPLOSION(" blew up."), - - MOB_KILL(" was slain by "), - - GENERIC(" died."); - - private final String messageFormat; - - BedWarsDeathType(String messageFormat) { - this.messageFormat = messageFormat; - } - - public boolean involvesPlayer() { - return switch (this) { - case PLAYER_MELEE, PLAYER_VOID_KNOCK, PLAYER_FALL_KNOCK, PLAYER_PROJECTILE, - PLAYER_EXPLOSION, PLAYER_FIRE, VOID_ASSISTED, FALL_ASSISTED -> true; - default -> false; - }; - } - - public boolean isAssisted() { - return this == VOID_ASSISTED || this == FALL_ASSISTED; - } - - public boolean isDirectKill() { - return switch (this) { - case PLAYER_MELEE, PLAYER_VOID_KNOCK, PLAYER_FALL_KNOCK, - PLAYER_PROJECTILE, PLAYER_EXPLOSION, PLAYER_FIRE -> true; - default -> false; - }; - } - - public boolean isVoidDeath() { - return this == VOID || this == PLAYER_VOID_KNOCK || this == VOID_ASSISTED; - } + VOID, + VOID_ASSISTED, + GENERIC, + GENERIC_ASSISTED, + BOW, + ENTITY, } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/entity/TextDisplayEntity.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/entity/TextDisplayEntity.java index 87167918f..da76bdebb 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/entity/TextDisplayEntity.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/entity/TextDisplayEntity.java @@ -16,6 +16,7 @@ public TextDisplayEntity(Component text) { editEntityMeta(TextDisplayMeta.class, (meta) -> { meta.setText(text); meta.setBillboardRenderConstraints(AbstractDisplayMeta.BillboardConstraints.CENTER); + meta.setSeeThrough(true); }); } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionBlockBreakAnimation.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionBlockBreakAnimation.java new file mode 100644 index 000000000..6dfd7fe6b --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionBlockBreakAnimation.java @@ -0,0 +1,29 @@ +package net.swofty.type.bedwarsgame.events; + +import net.minestom.server.event.player.PlayerPacketOutEvent; +import net.minestom.server.network.packet.server.ServerPacket; +import net.minestom.server.network.packet.server.play.BlockBreakAnimationPacket; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class ActionBlockBreakAnimation implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false, isAsync = true) // should it be async? - ARI + public void run(PlayerPacketOutEvent event) { + BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); + BedWarsGame game = TypeBedWarsGameLoader.getGameById(player.getGameId()); + if (game == null || !game.getReplayManager().isRecording()) { + return; + } + + ServerPacket packet = event.getPacket(); + if (packet instanceof BlockBreakAnimationPacket p) { + game.getReplayManager().recordBlockBreakAnimation(p); + } + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionEntityAttack.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionEntityAttack.java index ec8123da2..07d63dc40 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionEntityAttack.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionEntityAttack.java @@ -1,10 +1,12 @@ package net.swofty.type.bedwarsgame.events; import net.minestom.server.entity.Entity; +import net.minestom.server.event.entity.EntityDamageEvent; import net.swofty.pvp.events.PrepareAttackEvent; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.item.impl.LuckyCombatEffects; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; @@ -15,13 +17,13 @@ public class ActionEntityAttack implements HypixelEventClass { @HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false) public void run(PrepareAttackEvent event) { if (event.getEntity() instanceof BedWarsPlayer player) { - Game game = player.getGame(); + BedWarsGame game = player.getGame(); if (game == null) { event.setCancelled(true); return; } - if (game.getGameStatus() != GameStatus.IN_PROGRESS) { + if (game.getState() != GameState.IN_PROGRESS) { event.setCancelled(true); return; } @@ -32,6 +34,28 @@ public void run(PrepareAttackEvent event) { return; } } + + if (game.isSameTeam(player.getUuid(), event.getTarget().getUuid())) { + player.sendMessage("§cYou cannot attack your teammate!"); + event.setCancelled(true); + return; + } + + LuckyCombatEffects.handle(player, event.getTarget()); + } + } + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void run(EntityDamageEvent event) { + if (event.getEntity() instanceof BedWarsPlayer player) { + BedWarsGame game = player.getGame(); + if (game == null) { + return; + } + + if (game.getState() == GameState.IN_PROGRESS) { + player.updateBelowTag(); + } } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameBreak.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameBreak.java index 59e52345c..3c0cbaf9c 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameBreak.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameBreak.java @@ -3,6 +3,7 @@ import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; import net.minestom.server.entity.ItemEntity; +import net.minestom.server.event.instance.InstanceBlockUpdateEvent; import net.minestom.server.event.player.PlayerBlockBreakEvent; import net.minestom.server.instance.block.Block; import net.minestom.server.item.ItemStack; @@ -11,10 +12,12 @@ import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.item.impl.LuckyBlockItem; import net.swofty.type.bedwarsgame.stats.BedWarsStatsRecorder; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; +import net.swofty.type.game.replay.dispatcher.BlockChangeDispatcher; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; @@ -24,72 +27,97 @@ public class ActionGameBreak implements HypixelEventClass { - @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = true) - public void run(PlayerBlockBreakEvent event) { - BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - Block blockBeingBroken = event.getBlock(); - - Game game = player.getGame(); - if (game == null || game.getGameStatus() != GameStatus.IN_PROGRESS) { - event.setCancelled(true); - return; - } - - boolean isTeamBedPart = false; - TeamKey playerTeamKey = player.getTeamKey(); - Point brokenBlockPosition = event.getBlockPosition(); - - // Check if it's a part of any team's bed first - for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { - TeamKey teamKey = entry.getKey(); - MapTeam team = entry.getValue(); - BedWarsMapsConfig.TwoBlockPosition bedPos = team.getBed(); - if (bedPos == null || bedPos.feet() == null || bedPos.head() == null) continue; - - Point feetPoint = new Pos(bedPos.feet().x(), bedPos.feet().y(), bedPos.feet().z()); - Point headPoint = new Pos(bedPos.head().x(), bedPos.head().y(), bedPos.head().z()); - - if (brokenBlockPosition.sameBlock(feetPoint) || brokenBlockPosition.sameBlock(headPoint)) { - // This is team X's bed - if (teamKey.equals(playerTeamKey)) { - player.getAchievementHandler().completeAchievement("bedwars.you_cant_do_that"); - player.sendMessage("§cYou cannot break your own team's bed!"); - event.setCancelled(true); - return; - } - if (!game.getTeamManager().isBedAlive(teamKey)) { - // Bed already destroyed logically; block might linger if not cleared perfectly - event.setCancelled(true); - return; - } - game.recordBedDestroyed(teamKey); - BedWarsStatsRecorder.recordBedBroken(player, game.getBedwarsGameType()); - player.getInstance().setBlock(feetPoint, Block.AIR); - player.getInstance().setBlock(headPoint, Block.AIR); - - if (player.hasEffect(PotionEffect.INVISIBILITY)) { - player.getAchievementHandler().completeAchievement("bedwars.sneaky_rusher"); // break an bed while invisible - } - - for (BedWarsPlayer p : game.getPlayers()) { - p.sendMessage(String.format("§c§lBED DESTRUCTION §r§cTeam %s's bed was destroyed by %s%s!", - teamKey.getName(), teamKey.chatColor(), player.getUsername())); - } - event.setCancelled(true); // handled the bed destruction and block removal - return; - } - } - - // If it's not a team bed part, then check if it's any other player-placed block - if (!isTeamBedPart) { - if (Boolean.TRUE.equals(blockBeingBroken.getTag(TypeBedWarsGameLoader.PLAYER_PLACED_TAG))) { - new ItemEntity(ItemStack.of(Objects.requireNonNull(blockBeingBroken.registry().material()))).setInstance(player.getInstance(), event.getBlockPosition()); - event.setCancelled(false); - } else { - // Not a team bed and not a player-placed block - player.sendMessage("§cYou can only break blocks placed by players!"); - event.setCancelled(true); - } - } - } + @HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false) + public void globalBlockChange(InstanceBlockUpdateEvent event) { + BedWarsGame game = TypeBedWarsGameLoader.getGameByInstance(event.getInstance()); + if (game == null || !game.getReplayManager().isRecording()) { + return; + } + + if (Boolean.TRUE.equals(event.getBlock().getTag(TypeBedWarsGameLoader.PLAYER_PLACED_TAG))) { + return; // Player placements are recorded in ActionGamePlace + } + + BlockChangeDispatcher blockDispatcher = + game.getReplayManager().getBlockChangeDispatcher(); + if (blockDispatcher != null) { + Block previousBlock = event.getInstance().getBlock(event.getBlockPosition()); + + blockDispatcher.recordBlockChange( + event.getBlockPosition().blockX(), + event.getBlockPosition().blockY(), + event.getBlockPosition().blockZ(), + previousBlock.stateId(), + event.getBlock().stateId() + ); + } + } + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = true) + public void blockBreak(PlayerBlockBreakEvent event) { + BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); + Block blockBeingBroken = event.getBlock(); + + BedWarsGame game = player.getGame(); + if (game == null || game.getState() != GameState.IN_PROGRESS) { + event.setCancelled(true); + return; + } + + boolean isTeamBedPart = false; + TeamKey playerTeamKey = player.getTeamKey(); + Point brokenBlockPosition = event.getBlockPosition(); + + if (LuckyBlockItem.handleBreak(player, brokenBlockPosition, blockBeingBroken)) { + event.setCancelled(true); + return; + } + + // Check if it's a part of any team's bed first + for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { + TeamKey teamKey = entry.getKey(); + MapTeam team = entry.getValue(); + BedWarsMapsConfig.TwoBlockPosition bedPos = team.getBed(); + if (bedPos == null || bedPos.feet() == null || bedPos.head() == null) continue; + + Point feetPoint = new Pos(bedPos.feet().x(), bedPos.feet().y(), bedPos.feet().z()); + Point headPoint = new Pos(bedPos.head().x(), bedPos.head().y(), bedPos.head().z()); + + if (brokenBlockPosition.sameBlock(feetPoint) || brokenBlockPosition.sameBlock(headPoint)) { + // This is team X's bed + if (teamKey.equals(playerTeamKey)) { + if (player.allowsPersistentProgress()) + player.getAchievementHandler().completeAchievement("bedwars.you_cant_do_that"); + player.sendMessage("§cYou can't destroy your own bed!"); + event.setCancelled(true); + return; + } + if (!game.isBedAlive(teamKey)) { + event.setCancelled(true); + return; + } + game.onBedDestroyed(teamKey, player); + BedWarsStatsRecorder.recordBedBroken(player, game.getGameType()); + + if (player.hasEffect(PotionEffect.INVISIBILITY) && player.isInvisible()) { + if (player.allowsPersistentProgress()) + player.getAchievementHandler().completeAchievement("bedwars.sneaky_rusher"); // break an bed while invisible + } + event.setCancelled(true); // handled the bed destruction and block removal + return; + } + } + + // If it's not a team bed part, then check if it's any other player-placed block + if (!isTeamBedPart) { + if (Boolean.TRUE.equals(blockBeingBroken.getTag(TypeBedWarsGameLoader.PLAYER_PLACED_TAG))) { + new ItemEntity(ItemStack.of(Objects.requireNonNull(blockBeingBroken.registry().material()))).setInstance(player.getInstance(), event.getBlockPosition()); + event.setCancelled(false); + } else { + // Not a team bed and not a player-placed block + player.sendMessage("§cYou can only break blocks placed by players!"); + event.setCancelled(true); + } + } + } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCombatTrack.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCombatTrack.java index c9bfa0323..fd46ae85c 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCombatTrack.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCombatTrack.java @@ -3,9 +3,9 @@ import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.pvp.events.FinalDamageEvent; import net.swofty.type.bedwarsgame.death.BedWarsCombatTracker; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; @@ -18,8 +18,8 @@ public void run(FinalDamageEvent event) { return; } - Game game = victim.getGame(); - if (game == null || game.getGameStatus() != GameStatus.IN_PROGRESS) { + BedWarsGame game = victim.getGame(); + if (game == null || game.getState() != GameState.IN_PROGRESS) { return; } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCustomItems.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCustomItems.java index 1f7fff373..ef874563a 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCustomItems.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameCustomItems.java @@ -6,18 +6,21 @@ import net.minestom.server.entity.EntityType; import net.minestom.server.event.entity.projectile.ProjectileCollideWithBlockEvent; import net.minestom.server.event.entity.projectile.ProjectileCollideWithEntityEvent; +import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.event.item.PlayerFinishItemUseEvent; import net.minestom.server.event.player.PlayerBlockPlaceEvent; import net.minestom.server.event.player.PlayerUseItemEvent; import net.minestom.server.event.player.PlayerUseItemOnBlockEvent; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.Block; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.pvp.projectile.entities.FireballProjectile; import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; @@ -39,8 +42,8 @@ private static void handleFireballExplosion(FireballProjectile fireball) { return; } - Game game = shooter.getGame(); - if (game == null || game.getGameStatus() != GameStatus.IN_PROGRESS) { + BedWarsGame game = shooter.getGame(); + if (game == null || game.getState() != GameState.IN_PROGRESS) { fireball.remove(); return; } @@ -109,6 +112,17 @@ public void run(PlayerFinishItemUseEvent event) { @HypixelEvent(node = EventNodes.ALL, requireDataLoaded = true) public void run(PlayerUseItemEvent event) { + if (event.getPlayer() instanceof BedWarsPlayer player + && player.getGame() != null + && player.getGame().getGameType().isOneBlock() + && player.getGame().getState() == GameState.IN_PROGRESS + && event.getItemStack().material() == Material.VILLAGER_SPAWN_EGG) { + event.setCancelled(true); + ItemStack held = event.getItemStack(); + player.setItemInMainHand(held.amount() > 1 ? held.withAmount(held.amount() - 1) : ItemStack.AIR); + player.getGame().getWorldManager().spawnTemporaryItemShop(player.getPosition()); + return; + } TypeBedWarsGameLoader.getItemHandler().onItemUse(event); } @@ -117,4 +131,10 @@ public void run(PlayerBlockPlaceEvent event) { TypeBedWarsGameLoader.getItemHandler().onBlockPlace(event); } + // InventoryClickItem + @HypixelEvent(node = EventNodes.ALL, requireDataLoaded = true) + public void run(InventoryPreClickEvent event) { + TypeBedWarsGameLoader.getItemHandler().onInventoryClick(event); + } + } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameDeath.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameDeath.java index 51e723331..2711550fd 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameDeath.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameDeath.java @@ -1,55 +1,50 @@ package net.swofty.type.bedwarsgame.events; import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.title.Title; -import net.kyori.adventure.title.TitlePart; -import net.minestom.server.MinecraftServer; import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.GameMode; +import net.minestom.server.coordinate.Vec; import net.minestom.server.event.player.PlayerDeathEvent; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; -import net.minestom.server.tag.Tag; -import net.minestom.server.timer.Task; -import net.minestom.server.timer.TaskSchedule; -import net.swofty.commons.ServerType; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.commons.mc.HypixelPosition; import net.swofty.type.bedwarsgame.death.BedWarsCombatTracker; import net.swofty.type.bedwarsgame.death.BedWarsDeathHandler; import net.swofty.type.bedwarsgame.death.BedWarsDeathResult; import net.swofty.type.bedwarsgame.death.BedWarsDeathType; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.shop.impl.AxeShopItem; import net.swofty.type.bedwarsgame.shop.impl.PickaxeShopItem; import net.swofty.type.bedwarsgame.stats.BedWarsStatsRecorder; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; -import org.tinylog.Logger; +import net.swofty.type.generic.utility.ScheduleUtility; -import java.time.Duration; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; public class ActionGameDeath implements HypixelEventClass { - @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) public void run(PlayerDeathEvent event) { BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - Game game = player.getGame(); - if (game == null || game.getGameStatus() != GameStatus.IN_PROGRESS) { + BedWarsGame game = player.getGame(); + if (game == null || game.getState() != GameState.IN_PROGRESS) { return; } + death(player, game, event::setChatMessage, false); + } + + public static void death(BedWarsPlayer player, BedWarsGame game, Consumer deathMessageConsumer, boolean voidDeath) { + HypixelPosition position = game.getMapEntry().getConfiguration().getLocations().getSpectator(); + player.setVelocity(Vec.ZERO); // Stop any momentum the player had before death + player.teleport(new Pos(position.x(), position.y(), position.z())); + BedWarsGame.literalSetupSpectator(player); + Integer pickaxeLevel = player.getTag(PickaxeShopItem.PICKAXE_UPGRADE_TAG); if (pickaxeLevel != null && pickaxeLevel > 1) { player.setTag(PickaxeShopItem.PICKAXE_UPGRADE_TAG, pickaxeLevel - 1); @@ -78,168 +73,89 @@ public void run(PlayerDeathEvent event) { } } - BedWarsDeathResult deathResult = BedWarsDeathHandler.calculateDeath(player, game); + BedWarsDeathResult deathResult = BedWarsDeathHandler.calculateDeath(player, game, voidDeath); if (deathResult.deathType() == BedWarsDeathType.VOID) { - player.getAchievementHandler().completeAchievement("bedwars.its_dark_down_there"); + if (player.allowsPersistentProgress()) + player.getAchievementHandler().completeAchievement("bedwars.its_dark_down_there"); } if (deathResult.isFinalKill()) { - BedWarsStatsRecorder.recordFinalDeath(player, game.getBedwarsGameType()); - } - - BedWarsPlayer itemRecipient = deathResult.getKillCreditPlayer(); - if (itemRecipient != null) { - if (iron > 0) { - itemRecipient.getInventory().addItemStack(ItemStack.of(Material.IRON_INGOT, iron)); - itemRecipient.sendMessage("§f+ " + iron + " iron"); - } - if (gold > 0) { - itemRecipient.getInventory().addItemStack(ItemStack.of(Material.GOLD_INGOT, gold)); - itemRecipient.sendMessage("§e+ " + gold + " gold"); - } - if (diamonds > 0) { - itemRecipient.getInventory().addItemStack(ItemStack.of(Material.DIAMOND, diamonds)); - itemRecipient.sendMessage("§b+ " + diamonds + " diamond"); - } - if (emeralds > 0) { - itemRecipient.getInventory().addItemStack(ItemStack.of(Material.EMERALD, emeralds)); - itemRecipient.sendMessage("§a+ " + emeralds + " emerald"); - } + BedWarsStatsRecorder.recordFinalDeath(player, game.getGameType()); } TeamKey teamKey = player.getTeamKey(); - boolean bedExists = teamKey != null && game.getTeamManager().isBedAlive(teamKey); + boolean bedExists = teamKey != null && game.isBedAlive(teamKey); Component deathMessage = BedWarsDeathHandler.createDeathMessage(deathResult); handleDeathTypeActions(deathResult, game); + deathMessageConsumer.accept(deathMessage); if (!bedExists && deathResult.getKillCreditPlayer() != null) { - BedWarsStatsRecorder.recordFinalKill(deathResult.getKillCreditPlayer(), game.getBedwarsGameType()); + BedWarsStatsRecorder.recordFinalKill(deathResult.getKillCreditPlayer(), game.getGameType()); } - event.setChatMessage(deathMessage); - BedWarsCombatTracker.clearCombatData(player); - player.setGameMode(GameMode.SPECTATOR); - player.getInventory().clear(); - - if (bedExists) { - final Title.Times titleTimes = Title.Times.times(Duration.ofMillis(100), Duration.ofSeconds(1), Duration.ofMillis(100)); - final AtomicInteger countdown = new AtomicInteger(5); - final AtomicReference taskRef = new AtomicReference<>(); - final Task task = MinecraftServer.getSchedulerManager().buildTask(() -> { - if (!player.isOnline()) { - return; + final int finalIron = iron; + final int finalGold = gold; + final int finalDiamonds = diamonds; + final int finalEmeralds = emeralds; + ScheduleUtility.nextTick(() -> { + BedWarsPlayer itemRecipient = deathResult.getKillCreditPlayer(); + if (itemRecipient != null) { + if (finalIron > 0) { + itemRecipient.getInventory().addItemStack(ItemStack.of(Material.IRON_INGOT, finalIron)); + itemRecipient.sendMessage("§f+" + finalIron + " Iron"); } - - int secondsRemaining = countdown.getAndDecrement(); - - if (secondsRemaining > 0) { - Component mainTitleText = Component.text("YOU DIED!", NamedTextColor.RED); - Component subTitleText = Component.text("You will respawn in " + secondsRemaining + " second" + (secondsRemaining == 1 ? "" : "s") + "!", NamedTextColor.YELLOW); - Title title = Title.title(mainTitleText, subTitleText, titleTimes); - player.showTitle(title); - } else { - // Time to respawn - player.clearTitle(); - - MapTeam playerTeam = game.getMapEntry().getConfiguration().getTeams().get(teamKey); - - if (playerTeam != null) { - BedWarsMapsConfig.PitchYawPosition spawnPos = playerTeam.getSpawn(); - player.teleport(new Pos(spawnPos.x(), spawnPos.y(), spawnPos.z(), spawnPos.pitch(), spawnPos.yaw())); - player.setGameMode(GameMode.SURVIVAL); - player.setInvisible(false); - player.setFlying(false); - player.getInventory().addItemStack(ItemStack.of(Material.WOODEN_SWORD)); - - // Give back the downgraded tools - AxeShopItem axeShopItem = new AxeShopItem(); - Integer currentAxeLevel = player.getTag(AxeShopItem.AXE_UPGRADE_TAG); - if (currentAxeLevel != null && currentAxeLevel > 0) { - player.getInventory().addItemStack(ItemStack.of(axeShopItem.getTier(currentAxeLevel - 1).material())); - } - - PickaxeShopItem pickaxeShopItem = new PickaxeShopItem(); - Integer currentPickaxeLevel = player.getTag(PickaxeShopItem.PICKAXE_UPGRADE_TAG); - if (currentPickaxeLevel != null && currentPickaxeLevel > 0) { - player.getInventory().addItemStack(ItemStack.of(pickaxeShopItem.getTier(currentPickaxeLevel - 1).material())); - } - - // equip the player with team armor - game.getTeamManager().equipTeamArmor(player, teamKey); - - Integer protectionLevel = player.getTag(Tag.Integer("upgrade_reinforced_armor")); - if (protectionLevel != null) { - TypeBedWarsGameLoader.getTeamShopManager().getUpgrade("reinforced_armor").applyEffect(game, teamKey, protectionLevel); - } - - Integer cushionedBootsLevel = player.getTag(Tag.Integer("upgrade_cushioned_boots")); - if (cushionedBootsLevel != null) { - TypeBedWarsGameLoader.getTeamShopManager().getUpgrade("cushioned_boots").applyEffect(game, teamKey, cushionedBootsLevel); - } - - Integer sharpnessLevel = player.getTag(Tag.Integer("upgrade_sharpness")); - if (sharpnessLevel != null) { - TypeBedWarsGameLoader.getTeamShopManager().getUpgrade("sharpness").applyEffect(game, teamKey, sharpnessLevel); - } - - - } else { - Logger.warn("Player {} had team key '{}' but team was not found. Sending to lobby.", player.getUsername(), teamKey.getName()); - player.sendMessage("§cAn unexpected error occurred while respawning you. Please contact a staff member."); - player.sendTo(ServerType.BEDWARS_LOBBY); - } - - // if (game != null && teamName != null) game.notifyPlayerOrBedStateChanged(teamName); - - // cancel repeating task - Task currentTask = taskRef.get(); - if (currentTask != null) { - currentTask.cancel(); - } + if (finalGold > 0) { + itemRecipient.getInventory().addItemStack(ItemStack.of(Material.GOLD_INGOT, finalGold)); + itemRecipient.sendMessage("§6+" + finalGold + " Gold"); + } + if (finalDiamonds > 0) { + itemRecipient.getInventory().addItemStack(ItemStack.of(Material.DIAMOND, finalDiamonds)); + itemRecipient.sendMessage("§b+" + finalDiamonds + " Diamond"); } - }).repeat(TaskSchedule.seconds(1)).schedule(); - taskRef.set(task); + if (finalEmeralds > 0) { + itemRecipient.getInventory().addItemStack(ItemStack.of(Material.EMERALD, finalEmeralds)); + itemRecipient.sendMessage("§3+" + finalEmeralds + " Emerald"); + } + } + }); + + if (bedExists) { + game.getRespawnHandler().startRespawn(player); } else { - // Final kill - no bed - player.sendTitlePart(TitlePart.TITLE, Component.text("YOU DIED!", NamedTextColor.RED, TextDecoration.BOLD)); - player.sendTitlePart(TitlePart.SUBTITLE, Component.text("You will not respawn.", NamedTextColor.GRAY)); + // Final kill if the bed doesn't exist player.getInventory().clear(); - - player.setGameMode(GameMode.SPECTATOR); - player.setInvisible(true); - player.setFlying(true); - - if (game != null) { - game.playerEliminated(player); - } + game.onPlayerEliminated(player); } } - private void handleDeathTypeActions(BedWarsDeathResult result, Game game) { + private static void handleDeathTypeActions(BedWarsDeathResult result, BedWarsGame game) { BedWarsPlayer victim = result.victim(); - BedWarsPlayer killer = result.killer(); - BedWarsPlayer assistPlayer = result.assistPlayer(); + BedWarsPlayer creditPlayer = result.getKillCreditPlayer(); - if (killer != null) { - BedWarsStatsRecorder.recordKill(killer, game.getBedwarsGameType()); - } else if (assistPlayer != null) { - BedWarsStatsRecorder.recordKill(assistPlayer, game.getBedwarsGameType()); + if (creditPlayer != null) { + BedWarsStatsRecorder.recordKill(creditPlayer, game.getGameType()); } - BedWarsStatsRecorder.recordDeath(victim, game.getBedwarsGameType()); + BedWarsStatsRecorder.recordDeath(victim, game.getGameType()); - if (result.isFinalKill()) { - if (killer != null) killer.getAchievementHandler().addProgress("bedwars.bed_wars_killer", 1); + if (creditPlayer != null) { + game.getReplayManager().recordKill(creditPlayer, victim, result.deathType(), result.isFinalKill()); + } + + if (result.isFinalKill() && creditPlayer != null) { + if (creditPlayer.allowsPersistentProgress()) + creditPlayer.getAchievementHandler().addProgress("bedwars.bed_wars_killer", 1); } - BedWarsPlayer creditPlayer = result.getKillCreditPlayer(); if (creditPlayer != null && result.weaponUsed() != null) { if (result.weaponUsed() == Material.SHEARS) { - creditPlayer.getAchievementHandler().completeAchievement("bedwars.shear_luck"); + if (creditPlayer.allowsPersistentProgress()) + creditPlayer.getAchievementHandler().completeAchievement("bedwars.shear_luck"); } else if (result.weaponUsed() == Material.STICK) { - creditPlayer.getAchievementHandler().addProgressByTrigger("bedwars.knockback_void_kill", 1); + if (creditPlayer.allowsPersistentProgress()) + creditPlayer.getAchievementHandler().addProgressByTrigger("bedwars.knockback_void_kill", 1); } } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameMove.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameMove.java index 5a272d88b..355686a92 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameMove.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGameMove.java @@ -2,17 +2,17 @@ import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.Player; -import net.minestom.server.entity.damage.Damage; -import net.minestom.server.entity.damage.DamageType; import net.minestom.server.event.player.PlayerMoveEvent; import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.item.impl.LuckyBlockTrap; +import net.swofty.type.bedwarsgame.item.impl.LuckyEquipmentEffects; +import net.swofty.type.bedwarsgame.shop.TrapId; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; @@ -30,18 +30,13 @@ public void run(PlayerMoveEvent event) { return; } - Game game = player.getGame(); - if (game == null || game.getGameStatus() != GameStatus.IN_PROGRESS) { + BedWarsGame game = player.getGame(); + if (game == null || game.getState() != GameState.IN_PROGRESS) { return; } if (player.getPosition().y() <= 0) { - if (player.getLastDamageSource() != null && player.getLastDamageSource().getSource() instanceof Player p) { - player.damage(Damage.fromPlayer(p, 1.0f)); - } else { - player.damage(Damage.fromPosition(DamageType.OUT_OF_WORLD, player.getPosition(), 1.0f)); - } - player.kill(); + ActionGameDeath.death(player, game, game::broadcastMessage, true); return; } @@ -50,7 +45,17 @@ public void run(PlayerMoveEvent event) { return; } + LuckyEquipmentEffects.tick(player); + Point playerPos = player.getPosition(); + Point trapPos = new Pos(playerPos.blockX(), playerPos.blockY(), playerPos.blockZ()); + if (LuckyBlockTrap.trigger(player, trapPos, player.getInstance().getBlock(trapPos))) { + return; + } + Point belowTrapPos = new Pos(playerPos.blockX(), playerPos.blockY() - 1, playerPos.blockZ()); + if (LuckyBlockTrap.trigger(player, belowTrapPos, player.getInstance().getBlock(belowTrapPos))) { + return; + } // check what team this is for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { @@ -69,7 +74,7 @@ public void run(PlayerMoveEvent event) { Point bedLocation = new Pos(bedPos.feet().x(), bedPos.feet().y(), bedPos.feet().z()); if (playerPos.distance(bedLocation) <= 10) { - List teamTraps = game.getTeamManager().getTeamTraps(teamKey); + List teamTraps = game.getTeamTraps(teamKey); if (teamTraps.isEmpty()) { continue; } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePickup.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePickup.java index 4d557a9bb..d033d7f38 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePickup.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePickup.java @@ -1,10 +1,10 @@ package net.swofty.type.bedwarsgame.events; import net.minestom.server.component.DataComponents; -import net.minestom.server.entity.GameMode; import net.minestom.server.event.item.PickupItemEvent; import net.minestom.server.item.ItemStack; import net.minestom.server.item.component.CustomData; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.shop.Currency; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; import net.swofty.type.bedwarsgame.user.ExperienceCause; @@ -19,12 +19,21 @@ public class ActionGamePickup implements HypixelEventClass { public void run(PickupItemEvent event) { ItemStack itemStack = event.getItemEntity().getItemStack(); if (event.getLivingEntity() instanceof BedWarsPlayer player) { - // Only allow players on survival mode to pickup items - if (player.getGameMode() != GameMode.SURVIVAL) { + BedWarsGame game = player.getGame(); + if (!game.isPlayerCurrentlyPlaying(player.getUuid())) { event.setCancelled(true); return; } + // Record item pickup to replay + if (game != null && game.getReplayManager().isRecording()) { + game.getReplayManager().recordItemPickup( + event.getItemEntity().getEntityId(), + player.getEntityId() + ); + game.getReplayManager().recordEntityDespawn(event.getItemEntity().getEntityId()); + } + player.getInventory().addItemStack(itemStack); // handle bedwars xp for diamonds and emeralds diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlace.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlace.java index fb8034568..f6797e14e 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlace.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlace.java @@ -7,17 +7,18 @@ import net.minestom.server.instance.block.Block; import net.minestom.server.item.Material; import net.minestom.server.sound.SoundEvent; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; +import net.swofty.commons.mc.HypixelPosition; import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; import net.swofty.type.bedwarsgame.entity.TntEntity; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; +import net.swofty.type.game.replay.dispatcher.BlockChangeDispatcher; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; -import net.swofty.type.generic.utility.MathUtility; +import net.swofty.type.generic.utility.ScheduleUtility; import org.tinylog.Logger; public class ActionGamePlace implements HypixelEventClass { @@ -25,27 +26,32 @@ public class ActionGamePlace implements HypixelEventClass { @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) public void run(PlayerBlockPlaceEvent event) { BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - Game game = player.getGame(); + BedWarsGame game = player.getGame(); if (game == null) { Logger.info("Player {} tried to place a block but is not in a game!", player.getUsername()); event.setCancelled(true); // Prevent placing if not in a game return; } + if (!game.isPlayerCurrentlyPlaying(player.getUuid())) { + event.setCancelled(true); + return; + } + if (event.getBlockPosition().y() >= 105) { player.sendMessage("§cYou cannot place blocks this high!"); event.setCancelled(true); return; } - if (game.getGameStatus() != GameStatus.IN_PROGRESS) { + if (game.getState() != GameState.IN_PROGRESS) { event.setCancelled(true); return; } Point blockPosition = event.getBlockPosition(); for (MapTeam team : game.getMapEntry().getConfiguration().getTeams().values()) { - BedWarsMapsConfig.PitchYawPosition spawnPos = team.getSpawn(); + HypixelPosition spawnPos = team.getSpawn(); if (spawnPos != null) { Point spawnPoint = new Pos(spawnPos.x(), spawnPos.y(), spawnPos.z()); if (blockPosition.distance(spawnPoint) <= 6) { @@ -64,15 +70,30 @@ public void run(PlayerBlockPlaceEvent event) { SoundEvent.ENTITY_TNT_PRIMED, Sound.Source.BLOCK, 1.0f, 1.0f ), entity); - MathUtility.delay( - () -> player.getInstance().setBlock(blockPosition, Block.AIR), - 3 + ScheduleUtility.nextTick( + () -> player.getInstance().setBlock(blockPosition, Block.AIR) ); return; } - event.setBlock(event.getBlock().withTag(TypeBedWarsGameLoader.PLAYER_PLACED_TAG, true)); - player.getAchievementHandler().addProgressByTrigger("bedwars.blocks_placed", 1); + Block placedBlock = event.getBlock().withTag(TypeBedWarsGameLoader.PLAYER_PLACED_TAG, true); + if (game.getReplayManager().isRecording()) { + BlockChangeDispatcher blockDispatcher = game.getReplayManager().getBlockChangeDispatcher(); + if (blockDispatcher != null) { + Block previousBlock = event.getInstance().getBlock(blockPosition); + blockDispatcher.recordBlockChange( + blockPosition.blockX(), + blockPosition.blockY(), + blockPosition.blockZ(), + previousBlock.stateId(), + placedBlock.stateId() + ); + } + } + event.setBlock(placedBlock); + if (player.allowsPersistentProgress()) { + player.getAchievementHandler().addProgressByTrigger("bedwars.blocks_placed", 1); + } } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlayerEvent.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlayerEvent.java index 0ee3904a3..c6bcd46bd 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlayerEvent.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionGamePlayerEvent.java @@ -10,15 +10,17 @@ import net.minestom.server.inventory.PlayerInventory; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.commons.StringUtility; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.gui.GUIEnderChest; import net.swofty.type.bedwarsgame.gui.GUITeamChest; +import net.swofty.type.bedwarsgame.shop.Currency; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; import net.swofty.type.bedwarsgame.util.BedWarsInventoryManipulator; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; @@ -30,245 +32,248 @@ public class ActionGamePlayerEvent implements HypixelEventClass { - public static final ConcurrentHashMap ACTIVE_TEAM_CHESTS = new ConcurrentHashMap<>(); - - @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) - public void run(InventoryPreClickEvent event) { - if (!(event.getInventory() instanceof PlayerInventory)) { - return; - } - BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - if (event.getClickedItem().material().isArmor()) { - event.setCancelled(true); - return; - } - Game game = player.getGame(); - if (game == null) { - event.setCancelled(true); - return; - } - - if (game.getGameStatus() == GameStatus.WAITING) { - event.setCancelled(true); - } - } - - @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) - public void run(ItemDropEvent event) { - switch (event.getItemStack().material().name()) { - case "wooden_sword": - case "wooden_pickaxe": - case "wooden_axe": - case "stone_axe": - case "iron_pickaxe": - case "iron_axe": - case "diamond_pickaxe": - case "diamond_axe": - event.setCancelled(true); - event.getPlayer().sendMessage("§cYou cannot drop your tools!"); - break; - default: - ItemEntity itemEntity = new ItemEntity(event.getItemStack()); - itemEntity.setInstance(event.getPlayer().getInstance(), event.getPlayer().getPosition().add(0, event.getPlayer().getEyeHeight(), 0)); - itemEntity.setVelocity(event.getPlayer().getPosition().add(0, 0.3, 0).direction().mul(6)); - itemEntity.setPickupDelay(Duration.ofMillis(500)); - break; - } - } - - @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false, isAsync = true) - public void run(PlayerBlockInteractEvent event) { - Block block = event.getBlock(); - BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - if (player.getGame() == null) { - event.setCancelled(true); - return; - } - if (block.registry().material() == Material.ENDER_CHEST) { - new GUIEnderChest().open(player); - return; - } - - if (block.registry().material() != Material.CHEST) return; - - Game game = player.getGame(); - if (game == null || game.getGameStatus() != GameStatus.IN_PROGRESS) { - event.setCancelled(true); - return; - } - - TeamKey playerTeamKey = player.getTeamKey(); - if (playerTeamKey == null) { - event.setCancelled(true); - return; - } - - double closestDistance = Double.MAX_VALUE; - TeamKey chestTeamKey = null; - - for (java.util.Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { - TeamKey teamKey = entry.getKey(); - MapTeam team = entry.getValue(); - BedWarsMapsConfig.PitchYawPosition teamSpawn = team.getSpawn(); - if (teamSpawn == null) continue; - - double distance = Math.sqrt( - Math.pow(event.getBlockPosition().x() - teamSpawn.x(), 2) + - Math.pow(event.getBlockPosition().y() - teamSpawn.y(), 2) + - Math.pow(event.getBlockPosition().z() - teamSpawn.z(), 2) - ); - - if (distance < 10.0 && distance < closestDistance) { - closestDistance = distance; - chestTeamKey = teamKey; - } - } - - if (chestTeamKey == null) { - return; - } - - boolean sameTeam = chestTeamKey.equals(playerTeamKey); - if (!sameTeam && game.getTeamManager().getTeamBedStatus().getOrDefault(chestTeamKey, false)) { - event.setCancelled(true); - player.sendMessage("§cYou can only access enemy team chests if their bed is destroyed!"); - return; - } - - String existingContextId = ACTIVE_TEAM_CHESTS.get(chestTeamKey); - GUITeamChest teamChest = new GUITeamChest(chestTeamKey); - - if (existingContextId != null) { - teamChest.joinSharedContext(player, existingContextId); - } else { - String contextId = teamChest.createSharedContext(player); - ACTIVE_TEAM_CHESTS.put(chestTeamKey, contextId); - } - } - - @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) - public void run(PlayerStartDiggingEvent event) { - Block block = event.getBlock(); - BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - ItemStack itemInHand = player.getItemInMainHand(); - - Game game = player.getGame(); - if (game == null || game.getGameStatus() != GameStatus.IN_PROGRESS) { - return; - } - - if (itemInHand.isAir()) { - if (block.registry().material() == Material.CHEST || block.registry().material() == Material.ENDER_CHEST) { - event.setCancelled(true); - } - return; - } - - if (block.registry().material() != Material.CHEST && - block.registry().material() != Material.ENDER_CHEST) { - return; - } - - if (!BedWarsInventoryManipulator.canBeChested(itemInHand.material())) { - player.sendMessage("§cYou cannot store this item in the chest!"); - event.setCancelled(true); - return; - } - - // Handle Ender Chest - if (block.registry().material() == Material.ENDER_CHEST) { - event.setCancelled(true); - try { - Map playerEnderChest = game.getEnderchests().computeIfAbsent(player, k -> new ConcurrentHashMap<>()); - boolean itemAdded = false; - for (int i = 0; i < 27; i++) { // Standard ender chest size - if (playerEnderChest.get(i) == null || playerEnderChest.get(i).isAir()) { - playerEnderChest.put(i, itemInHand); - itemAdded = true; - break; - } - } - - if (itemAdded) { - player.setItemInMainHand(ItemStack.AIR); - player.sendMessage("§7You deposited x" + itemInHand.amount() - + " " + itemInHand.material().name().toLowerCase().replace("_", " ") - + " into your ender chest."); - player.getAchievementHandler().addProgressByTrigger("bedwars.chest_deposit", 1); - } else { - player.sendMessage("§cYour ender chest is full!"); - } - } catch (Exception e) { - Logger.error("Failed to add item to ender chest for player {}: {}", player.getUsername(), e.getMessage()); - e.printStackTrace(); - player.sendMessage("§cFailed to add item to ender chest!"); - } - return; - } - - if (block.registry().material() == Material.CHEST) { - event.setCancelled(true); - - TeamKey playerTeamName = player.getTeamKey(); - if (playerTeamName == null) { - return; - } - - TeamKey chestTeamName = null; - double closestDistance = Double.MAX_VALUE; - - for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { - TeamKey teamKey = entry.getKey(); - MapTeam team = entry.getValue(); - BedWarsMapsConfig.PitchYawPosition teamSpawn = team.getSpawn(); - if (teamSpawn == null) continue; - - double distance = Math.sqrt( - Math.pow(event.getBlockPosition().x() - teamSpawn.x(), 2) + - Math.pow(event.getBlockPosition().y() - teamSpawn.y(), 2) + - Math.pow(event.getBlockPosition().z() - teamSpawn.z(), 2) - ); - - if (distance < 10.0 && distance < closestDistance) { - closestDistance = distance; - chestTeamName = teamKey; - } - } - - if (chestTeamName == null) { - event.setCancelled(false); - return; - } - - boolean sameTeam = chestTeamName.equals(playerTeamName); - if (!sameTeam && game.getTeamManager().getTeamBedStatus().getOrDefault(chestTeamName, false)) { - player.sendMessage(MiniMessage.miniMessage().deserialize("§cYou can only access enemy team chests if their bed is destroyed!")); - return; - } - - try { - Map teamChest = game.getChests().computeIfAbsent(chestTeamName, k -> new ConcurrentHashMap<>()); - boolean itemAdded = false; - for (int i = 0; i < 27; i++) { - if (teamChest.get(i) == null || teamChest.get(i).isAir()) { - teamChest.put(i, itemInHand); - itemAdded = true; - break; - } - } - - if (itemAdded) { - player.setItemInMainHand(ItemStack.AIR); - player.getAchievementHandler().addProgressByTrigger("bedwars.chest_deposit", 1); - } else { - player.sendMessage("§cThe team chest is full!"); - } - } catch (Exception e) { - Logger.error("Failed to add item to team chest for team {}: {}", chestTeamName, e); - e.printStackTrace(); - player.sendMessage("§cFailed to add item to chest!"); - } - } - } + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) + public void run(InventoryPreClickEvent event) { + if (!(event.getInventory() instanceof PlayerInventory)) { + return; + } + + BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); + if (event.getClickedItem().material().isArmor()) { + event.setCancelled(true); + return; + } + + BedWarsGame game = player.getGame(); + if (game == null) { + event.setCancelled(true); + return; + } + + if (game.getState() == GameState.WAITING) { + event.setCancelled(true); + } + } + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) + public void run(ItemDropEvent event) { + switch (event.getItemStack().material().name()) { + case "wooden_sword": + case "wooden_pickaxe": + case "wooden_axe": + case "stone_axe": + case "iron_pickaxe": + case "iron_axe": + case "diamond_pickaxe": + case "diamond_axe": + event.setCancelled(true); + event.getPlayer().sendMessage("§cYou cannot drop your tools!"); + break; + default: + ItemEntity itemEntity = new ItemEntity(event.getItemStack()); + itemEntity.setInstance(event.getPlayer().getInstance(), event.getPlayer().getPosition().add(0, event.getPlayer().getEyeHeight(), 0)); + itemEntity.setVelocity(event.getPlayer().getPosition().add(0, 0.3, 0).direction().mul(6)); + itemEntity.setPickupDelay(Duration.ofMillis(500)); + break; + } + } + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false, isAsync = true) + public void run(PlayerBlockInteractEvent event) { + Block block = event.getBlock(); + BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); + if (player.getGame() == null) { + event.setCancelled(true); + return; + } + if (block.registry().material() == Material.ENDER_CHEST) { + player.openView(new GUIEnderChest()); + return; + } + + if (block.registry().material() != Material.CHEST) return; + + BedWarsGame game = player.getGame(); + if (game == null || game.getState() != GameState.IN_PROGRESS) { + event.setCancelled(true); + return; + } + + TeamKey playerTeamKey = player.getTeamKey(); + if (playerTeamKey == null) { + event.setCancelled(true); + return; + } + + double closestDistance = Double.MAX_VALUE; + TeamKey chestTeamKey = null; + + for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { + TeamKey teamKey = entry.getKey(); + MapTeam team = entry.getValue(); + HypixelPosition teamSpawn = team.getSpawn(); + if (teamSpawn == null) continue; + + double distance = Math.sqrt( + Math.pow(event.getBlockPosition().x() - teamSpawn.x(), 2) + + Math.pow(event.getBlockPosition().y() - teamSpawn.y(), 2) + + Math.pow(event.getBlockPosition().z() - teamSpawn.z(), 2) + ); + + if (distance < 10.0 && distance < closestDistance) { + closestDistance = distance; + chestTeamKey = teamKey; + } + } + + if (chestTeamKey == null) { + return; + } + + boolean sameTeam = chestTeamKey.equals(playerTeamKey); + if (!sameTeam && game.isBedAlive(chestTeamKey)) { + event.setCancelled(true); + player.sendMessage("§cYou can only access enemy team chests if their bed is destroyed!"); + return; + } + + GUITeamChest.open(player, chestTeamKey); + } + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) + public void run(PlayerStartDiggingEvent event) { + Block block = event.getBlock(); + BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); + ItemStack itemInHand = player.getItemInMainHand(); + + BedWarsGame game = player.getGame(); + if (game == null || game.getState() != GameState.IN_PROGRESS) { + return; + } + + if (itemInHand.isAir()) { + if (block.registry().material() == Material.CHEST || block.registry().material() == Material.ENDER_CHEST) { + event.setCancelled(true); + } + return; + } + + if (block.registry().material() != Material.CHEST && + block.registry().material() != Material.ENDER_CHEST) { + return; + } + + if (!BedWarsInventoryManipulator.canBeChested(itemInHand.material())) { + player.sendMessage("§cYou cannot store this item in the chest!"); + event.setCancelled(true); + return; + } + + // Handle Ender Chest + if (block.registry().material() == Material.ENDER_CHEST) { + event.setCancelled(true); + try { + Map playerEnderChest = game.getEnderChests().computeIfAbsent(player.getUuid(), k -> new ConcurrentHashMap<>()); + boolean itemAdded = false; + for (int i = 0; i < 27; i++) { // Standard ender chest size + if (playerEnderChest.get(i) == null || playerEnderChest.get(i).isAir()) { + playerEnderChest.put(i, itemInHand); + itemAdded = true; + break; + } + } + + if (itemAdded) { + player.setItemInMainHand(ItemStack.AIR); + player.sendMessage(depositMessage(itemInHand, true)); + if (player.allowsPersistentProgress()) + player.getAchievementHandler().addProgressByTrigger("bedwars.chest_deposit", 1); + } else { + player.sendMessage("§cYour ender chest is full!"); + } + } catch (Exception e) { + Logger.error("Failed to add item to ender chest for player {}: {}", player.getUsername(), e.getMessage()); + e.printStackTrace(); + player.sendMessage("§cFailed to add item to ender chest!"); + } + return; + } + + if (block.registry().material() == Material.CHEST) { + event.setCancelled(true); + + TeamKey playerTeamName = player.getTeamKey(); + if (playerTeamName == null) { + return; + } + + TeamKey chestTeamName = null; + double closestDistance = Double.MAX_VALUE; + + for (Map.Entry entry : game.getMapEntry().getConfiguration().getTeams().entrySet()) { + TeamKey teamKey = entry.getKey(); + MapTeam team = entry.getValue(); + HypixelPosition teamSpawn = team.getSpawn(); + if (teamSpawn == null) continue; + + double distance = Math.sqrt( + Math.pow(event.getBlockPosition().x() - teamSpawn.x(), 2) + + Math.pow(event.getBlockPosition().y() - teamSpawn.y(), 2) + + Math.pow(event.getBlockPosition().z() - teamSpawn.z(), 2) + ); + + if (distance < 10.0 && distance < closestDistance) { + closestDistance = distance; + chestTeamName = teamKey; + } + } + + if (chestTeamName == null) { + event.setCancelled(false); + return; + } + + boolean sameTeam = chestTeamName.equals(playerTeamName); + if (!sameTeam && game.isBedAlive(chestTeamName)) { + player.sendMessage(MiniMessage.miniMessage().deserialize("§cYou can only access enemy team chests if their bed is destroyed!")); + return; + } + + try { + Map teamChest = game.getTeamChests().computeIfAbsent(chestTeamName, k -> new ConcurrentHashMap<>()); + boolean itemAdded = false; + for (int i = 0; i < 27; i++) { + if (teamChest.get(i) == null || teamChest.get(i).isAir()) { + teamChest.put(i, itemInHand); + itemAdded = true; + break; + } + } + + if (itemAdded) { + player.sendMessage(depositMessage(itemInHand, false)); + player.setItemInMainHand(ItemStack.AIR); + if (player.allowsPersistentProgress()) + player.getAchievementHandler().addProgressByTrigger("bedwars.chest_deposit", 1); + } else { + player.sendMessage("§cThe team chest is full!"); + } + } catch (Exception e) { + Logger.error("Failed to add item to team chest for team {}: {}", chestTeamName, e); + e.printStackTrace(); + player.sendMessage("§cFailed to add item to chest!"); + } + } + } + + private String depositMessage(ItemStack itemStack, boolean enderChest) { + String chestType = enderChest ? "§dEnder Chest§7" : "§dTeam Chest§7"; + Currency currency = Currency.byMaterial(itemStack.material()); + String itemName = StringUtility.capitalizeSentence(itemStack.material().name().toLowerCase().replace("minecraft:", "").replace("_", " ")); + if (currency != null) { + return "§7Deposited " + currency.getColor() + "x" + itemStack.amount() + " " + itemName + "§7 into " + chestType + "! §8(?? Total)"; + } + return "§7Deposited §fx" + itemStack.amount() + " " + itemName + " §7into " + chestType + "! §8(?? Total)"; + } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionItemDropped.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionItemDropped.java new file mode 100644 index 000000000..58ca98a54 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionItemDropped.java @@ -0,0 +1,25 @@ +package net.swofty.type.bedwarsgame.events; + +import net.minestom.server.entity.ItemEntity; +import net.minestom.server.event.entity.EntitySpawnEvent; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class ActionItemDropped implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.ALL, requireDataLoaded = false, isAsync = false) + public void run(EntitySpawnEvent event) { + if (event.getEntity() instanceof ItemEntity itemEntity) { + BedWarsGame game = TypeBedWarsGameLoader.getGameByInstance(event.getInstance()); + if (game == null) return; + + if (!game.getReplayManager().isRecording()) return; + + game.getReplayManager().recordDroppedItem(itemEntity); + } + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerArmSwing.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerArmSwing.java new file mode 100644 index 000000000..adc8236c2 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerArmSwing.java @@ -0,0 +1,33 @@ +package net.swofty.type.bedwarsgame.events; + +import net.minestom.server.event.player.PlayerHandAnimationEvent; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class ActionPlayerArmSwing implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) + public void run(PlayerHandAnimationEvent event) { + if (!(event.getPlayer() instanceof BedWarsPlayer player)) { + return; + } + + BedWarsGame game = player.getGame(); + if (game == null || game.getReplayManager() == null) { + return; + } + + if (!game.getReplayManager().isRecording()) { + return; + } + + var dispatcher = game.getReplayManager().getEntityLifecycleDispatcher(); + if (dispatcher != null) { + boolean mainHand = event.getHand().name().equals("MAIN"); + dispatcher.recordArmSwing(player.getEntityId(), mainHand); + } + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerChat.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerChat.java index a1eba9d36..c73ebf4d4 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerChat.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerChat.java @@ -1,15 +1,12 @@ package net.swofty.type.bedwarsgame.events; import net.minestom.server.event.player.PlayerChatEvent; -import net.swofty.commons.bedwars.BedwarsGameType; -import net.swofty.commons.bedwars.BedwarsLevelColor; -import net.swofty.commons.bedwars.BedwarsLevelUtil; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.commons.bedwars.BedWarsGameType; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; import net.swofty.type.generic.chat.StaffChat; +import net.swofty.type.generic.collectibles.bedwars.prestige.BedWarsPrestigeRenderer; import net.swofty.type.generic.data.datapoints.DatapointChatType; -import net.swofty.type.generic.data.datapoints.DatapointLeaderboardLong; import net.swofty.type.generic.data.handlers.BedWarsDataHandler; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; @@ -17,6 +14,7 @@ import net.swofty.type.generic.party.PartyManager; import net.swofty.type.generic.user.categories.Rank; +import java.util.ArrayList; import java.util.List; public class ActionPlayerChat implements HypixelEventClass { @@ -26,7 +24,7 @@ public void run(PlayerChatEvent event) { final BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); event.setCancelled(true); - Game game = player.getGame(); + BedWarsGame game = player.getGame(); if (game == null) return; BedWarsDataHandler bedWarsDataHandler = BedWarsDataHandler.getUser(player); @@ -66,30 +64,27 @@ public void run(PlayerChatEvent event) { return; } - if (game.getGameStatus() == GameStatus.WAITING) { + if (game.getState().isWaiting()) { String textColor = rank.equals(Rank.DEFAULT) ? "§7" : "§f"; - game.getPlayers().forEach(onlinePlayer -> { - onlinePlayer.sendMessage(rank.getPrefix() + player.getUsername() + textColor + ": " + finalMessage); - }); + game.getPlayers().forEach(onlinePlayer -> onlinePlayer.sendMessage(player.getLegacyRankPrefix() + player.getUsername() + textColor + ": " + finalMessage)); return; } + if (game.getReplayManager().isRecording()) { + game.getReplayManager().recordPlayerChat(player, finalMessage, false); + } + List receivers; - if (game.getBedwarsGameType() == BedwarsGameType.SOLO) { - receivers = game.getPlayers(); + if (game.getGameType() == BedWarsGameType.ONE_EIGHT || game.getGameType() == BedWarsGameType.ONE_BLOCK) { + receivers = new ArrayList<>(game.getPlayers()); } else { - receivers = game.getTeamManager().getPlayersOnTeam(player.getTeamKey()).stream().map(p -> (BedWarsPlayer) p).toList(); + receivers = game.getPlayersOnTeam(player.getTeamKey()); } - String levelPrefix = BedwarsLevelColor.constructLevelBrackets( - BedwarsLevelUtil.calculateLevel(bedWarsDataHandler.get(BedWarsDataHandler.Data.EXPERIENCE, DatapointLeaderboardLong.class).getValue()) - ) + " "; + String levelPrefix = BedWarsPrestigeRenderer.renderBrackets(player) + " "; String textColor = rank.equals(Rank.DEFAULT) ? "§7" : "§f"; - receivers.forEach(onlinePlayer -> { - onlinePlayer.sendMessage(levelPrefix + rank.getPrefix() + player.getUsername() + textColor + ": " + finalMessage); - }); + receivers.forEach(onlinePlayer -> onlinePlayer.sendMessage(levelPrefix + player.getLegacyRankPrefix() + player.getUsername() + textColor + ": " + finalMessage)); } } - diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDataSpawn.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDataSpawn.java index 4b8d9a8e0..d00d8a597 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDataSpawn.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDataSpawn.java @@ -1,9 +1,8 @@ package net.swofty.type.bedwarsgame.events; -import net.minestom.server.entity.EntityType; import net.minestom.server.event.player.PlayerSpawnEvent; -import net.swofty.pvp.projectile.BowModule; -import net.swofty.pvp.projectile.entities.ArrowProjectile; +import net.swofty.commons.bedwars.BedwarsLevelUtil; +import net.swofty.type.generic.data.datapoints.DatapointLeaderboardLong; import net.swofty.type.generic.data.handlers.BedWarsDataHandler; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; @@ -12,15 +11,21 @@ public class ActionPlayerDataSpawn implements HypixelEventClass { - @HypixelEvent(node = EventNodes.PLAYER_DATA, requireDataLoaded = false, isAsync = true) - public void run(PlayerSpawnEvent event) { - if (!event.isFirstSpawn()) return; - final HypixelPlayer player = (HypixelPlayer) event.getPlayer(); + @HypixelEvent(node = EventNodes.PLAYER_DATA, requireDataLoaded = false, isAsync = true) + public void run(PlayerSpawnEvent event) { + if (!event.isFirstSpawn()) return; + final HypixelPlayer player = (HypixelPlayer) event.getPlayer(); - BedWarsDataHandler handler = BedWarsDataHandler.getUser(player.getUuid()); - handler.runOnLoad(player); + BedWarsDataHandler handler = BedWarsDataHandler.getUser(player.getUuid()); + handler.runOnLoad(player); - // Registers the bow module, which creates event nodes for the player for bow behavior - new BowModule(player.eventNode(), (p, i) -> new ArrowProjectile(EntityType.ARROW, p)); - } + DatapointLeaderboardLong dp = handler.get(BedWarsDataHandler.Data.EXPERIENCE, DatapointLeaderboardLong.class); + player.setLevel(BedwarsLevelUtil.calculateLevel(dp.getValue())); + player.setExp((float) BedwarsLevelUtil.calculateExperienceSinceLastLevel(dp.getValue()) / BedwarsLevelUtil.calculateMaxExperienceFromExperience(dp.getValue())); + + // should be handled in BedWarsPlayer + //List players = HypixelGenericLoader.getLoadedPlayers(); + //Collection playerCollection = players.stream().map(p -> (Player) p).toList(); + //PacketSendingUtils.sendGroupedPacket(playerCollection, new PlayerInfoRemovePacket(player.getUuid())); + } } \ No newline at end of file diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDisconnect.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDisconnect.java index c266a5140..e761bdf74 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDisconnect.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerDisconnect.java @@ -3,9 +3,9 @@ import lombok.SneakyThrows; import net.minestom.server.event.player.PlayerDisconnectEvent; import net.swofty.type.bedwarsgame.BedWarsGameScoreboard; -import net.swofty.type.bedwarsgame.game.Game; -import net.swofty.type.bedwarsgame.game.GameStatus; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; @@ -16,9 +16,9 @@ public class ActionPlayerDisconnect implements HypixelEventClass { @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) public void run(PlayerDisconnectEvent event) { final BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - Game game = player.getGame(); + BedWarsGame game = player.getGame(); if (game != null) { - if (game.getGameStatus() == GameStatus.IN_PROGRESS) { + if (game.getState() == GameState.IN_PROGRESS) { game.handleDisconnect(player); } else { game.leave(player); diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerInventory.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerInventory.java new file mode 100644 index 000000000..b5985d6a7 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerInventory.java @@ -0,0 +1,65 @@ +package net.swofty.type.bedwarsgame.events; + +import net.minestom.server.entity.Player; +import net.minestom.server.event.inventory.InventoryItemChangeEvent; +import net.minestom.server.event.player.PlayerChangeHeldSlotEvent; +import net.minestom.server.inventory.PlayerInventory; +import net.minestom.server.utils.inventory.PlayerInventoryUtils; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class ActionPlayerInventory implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) + public void changeHeldSlot(PlayerChangeHeldSlotEvent event) { + BedWarsGame game = TypeBedWarsGameLoader.getGameByInstance(event.getInstance()); + if (game == null || game.getReplayManager() == null) { + return; + } + if (!game.getReplayManager().isRecording()) { + return; + } + + var dispatcher = game.getReplayManager().getEntityLifecycleDispatcher(); + if (dispatcher != null) { + dispatcher.recordHeldItem(event.getPlayer().getEntityId(), event.getItemInNewSlot()); + } + } + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) + public void changeEquipment(InventoryItemChangeEvent event) { + if (!(event.getInventory() instanceof PlayerInventory)) { + return; + } + + Player player = event.getInventory().getViewers().stream().findFirst().orElseThrow(); + BedWarsGame game = TypeBedWarsGameLoader.getGameByInstance(player.getInstance()); + if (game == null || game.getReplayManager() == null) { + return; + } + if (!game.getReplayManager().isRecording()) { + return; + } + + int slot = event.getSlot(); + if (!( + slot == PlayerInventoryUtils.HELMET_SLOT || + slot == PlayerInventoryUtils.CHESTPLATE_SLOT || + slot == PlayerInventoryUtils.LEGGINGS_SLOT || + slot == PlayerInventoryUtils.BOOTS_SLOT + )) return; + + var dispatcher = game.getReplayManager().getEntityLifecycleDispatcher(); + if (dispatcher != null) { + dispatcher.recordEquipment( + player.getEntityId(), + slot, + event.getNewItem() + ); + } + + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerJoin.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerJoin.java index e878f3ff7..da0902618 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerJoin.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/ActionPlayerJoin.java @@ -5,14 +5,16 @@ import net.minestom.server.event.player.AsyncPlayerConfigurationEvent; import net.swofty.commons.ServerType; import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.game.Game; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.Game.JoinResult; +import net.swofty.type.game.game.GameState; import net.swofty.type.generic.HypixelConst; import net.swofty.type.generic.event.EventNodes; import net.swofty.type.generic.event.HypixelEvent; import net.swofty.type.generic.event.HypixelEventClass; import net.swofty.type.generic.redis.service.TypedGameInformationHandler; -import net.swofty.type.generic.utility.MathUtility; +import net.swofty.type.generic.utility.ScheduleUtility; import org.tinylog.Logger; public class ActionPlayerJoin implements HypixelEventClass { @@ -21,11 +23,11 @@ public class ActionPlayerJoin implements HypixelEventClass { @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = false) public void run(AsyncPlayerConfigurationEvent event) { final BedWarsPlayer player = (BedWarsPlayer) event.getPlayer(); - Logger.info("Player " + player.getUsername() + " joined the server from origin server " + player.getOriginServer()); + Logger.info("Player " + player.getUsername() + " joined the server from start server " + player.getOriginServer()); event.setSpawningInstance(HypixelConst.getEmptyInstance()); player.setRespawnPoint(new Pos(10, 10, 10)); - MathUtility.delay(() -> tryJoinGame(player, false), 15); + ScheduleUtility.delay(() -> tryJoinGame(player, false), 15); } private void tryJoinGame(BedWarsPlayer player, boolean isRetry) { @@ -35,7 +37,7 @@ private void tryJoinGame(BedWarsPlayer player, boolean isRetry) { if (preferredGameId == null) { if (!isRetry) { Logger.info("No game assignment found for " + player.getUsername() + ", retrying in 1 second..."); - MathUtility.delay(() -> tryJoinGame(player, true), 20); + ScheduleUtility.delay(() -> tryJoinGame(player, true), 20); return; } Logger.error("Failed to find game assignment for player " + player.getUsername()); @@ -44,19 +46,33 @@ private void tryJoinGame(BedWarsPlayer player, boolean isRetry) { return; } - Game preferred = TypeBedWarsGameLoader.getGameById(preferredGameId); + BedWarsGame preferred = TypeBedWarsGameLoader.getGameById(preferredGameId); if (preferred == null) { player.sendMessage("§cThe assigned game no longer exists! Returning to lobby..."); player.sendTo(ServerType.BEDWARS_LOBBY); return; } - MathUtility.delay(() -> { + ScheduleUtility.delay(() -> { if (!player.isOnline()) return; if (preferred.hasDisconnectedPlayer(player.getUuid())) { - preferred.rejoin(player); - } else { - preferred.join(player); + if (!preferred.handleRejoin(player)) { + player.sendMessage("§cFailed to rejoin your previous game! Returning to lobby..."); + player.sendTo(ServerType.BEDWARS_LOBBY); + } + return; + } + + if (preferred.getState() != GameState.WAITING && preferred.getState() != GameState.COUNTDOWN) { + player.sendMessage("§cThe assigned game is no longer joinable! Returning to lobby..."); + player.sendTo(ServerType.BEDWARS_LOBBY); + return; + } + + JoinResult joinResult = preferred.join(player); + if (joinResult instanceof JoinResult.Denied(String reason)) { + player.sendMessage("§cFailed to join assigned game (" + reason + ")! Returning to lobby..."); + player.sendTo(ServerType.BEDWARS_LOBBY); } }, 15); } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/custom/BedDestroyedEvent.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/custom/BedDestroyedEvent.java new file mode 100644 index 000000000..3f4acd3bd --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/custom/BedDestroyedEvent.java @@ -0,0 +1,16 @@ +package net.swofty.type.bedwarsgame.events.custom; + +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.GameEvent; + +public record BedDestroyedEvent( + String gameId, + TeamKey teamKey, + BedWarsPlayer destroyer +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/custom/BedWarsGameEventAdvanceEvent.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/custom/BedWarsGameEventAdvanceEvent.java new file mode 100644 index 000000000..6d074e2f3 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/events/custom/BedWarsGameEventAdvanceEvent.java @@ -0,0 +1,15 @@ +package net.swofty.type.bedwarsgame.events.custom; + +import net.swofty.type.game.game.event.GameEvent; + +public record BedWarsGameEventAdvanceEvent( + String gameId, + String previousEvent, + String currentEvent, + long secondsUntilNext +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/DisconnectedPlayerInfo.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/DisconnectedPlayerInfo.java deleted file mode 100644 index eb26d8367..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/DisconnectedPlayerInfo.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import lombok.Getter; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; - -import java.util.UUID; - -@Getter -public class DisconnectedPlayerInfo { - private final UUID playerUuid; - private final String username; - private final TeamKey teamKey; - private final long disconnectTime; - private final boolean bedWasAliveOnDisconnect; - - private final int armorLevel; - private final int pickaxeLevel; - private final int axeLevel; - - public DisconnectedPlayerInfo(UUID playerUuid, String username, TeamKey teamKey, - boolean bedWasAlive, - int armorLevel, int pickaxeLevel, int axeLevel) { - this.playerUuid = playerUuid; - this.username = username; - this.teamKey = teamKey; - this.disconnectTime = System.currentTimeMillis(); - this.bedWasAliveOnDisconnect = bedWasAlive; - this.armorLevel = armorLevel; - this.pickaxeLevel = pickaxeLevel; - this.axeLevel = axeLevel; - } - -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/Game.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/Game.java deleted file mode 100644 index 30a1209cf..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/Game.java +++ /dev/null @@ -1,551 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import lombok.Getter; -import lombok.Setter; -import net.kyori.adventure.audience.Audience; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.sound.Sound; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.title.Title; -import net.kyori.adventure.title.TitlePart; -import net.minestom.server.MinecraftServer; -import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.GameMode; -import net.minestom.server.entity.Player; -import net.minestom.server.instance.InstanceContainer; -import net.minestom.server.item.ItemStack; -import net.minestom.server.item.Material; -import net.minestom.server.tag.Tag; -import net.minestom.server.timer.Task; -import net.minestom.server.timer.TaskSchedule; -import net.swofty.commons.ChatUtility; -import net.swofty.commons.ServerType; -import net.swofty.commons.bedwars.BedwarsGameType; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.BedWarsGameScoreboard; -import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.shop.impl.AxeShopItem; -import net.swofty.type.bedwarsgame.shop.impl.PickaxeShopItem; -import net.swofty.type.bedwarsgame.stats.BedWarsStatsRecorder; -import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import net.swofty.type.bedwarsgame.user.ExperienceCause; -import org.tinylog.Logger; - -import java.time.Duration; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -@Getter -public final class Game { - - public static final Tag ELIMINATED_TAG = Tag.Boolean("eliminated"); - - private final InstanceContainer instanceContainer; - private final BedwarsGameType bedwarsGameType = BedwarsGameType.SOLO; - private final List players = new ArrayList<>(); - private final String gameId = UUID.randomUUID().toString(); - private final BedWarsMapsConfig.MapEntry mapEntry; - - private final TeamManager teamManager; - private final GeneratorManager generatorManager; - private final GameWorldManager worldManager; - private final GameCountdown countdown; - private final GameEventManager eventManager; - - private final Map> chests = new HashMap<>(); - private final Map> enderchests = new HashMap<>(); - - // Track players who disconnected during an active game for rejoin - private final Map disconnectedPlayers = new ConcurrentHashMap<>(); - - private Task timePlayedTask; - - @Setter - private GameStatus gameStatus; - - public Game(BedWarsMapsConfig.MapEntry mapEntry, InstanceContainer instanceContainer) { - this.mapEntry = mapEntry; - this.instanceContainer = instanceContainer; - - this.teamManager = new TeamManager(this); - this.generatorManager = new GeneratorManager(this); - this.worldManager = new GameWorldManager(this); - this.countdown = new GameCountdown(this); - this.eventManager = new GameEventManager(this); - - this.gameStatus = GameStatus.WAITING; - BedWarsGameScoreboard.start(this); - } - - public void join(BedWarsPlayer player) { - Logger.info("Player {} joining game {} on map {}", player.getUsername(), gameId, mapEntry.getName()); - - if (gameStatus != GameStatus.WAITING) { - player.sendMessage(Component.text("The game is already in progress or has ended.", NamedTextColor.RED)); - player.sendTo(ServerType.BEDWARS_LOBBY); - return; - } - - if (!hasCapacityForPlayer()) { - player.sendMessage(Component.text( - "This game is full. You shouldn't have been sent here. You'll be sent back to a lobby.", - NamedTextColor.RED)); - player.sendTo(ServerType.BEDWARS_LOBBY); - return; - } - - setupPlayerForWaiting(player); - players.add(player); - - int maxPlayers = getMaxPlayers(); - String randomLetters = UUID.randomUUID().toString().replaceAll("-", "") - .substring(0, new Random().nextInt(10) + 4); - for (BedWarsPlayer p : players) { - String name = p.getUuid().compareTo(player.getUuid()) == 0 ? player.getUsername() : "§k" + randomLetters; - p.sendMessage(name + " §ehas joined (§b" + players.size() + "§e/§b" + maxPlayers + "§e)"); - } - player.setDisplayName(Component.text(randomLetters, NamedTextColor.WHITE, TextDecoration.OBFUSCATED)); - - if (hasMinimumPlayersForStart() && !countdown.isActive()) { - countdown.startCountdown(); - } - } - - public void leave(BedWarsPlayer player) { - TeamKey teamName = player.getTeamKey(); - players.remove(player); - - player.removeTag(Tag.String("gameId")); - player.removeTag(Tag.String("team")); - player.sendTo(ServerType.BEDWARS_LOBBY); - - countdown.checkCountdownConditions(); - - if (gameStatus == GameStatus.IN_PROGRESS && teamName != null) { - checkForWinCondition(); - } - } - - /** - * Handle player disconnect during an active game. - * Stores their info for potential rejoin instead of removing them permanently. - */ - public void handleDisconnect(BedWarsPlayer player) { - if (gameStatus != GameStatus.IN_PROGRESS) { - leave(player); - return; - } - - TeamKey teamKey = player.getTeamKey(); - boolean bedAlive = teamKey != null && teamManager.isBedAlive(teamKey); - - // Get current upgrade levels - Integer armorLevel = player.getTag(TypeBedWarsGameLoader.ARMOR_LEVEL_TAG); - Integer pickaxeLevel = player.getTag(PickaxeShopItem.PICKAXE_UPGRADE_TAG); - Integer axeLevel = player.getTag(AxeShopItem.AXE_UPGRADE_TAG); - - // Store disconnect info for rejoin - DisconnectedPlayerInfo info = new DisconnectedPlayerInfo( - player.getUuid(), - player.getUsername(), - teamKey, - bedAlive, - armorLevel != null ? armorLevel : 0, - pickaxeLevel != null ? pickaxeLevel : 0, - axeLevel != null ? axeLevel : 0 - ); - disconnectedPlayers.put(player.getUuid(), info); - - // Remove from active players list - players.remove(player); - - // Send disconnect message to remaining players - String teamColor = teamKey != null ? teamKey.chatColor() : "§7"; - getPlayersAsAudience().sendMessage( - Component.text(teamColor + player.getUsername() + " §7disconnected.") - ); - - Logger.info("Player {} disconnected from game {} (team: {}, bed alive: {})", - player.getUsername(), gameId, teamKey, bedAlive); - - // Clear player tags and send to lobby - player.removeTag(Tag.String("gameId")); - player.removeTag(Tag.String("team")); - player.sendTo(ServerType.BEDWARS_LOBBY); - - // Check win condition - checkForWinCondition(); - } - - /** - * Handle player rejoining an active game. - */ - public void rejoin(BedWarsPlayer player) { - DisconnectedPlayerInfo info = disconnectedPlayers.remove(player.getUuid()); - - if (info == null) { - player.sendMessage(Component.text("You don't have a game to rejoin!", NamedTextColor.RED)); - player.sendTo(ServerType.BEDWARS_LOBBY); - return; - } - - if (gameStatus != GameStatus.IN_PROGRESS) { - player.sendMessage(Component.text("The game has ended.", NamedTextColor.RED)); - player.sendTo(ServerType.BEDWARS_LOBBY); - return; - } - - // Re-add to players list - players.add(player); - - // Restore tags - player.setTag(Tag.String("gameId"), gameId); - player.setTag(Tag.String("team"), info.getTeamKey().name()); - - // Restore upgrade levels - if (info.getArmorLevel() > 0) { - player.setTag(TypeBedWarsGameLoader.ARMOR_LEVEL_TAG, info.getArmorLevel()); - } - if (info.getPickaxeLevel() > 0) { - player.setTag(PickaxeShopItem.PICKAXE_UPGRADE_TAG, info.getPickaxeLevel()); - } - if (info.getAxeLevel() > 0) { - player.setTag(AxeShopItem.AXE_UPGRADE_TAG, info.getAxeLevel()); - } - - // Set to correct instance - player.setInstance(instanceContainer); - - // Send reconnect message to all players - String teamColor = info.getTeamKey().chatColor(); - getPlayersAsAudience().sendMessage( - Component.text(teamColor + player.getUsername() + " §7reconnected.") - ); - player.getAchievementHandler().completeAchievement(""); - - Logger.info("Player {} rejoined game {} (team: {})", player.getUsername(), gameId, info.getTeamKey().getName()); - - // check if bed is alive, if not, set up as spectator - if (!teamManager.isBedAlive(info.getTeamKey())) { - setupAsSpectator(player); - } else { - // Normal rejoin with respawn timer - triggerRespawnTimer(player, info.getTeamKey()); - } - } - - private void setupAsSpectator(BedWarsPlayer player) { - player.setTag(ELIMINATED_TAG, true); - player.setGameMode(GameMode.SPECTATOR); - player.setInvisible(true); - player.setFlying(true); - - BedWarsMapsConfig.Position spectatorPos = mapEntry.getConfiguration().getLocations().getSpectator(); - if (spectatorPos != null) { - player.teleport(new Pos(spectatorPos.x(), spectatorPos.y(), spectatorPos.z())); - } - - player.sendTitlePart(TitlePart.TITLE, Component.text("SPECTATING", NamedTextColor.GRAY)); - player.sendTitlePart(TitlePart.SUBTITLE, Component.text("Your bed was destroyed.", NamedTextColor.RED)); - } - - private void triggerRespawnTimer(BedWarsPlayer player, TeamKey teamKey) { - // Put player in spectator mode temporarily - player.setGameMode(GameMode.SPECTATOR); - player.getInventory().clear(); - - BedWarsMapsConfig.Position spectatorPos = mapEntry.getConfiguration().getLocations().getSpectator(); - if (spectatorPos != null) { - player.teleport(new Pos(spectatorPos.x(), spectatorPos.y(), spectatorPos.z())); - } - - // Start respawn countdown (same as death handler) - final Title.Times titleTimes = Title.Times.times(Duration.ofMillis(100), Duration.ofSeconds(1), Duration.ofMillis(100)); - final AtomicInteger countdown = new AtomicInteger(5); - final AtomicReference taskRef = new AtomicReference<>(); - - final Task task = MinecraftServer.getSchedulerManager().buildTask(() -> { - if (!player.isOnline()) { - Task currentTask = taskRef.get(); - if (currentTask != null) currentTask.cancel(); - return; - } - - int secondsRemaining = countdown.getAndDecrement(); - - if (secondsRemaining > 0) { - Component mainTitleText = Component.text("YOU DIED!", NamedTextColor.RED); - Component subTitleText = Component.text("You will respawn in " + secondsRemaining + " second" + (secondsRemaining == 1 ? "" : "s") + "!", NamedTextColor.YELLOW); - Title title = Title.title(mainTitleText, subTitleText, titleTimes); - player.showTitle(title); - } else { - // Time to respawn - player.clearTitle(); - respawnPlayer(player, teamKey); - - // Cancel repeating task - Task currentTask = taskRef.get(); - if (currentTask != null) { - currentTask.cancel(); - } - } - }).repeat(TaskSchedule.seconds(1)).schedule(); - taskRef.set(task); - } - - private void respawnPlayer(BedWarsPlayer player, TeamKey teamKey) { - MapTeam playerTeam = mapEntry.getConfiguration().getTeams().get(teamKey); - - if (playerTeam != null) { - BedWarsMapsConfig.PitchYawPosition spawnPos = playerTeam.getSpawn(); - player.teleport(new Pos(spawnPos.x(), spawnPos.y(), spawnPos.z(), spawnPos.pitch(), spawnPos.yaw())); - player.setGameMode(GameMode.SURVIVAL); - player.setInvisible(false); - player.setFlying(false); - player.getInventory().addItemStack(ItemStack.of(Material.WOODEN_SWORD)); - - // Give back tools - AxeShopItem axeShopItem = new AxeShopItem(); - Integer currentAxeLevel = player.getTag(AxeShopItem.AXE_UPGRADE_TAG); - if (currentAxeLevel != null && currentAxeLevel > 0) { - player.getInventory().addItemStack(ItemStack.of(axeShopItem.getTier(currentAxeLevel - 1).material())); - } - - PickaxeShopItem pickaxeShopItem = new PickaxeShopItem(); - Integer currentPickaxeLevel = player.getTag(PickaxeShopItem.PICKAXE_UPGRADE_TAG); - if (currentPickaxeLevel != null && currentPickaxeLevel > 0) { - player.getInventory().addItemStack(ItemStack.of(pickaxeShopItem.getTier(currentPickaxeLevel - 1).material())); - } - - // Equip team armor - teamManager.equipTeamArmor(player, teamKey); - - // Apply upgrades - Integer protectionLevel = player.getTag(Tag.Integer("upgrade_reinforced_armor")); - if (protectionLevel != null) { - TypeBedWarsGameLoader.getTeamShopManager().getUpgrade("reinforced_armor").applyEffect(this, teamKey, protectionLevel); - } - - Integer cushionedBootsLevel = player.getTag(Tag.Integer("upgrade_cushioned_boots")); - if (cushionedBootsLevel != null) { - TypeBedWarsGameLoader.getTeamShopManager().getUpgrade("cushioned_boots").applyEffect(this, teamKey, cushionedBootsLevel); - } - - Integer sharpnessLevel = player.getTag(Tag.Integer("upgrade_sharpness")); - if (sharpnessLevel != null) { - TypeBedWarsGameLoader.getTeamShopManager().getUpgrade("sharpness").applyEffect(this, teamKey, sharpnessLevel); - } - } else { - Logger.warn("Player {} had team key '{}' but team was not found. Sending to lobby.", player.getUsername(), teamKey.getName()); - player.sendMessage("§cAn unexpected error occurred while respawning you. Please contact a staff member."); - player.sendTo(ServerType.BEDWARS_LOBBY); - } - } - - /** - * Check if a player has a pending rejoin for this game. - */ - public boolean hasDisconnectedPlayer(UUID playerUuid) { - return disconnectedPlayers.containsKey(playerUuid); - } - - /** - * Get list of disconnected player UUIDs for heartbeat. - */ - public List getDisconnectedPlayerUuids() { - return new ArrayList<>(disconnectedPlayers.keySet()); - } - - public void startGame() { - Logger.info("Starting game {}", gameId); - gameStatus = GameStatus.IN_PROGRESS; - - worldManager.clearExistingBeds(); - Map activeTeams = teamManager.assignPlayersToTeams(); - worldManager.placeBeds(activeTeams); - worldManager.spawnShopNPCs(activeTeams); - generatorManager.startTeamGenerators(activeTeams); - generatorManager.startGlobalGenerators(); - eventManager.start(); - - timePlayedTask = MinecraftServer.getSchedulerManager().buildTask(() -> { - if (gameStatus != GameStatus.IN_PROGRESS) { - timePlayedTask.cancel(); - return; - } - for (BedWarsPlayer player : players) { - player.xp(ExperienceCause.TIME_PLAYED); - } - }).delay(TaskSchedule.minutes(1)).repeat(TaskSchedule.minutes(1)).schedule(); - - Logger.info("Game {} started with {} active teams", gameId, activeTeams.size()); - - String line = "■".repeat(50); - Component[] messages = new Component[] { - Component.text(line, NamedTextColor.GREEN), - Component.text(ChatUtility.FontInfo.center("Bed Wars"), NamedTextColor.WHITE, TextDecoration.BOLD), - Component.space(), - Component.text(ChatUtility.FontInfo.center("Protect your bed and destroy the enemy beds."), NamedTextColor.YELLOW, TextDecoration.BOLD), - Component.text(ChatUtility.FontInfo.center("Upgrade yourself and your team by collecting"), NamedTextColor.YELLOW, TextDecoration.BOLD), - Component.text(ChatUtility.FontInfo.center("Iron, Gold, Emerald and Diamond from generators"), NamedTextColor.YELLOW, TextDecoration.BOLD), - Component.text(ChatUtility.FontInfo.center("to access powerful upgrades."), NamedTextColor.YELLOW, TextDecoration.BOLD), - Component.space(), - Component.text(line, NamedTextColor.GREEN) - }; - for (Component msg : messages) { - getPlayersAsAudience().sendMessage(msg); - } - } - - public void recordBedDestroyed(TeamKey teamKey) { - teamManager.recordBedDestroyed(teamKey); - players.forEach(player -> { - player.sendMessage(teamKey.chatColor() + "Team " + teamKey.getName() + "'s §cbed has been destroyed!"); - player.playSound(Sound.sound(Key.key("minecraft:entity.wither.death"), - Sound.Source.MASTER, 1f, 1f), Sound.Emitter.self()); - }); - checkForWinCondition(); - } - - public void playerEliminated(BedWarsPlayer player) { - player.setTag(ELIMINATED_TAG, true); - TeamKey teamName = player.getTeamKey(); - Logger.info("Player {} from team {} eliminated", player.getUsername(), teamName != null ? teamName : "N/A"); - checkForWinCondition(); - } - - public void checkForWinCondition() { - if (gameStatus != GameStatus.IN_PROGRESS) return; - - List viableTeams = mapEntry.getConfiguration().getTeams().keySet().stream() - .filter(this::isTeamViable) - .toList(); - - if (viableTeams.size() <= 1) { - TeamKey winningTeam = viableTeams.isEmpty() ? null : viableTeams.getFirst(); - endGame(winningTeam); - } - } - - private boolean isTeamViable(TeamKey teamKey) { - // A team is viable if: - // 1. Bed is alive, OR - // 2. Has active (non-eliminated) players online, OR - // 3. Has disconnected players who can still rejoin - // 4. Has not been vibecoded by Swofty - boolean hasActivePlayers = teamManager.countActivePlayersOnTeam(teamKey) > 0; - boolean hasRejoinablePlayers = disconnectedPlayers.values().stream() - .anyMatch(info -> info.getTeamKey() == teamKey && teamManager.isBedAlive(info.getTeamKey())); - - return teamManager.isBedAlive(teamKey) || hasActivePlayers || hasRejoinablePlayers; - } - - private boolean hasCapacityForPlayer() { - return players.size() < getMaxPlayers(); - } - - public boolean canAcceptNewPlayers() { - return gameStatus == GameStatus.WAITING; - } - - public int getAvailableSlots() { - return Math.max(0, getMaxPlayers() - players.size()); - } - - public String canAcceptPartyWarp() { - if (gameStatus == GameStatus.IN_PROGRESS) { - return "Cannot warp - game has already started"; - } - if (gameStatus == GameStatus.ENDING) { - return "Cannot warp - game is ending"; - } - return null; - } - - private boolean hasMinimumPlayersForStart() { - int teamSize = Math.max(1, bedwarsGameType.getTeamSize()); - int teamCount = mapEntry.getConfiguration().getTeams().size(); - return players.size() >= teamSize * Math.min(2, teamCount) && teamCount >= 2; - } - - private int getMaxPlayers() { - return mapEntry.getConfiguration().getTeams().size() * Math.max(1, bedwarsGameType.getTeamSize()); - } - - private void setupPlayerForWaiting(BedWarsPlayer player) { - BedWarsMapsConfig.Position waiting = mapEntry.getConfiguration().getLocations().getWaiting(); - - if (player.getInstance() == null || player.getInstance().getUuid() != instanceContainer.getUuid()) { - player.setInstance(instanceContainer, new Pos(waiting.x(), waiting.y(), waiting.z())); - } - - player.setFlying(false); - player.setGameMode(GameMode.ADVENTURE); - player.getInventory().setItemStack(8, - TypeBedWarsGameLoader.getItemHandler().getItem("leave_game").getItemStack()); - player.setTag(Tag.String("gameId"), gameId); - player.sendMessage("§8Joined the game on map " + mapEntry.getId() + "."); - } - - private void endGame(TeamKey winningTeam) { - if (gameStatus == GameStatus.ENDING) return; - - gameStatus = GameStatus.ENDING; - Logger.info("Game {} ended. Winner: {}", gameId, winningTeam != null ? winningTeam.getName() : "None (Draw)"); - - generatorManager.stopAllGenerators(); - eventManager.stop(); - - String titleMessage; - String subtitleMessage; - - if (winningTeam != null) { - titleMessage = winningTeam.chatColor() + "Team " + winningTeam.getName() + " has won!"; - subtitleMessage = "Congratulations!"; - } else { - titleMessage = "§cGame Over!"; - subtitleMessage = "It's a draw!"; - } - - final TeamKey finalWinningTeam = winningTeam; - players.forEach(player -> { - player.sendTitlePart(TitlePart.TITLE, Component.text(titleMessage)); - player.sendTitlePart(TitlePart.SUBTITLE, Component.text(subtitleMessage)); - player.playSound(Sound.sound(Key.key("minecraft:ui.toast.challenge_complete"), - Sound.Source.MASTER, 1f, 1f), Sound.Emitter.self()); - - // Record win for players on the winning team - if (finalWinningTeam != null && finalWinningTeam.getName().equalsIgnoreCase(player.getTeamName())) { - BedWarsStatsRecorder.recordWin(player, bedwarsGameType); - player.getAchievementHandler().addProgressByTrigger("bedwars.wins", 1); - } - - if (player.getGameMode() != GameMode.SPECTATOR) { - player.setGameMode(GameMode.SPECTATOR); - } - }); - - MinecraftServer.getSchedulerManager().buildTask(() -> { - players.forEach(this::leave); - players.clear(); - TypeBedWarsGameLoader.getGames().remove(this); - TypeBedWarsGameLoader.createGame(mapEntry); - }).delay(TaskSchedule.seconds(10)).schedule(); - } - - public Audience getPlayersAsAudience() { - return Audience.audience(players); - } - -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameCountdown.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameCountdown.java deleted file mode 100644 index 16242dd54..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameCountdown.java +++ /dev/null @@ -1,161 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import lombok.Getter; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.MinecraftServer; -import net.minestom.server.timer.Task; -import net.minestom.server.timer.TaskSchedule; -import org.tinylog.Logger; - -import javax.annotation.Nullable; - -public final class GameCountdown { - private static final int COUNTDOWN_DURATION_SECONDS = 30; - private static final int[] ANNOUNCEMENT_TIMES = {30, 20, 15, 10, 5, 4, 3, 2, 1}; - - private final Game game; - @Getter - private int remainingSeconds; - @Getter - private boolean isActive; - @Nullable - private Task countdownTask; - - public GameCountdown(Game game) { - this.game = game; - this.remainingSeconds = COUNTDOWN_DURATION_SECONDS; - this.isActive = false; - } - - public boolean startCountdown() { - if (isActive || game.getGameStatus() != GameStatus.WAITING) { - return false; - } - - if (!hasMinimumPlayers()) { - Logger.debug("Cannot start countdown: insufficient players"); - return false; - } - - isActive = true; - remainingSeconds = COUNTDOWN_DURATION_SECONDS; - - Logger.info("Starting countdown for game {}", game.getGameId()); - announceCountdown(); - - countdownTask = MinecraftServer.getSchedulerManager() - .buildTask(this::tickCountdown) - .delay(TaskSchedule.seconds(1)) - .repeat(TaskSchedule.seconds(1)) - .schedule(); - - return true; - } - - public void stopCountdown() { - if (!isActive) { - return; - } - - Logger.info("Stopping countdown for game {}", game.getGameId()); - isActive = false; - - if (countdownTask != null) { - countdownTask.cancel(); - countdownTask = null; - } - - game.getPlayers().forEach(player -> - player.sendMessage(Component.text("Countdown stopped - not enough players!") - .color(NamedTextColor.RED)) - ); - } - - public void checkCountdownConditions() { - if (!isActive) { - return; - } - - if (!hasMinimumPlayers()) { - stopCountdown(); - } - } - - private void tickCountdown() { - if (!isActive || game.getGameStatus() != GameStatus.WAITING) { - stopCountdown(); - return; - } - - if (!hasMinimumPlayers()) { - stopCountdown(); - return; - } - - remainingSeconds--; - - if (shouldAnnounce(remainingSeconds)) { - announceCountdown(); - } - - if (remainingSeconds <= 0) { - finishCountdown(); - } - } - - private void finishCountdown() { - isActive = false; - if (countdownTask != null) { - countdownTask.cancel(); - countdownTask = null; - } - - Logger.info("Countdown finished for game {}, starting game", game.getGameId()); - game.startGame(); - } - - private void announceCountdown() { - Component message = createCountdownMessage(); - game.getPlayers().forEach(player -> player.sendMessage(message)); - } - - private Component createCountdownMessage() { - if (remainingSeconds > 1) { - return Component.text("Game starting in ") - .color(NamedTextColor.YELLOW) - .append(Component.text(remainingSeconds) - .color(NamedTextColor.RED)) - .append(Component.text(" seconds!") - .color(NamedTextColor.YELLOW)); - } else if (remainingSeconds == 1) { - return Component.text("Game starting in ") - .color(NamedTextColor.YELLOW) - .append(Component.text("1") - .color(NamedTextColor.RED)) - .append(Component.text(" second!") - .color(NamedTextColor.YELLOW)); - } else { - return Component.text("Game starting now!") - .color(NamedTextColor.GREEN); - } - } - - private boolean shouldAnnounce(int seconds) { - for (int time : ANNOUNCEMENT_TIMES) { - if (seconds == time) { - return true; - } - } - return false; - } - - private boolean hasMinimumPlayers() { - int teamSize = game.getBedwarsGameType().getTeamSize(); - if (teamSize <= 0) teamSize = 1; - - int minPlayersRequired = teamSize * Math.min(2, game.getMapEntry().getConfiguration().getTeams().size()); - return game.getPlayers().size() >= minPlayersRequired; - } - -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameEventManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameEventManager.java deleted file mode 100644 index ac40c8781..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameEventManager.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import lombok.Getter; -import net.minestom.server.MinecraftServer; -import net.minestom.server.timer.Task; -import net.minestom.server.timer.TaskSchedule; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -public final class GameEventManager { - private final Game game; - private final List orderedEvents = new ArrayList<>(EnumSet.allOf(GameEventPosition.class)); - private final List listeners = new ArrayList<>(); - @Getter - private GameEventPosition currentEvent = GameEventPosition.BEGIN; - @Getter - private long secondsUntilNextEvent; - private int eventIndex; // index within orderedEvents - private Task ticker; - - public GameEventManager(Game game) { - this.game = game; - this.eventIndex = 0; - this.secondsUntilNextEvent = getNextEvent() != null ? getNextEvent().getTime() : 0; - } - - public void start() { - if (ticker != null) return; - ticker = MinecraftServer.getSchedulerManager().buildTask(() -> { - if (game.getGameStatus() != GameStatus.IN_PROGRESS) return; - if (secondsUntilNextEvent > 0) { - secondsUntilNextEvent--; - return; - } - - // advance to the next event - GameEventPosition prev = currentEvent; - GameEventPosition next = getNextEvent(); - if (next == null) return; // no more events - - currentEvent = next; - eventIndex++; - secondsUntilNextEvent = getNextEvent() != null ? getNextEvent().getTime() : 0; - - for (Listener l : listeners) { - l.onEventChange(prev, currentEvent); - } - }).delay(TaskSchedule.seconds(1)).repeat(TaskSchedule.seconds(1)).schedule(); - } - - public void stop() { - if (ticker != null) { - ticker.cancel(); - ticker = null; - } - } - - public GameEventPosition getNextEvent() { - int nextIdx = eventIndex + 1; - return nextIdx < orderedEvents.size() ? orderedEvents.get(nextIdx) : null; - } - - public long getDiamondDelaySeconds() { - return currentEvent.getDiamondSeconds(); - } - - public long getEmeraldDelaySeconds() { - return currentEvent.getEmeraldSeconds(); - } - - public void addListener(Listener listener) { - listeners.add(listener); - } - - public interface Listener { - void onEventChange(GameEventPosition previous, GameEventPosition current); - } -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameEventPosition.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameEventPosition.java deleted file mode 100644 index 8f1ed61fc..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameEventPosition.java +++ /dev/null @@ -1,45 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import lombok.Getter; - -@Getter -public enum GameEventPosition { - BEGIN(30, 65), - DIAMOND_2(6 * 60, 30, 65), - EMERALD_2(6 * 60, 30, 65), - DIAMOND_3(6 * 60, 30, 65), - EMERALD_3(6 * 60, 30, 65), - BED_BREAK(6 * 60, 30, 65), - SUDDEN_DEATH(10 * 60, 30, 65), - GAME_END(10 * 60, 30, 65); - - private final long time; // in seconds - private final long diamondSeconds; - private final long emeraldSeconds; - - GameEventPosition(long diamondSeconds, long emeraldSeconds) { - this.time = 0; - this.diamondSeconds = diamondSeconds; - this.emeraldSeconds = emeraldSeconds; - } - - GameEventPosition(long time, long diamondSeconds, long emeraldSeconds) { - this.time = time; - this.diamondSeconds = diamondSeconds; - this.emeraldSeconds = emeraldSeconds; - } - - public String getDisplayName() { - return switch (this) { - case BEGIN -> "Game Start"; - case DIAMOND_2 -> "Diamond II"; - case EMERALD_2 -> "Emerald II"; - case DIAMOND_3 -> "Diamond III"; - case EMERALD_3 -> "Emerald III"; - case BED_BREAK -> "Bed Break"; - case SUDDEN_DEATH -> "Sudden Death"; - case GAME_END -> "Game End"; - }; - } - -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameStatus.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameStatus.java deleted file mode 100644 index 2b0302c29..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameStatus.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -public enum GameStatus { - WAITING, - IN_PROGRESS, - ENDING -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameWorldManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameWorldManager.java deleted file mode 100644 index 51c2d8f5b..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GameWorldManager.java +++ /dev/null @@ -1,221 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.VillagerProfession; -import net.minestom.server.instance.Instance; -import net.minestom.server.instance.InstanceContainer; -import net.minestom.server.instance.block.Block; -import net.minestom.server.item.Material; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.gui.GUIItemShop; -import net.swofty.type.bedwarsgame.gui.GUITeamShop; -import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.VillagerConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -import org.tinylog.Logger; - -import java.util.Map; - -public final class GameWorldManager { - private final Game game; - private final InstanceContainer instanceContainer; - - public GameWorldManager(Game game) { - this.game = game; - this.instanceContainer = game.getInstanceContainer(); - } - - public void clearExistingBeds() { - Map teams = game.getMapEntry().getConfiguration().getTeams(); - - for (MapTeam team : teams.values()) { - BedWarsMapsConfig.TwoBlockPosition bedPositions = team.getBed(); - if (bedPositions != null) { - clearBedBlocks(bedPositions); - } - } - } - - private void clearBedBlocks(BedWarsMapsConfig.TwoBlockPosition bedPositions) { - if (bedPositions.feet() != null) { - instanceContainer.setBlock( - (int) bedPositions.feet().x(), - (int) bedPositions.feet().y(), - (int) bedPositions.feet().z(), - Block.AIR - ); - } - - if (bedPositions.head() != null) { - instanceContainer.setBlock( - (int) bedPositions.head().x(), - (int) bedPositions.head().y(), - (int) bedPositions.head().z(), - Block.AIR - ); - } - } - - public void placeBeds(Map activeTeams) { - activeTeams.forEach(this::placeBedForTeam); - } - - private void placeBedForTeam(TeamKey teamKey, MapTeam team) { - BedWarsMapsConfig.TwoBlockPosition bedPositions = team.getBed(); - if (bedPositions == null || bedPositions.feet() == null || bedPositions.head() == null) { - Logger.warn("Bed position not fully defined for team: {}. Skipping bed placement.", teamKey.getName()); - return; - } - - BedWarsMapsConfig.Position feetPos = bedPositions.feet(); - BedWarsMapsConfig.Position headPos = bedPositions.head(); - - try { - Material bedMaterial = getBedMaterialForTeam(teamKey); - String facing = calculateBedFacing(feetPos, headPos); - - Block footBlock = bedMaterial.block() - .withProperty("part", "foot") - .withProperty("facing", facing); - Block headBlock = bedMaterial.block() - .withProperty("part", "head") - .withProperty("facing", facing); - - instanceContainer.setBlock((int) feetPos.x(), (int) feetPos.y(), (int) feetPos.z(), footBlock); - instanceContainer.setBlock((int) headPos.x(), (int) headPos.y(), (int) headPos.z(), headBlock); - - game.getTeamManager().setBedStatus(teamKey, true); - - Logger.debug("Placed {} bed for team {} (foot: {}, head: {}, facing: {})", - teamKey.getName().toLowerCase(), teamKey.getName(), feetPos, headPos, facing); - - } catch (IllegalArgumentException e) { - Logger.error("Error placing bed for team {}: {}", teamKey.getName(), e.getMessage()); - instanceContainer.setBlock((int) feetPos.x(), (int) feetPos.y(), (int) feetPos.z(), Block.STONE); - instanceContainer.setBlock((int) headPos.x(), (int) headPos.y(), (int) headPos.z(), Block.STONE); - } - } - - private Material getBedMaterialForTeam(TeamKey teamKey) { - return switch (teamKey) { - case RED -> Material.RED_BED; - case BLUE -> Material.BLUE_BED; - case GREEN -> Material.LIME_BED; - case YELLOW -> Material.YELLOW_BED; - case AQUA -> Material.LIGHT_BLUE_BED; - case PINK -> Material.PINK_BED; - case WHITE -> Material.WHITE_BED; - case GRAY -> Material.GRAY_BED; - }; - } - - private String calculateBedFacing(BedWarsMapsConfig.Position feetPos, BedWarsMapsConfig.Position headPos) { - if (headPos.x() > feetPos.x()) return "east"; - if (headPos.x() < feetPos.x()) return "west"; - if (headPos.z() > feetPos.z()) return "south"; - return "north"; - } - - public void spawnShopNPCs(Map activeTeams) { - activeTeams.forEach(this::spawnShopNPCsForTeam); - } - - private void spawnShopNPCsForTeam(TeamKey teamKey, MapTeam team) { - if (team.getShop() == null) return; - - BedWarsMapsConfig.PitchYawPosition itemShopPos = team.getShop().item(); - BedWarsMapsConfig.PitchYawPosition teamShopPos = team.getShop().team(); - - if (itemShopPos != null) { - HypixelNPC shopNpc = new HypixelNPC( - new VillagerConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§bITEM SHOP", "§e§lRIGHT CLICK"}; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(itemShopPos.x(), itemShopPos.y(), itemShopPos.z(), - itemShopPos.yaw(), itemShopPos.pitch()); - } - - @Override - public VillagerProfession profession() { - return VillagerProfession.BUTCHER; - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - - @Override - public Instance instance() { - return game.getInstanceContainer(); - } - } - ) { - @Override - public void onClick(NPCInteractEvent event) { - BedWarsPlayer bwPlayer = (BedWarsPlayer) event.player(); - new GUIItemShop(bwPlayer.getGame()).open(event.player()); - } - }; - shopNpc.register(); - } - - if (teamShopPos != null) { - HypixelNPC teamNpc = new HypixelNPC( - new VillagerConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§bTEAM", "§bUPGRADES", "§e§lRIGHT CLICK"}; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(teamShopPos.x(), teamShopPos.y(), teamShopPos.z(), - teamShopPos.yaw(), teamShopPos.pitch()); - } - - @Override - public VillagerProfession profession() { - return VillagerProfession.BUTCHER; - } - - @Override - public boolean looking(HypixelPlayer player) { - return true; - } - - @Override - public Instance instance() { - return game.getInstanceContainer(); - } - } - ) { - @Override - public void onClick(NPCInteractEvent event) { - BedWarsPlayer bwPlayer = (BedWarsPlayer) event.player(); - new GUITeamShop().open(bwPlayer); - } - }; - teamNpc.register(); - } - } - - public void respawnAllBeds() { - Map teams = game.getMapEntry().getConfiguration().getTeams(); - - teams.forEach((teamKey, team) -> { - if (game.getTeamManager().isBedAlive(teamKey)) { - placeBedForTeam(teamKey, team); - } - }); - } -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GeneratorManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GeneratorManager.java deleted file mode 100644 index a009b1f74..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/GeneratorManager.java +++ /dev/null @@ -1,309 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import net.kyori.adventure.key.Key; -import net.kyori.adventure.nbt.CompoundBinaryTag; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.minestom.server.MinecraftServer; -import net.minestom.server.component.DataComponents; -import net.minestom.server.coordinate.Pos; -import net.minestom.server.coordinate.Vec; -import net.minestom.server.entity.ItemEntity; -import net.minestom.server.item.ItemStack; -import net.minestom.server.item.Material; -import net.minestom.server.item.component.CustomData; -import net.minestom.server.timer.Task; -import net.minestom.server.timer.TaskSchedule; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.entity.TextDisplayEntity; -import org.intellij.lang.annotations.Subst; -import org.tinylog.Logger; - -import java.time.Duration; -import java.util.*; - -public final class GeneratorManager implements GameEventManager.Listener { - private final Game game; - private final Map> teamGeneratorTasks = new EnumMap<>(TeamKey.class); - private final Map> generatorDisplays = new HashMap<>(); - private final Map generatorLimits = new HashMap<>(); - private Task globalTicker; - private long lastDiamondDelay = -1; - private long lastEmeraldDelay = -1; - - public GeneratorManager(Game game) { - this.game = game; - if (game.getEventManager() != null) { - game.getEventManager().addListener(this); - } - } - - public void startTeamGenerators(Map activeTeams) { - BedWarsMapsConfig.MapEntry.MapConfiguration mapConfig = game.getMapEntry().getConfiguration(); - BedWarsMapsConfig.GeneratorSpeed generatorSpeed = mapConfig.getGeneratorSpeed(); - - if (generatorSpeed == null) { - Logger.warn("No generator speed configured for map"); - return; - } - - activeTeams.forEach((teamKey, team) -> { - BedWarsMapsConfig.Position genLocation = team.getGenerator(); - if (genLocation == null) return; - - Pos spawnPosition = new Pos(genLocation.x(), genLocation.y(), genLocation.z()); - - // Start iron generator - startTeamGenerator(teamKey, "iron", generatorSpeed.getIronAmount(), - generatorSpeed.getIronDelaySeconds(), spawnPosition); - - // Start gold generator - startTeamGenerator(teamKey, "gold", generatorSpeed.getGoldAmount(), - generatorSpeed.getGoldDelaySeconds(), spawnPosition); - }); - } - - private void startTeamGenerator(TeamKey teamKey, String materialType, - int baseAmount, int baseDelay, Pos spawnPosition) { - Material itemMaterial = getMaterialFromType(materialType); - if (itemMaterial == null) { - Logger.warn("Invalid material type: {} for team {}", materialType, teamKey.getName()); - return; - } - - - Task task = MinecraftServer.getSchedulerManager().buildTask(() -> { - if (game.getGameStatus() != GameStatus.IN_PROGRESS) return; - - int forgeLevel = game.getTeamManager().getTeamUpgradeLevel(teamKey, "forge"); - double multiplier = calculateForgeMultiplier(itemMaterial, forgeLevel); - - int finalAmount = (int) Math.round(baseAmount * multiplier); - if (finalAmount == 0 && baseAmount > 0 && multiplier > 1.0) finalAmount = 1; - - if (finalAmount > 0) { - spawnItem(itemMaterial, finalAmount, spawnPosition, Duration.ofMillis(500)); - } - }).delay(TaskSchedule.seconds(baseDelay)).repeat(TaskSchedule.seconds(baseDelay)).schedule(); - - teamGeneratorTasks.computeIfAbsent(teamKey, k -> new ArrayList<>()).add(task); - } - - public void startGlobalGenerators() { - BedWarsMapsConfig.MapEntry.MapConfiguration mapConfig = game.getMapEntry().getConfiguration(); - if (mapConfig.getGlobal_generator() == null) return; - - mapConfig.getGlobal_generator().forEach(this::setupGlobalGenerator); - - if (globalTicker != null) globalTicker.cancel(); - globalTicker = MinecraftServer.getSchedulerManager().buildTask(() -> { - if (game.getGameStatus() != GameStatus.IN_PROGRESS) return; - updateGeneratorDisplays(); - tickGlobalGenerators(); - }).delay(TaskSchedule.seconds(1)).repeat(TaskSchedule.seconds(1)).schedule(); - } - - private void setupGlobalGenerator(String generatorType, BedWarsMapsConfig.MapEntry.MapConfiguration.GlobalGenerator config) { - Material itemMaterial = Material.fromKey(Key.key(Key.MINECRAFT_NAMESPACE, generatorType)); - if (itemMaterial == null) { - Logger.warn("Invalid material for global generator: {}", generatorType); - return; - } - - List locations = config.getLocations(); - if (locations == null || locations.isEmpty()) return; - - if (generatorType.equals("diamond") || generatorType.equals("emerald")) { - long delaySeconds = generatorType.equals("diamond") - ? game.getEventManager().getDiamondDelaySeconds() - : game.getEventManager().getEmeraldDelaySeconds(); - - setupGlobalGeneratorDisplays(generatorType, locations, (int) delaySeconds); - generatorLimits.put(generatorType, new GeneratorLimits( - itemMaterial, config.getAmount(), config.getMax(), locations)); - } - } - - private void setupGlobalGeneratorDisplays(String generatorType, List locations, int delaySeconds) { - NamedTextColor color = generatorType.equals("diamond") ? NamedTextColor.AQUA : NamedTextColor.GREEN; - String capitalizedType = Character.toUpperCase(generatorType.charAt(0)) + generatorType.substring(1); - - for (BedWarsMapsConfig.Position location : locations) { - double locY = location.y() + 4.0; - - TextDisplayEntity tierDisplay = new TextDisplayEntity( - Component.text("Tier I").color(NamedTextColor.YELLOW)); - tierDisplay.setInstance(game.getInstanceContainer(), new Pos(location.x(), locY, location.z())); - - locY -= 0.3; - TextDisplayEntity titleDisplay = new TextDisplayEntity( - Component.text(capitalizedType).color(color).decorate(TextDecoration.BOLD)); - titleDisplay.setInstance(game.getInstanceContainer(), new Pos(location.x(), locY, location.z())); - - locY -= 0.3; - TextDisplayEntity spawnDisplay = new TextDisplayEntity( - MiniMessage.miniMessage().deserialize("Spawns in " + delaySeconds + " seconds!")); - spawnDisplay.setInstance(game.getInstanceContainer(), new Pos(location.x(), locY, location.z())); - - generatorDisplays.computeIfAbsent(generatorType, k -> new ArrayList<>()) - .add(new GeneratorDisplay(tierDisplay, spawnDisplay, delaySeconds)); - } - } - - private void tickGlobalGenerators() { - long diamondDelay = game.getEventManager().getDiamondDelaySeconds(); - long emeraldDelay = game.getEventManager().getEmeraldDelaySeconds(); - resetDisplaysIfEventChanged((int) diamondDelay, (int) emeraldDelay); - - long now = System.currentTimeMillis() / 1000L; - - for (Map.Entry entry : generatorLimits.entrySet()) { - String type = entry.getKey(); - GeneratorLimits limits = entry.getValue(); - long delay = type.equals("diamond") ? diamondDelay : emeraldDelay; - - if (delay <= 0 || (now % delay) != 0) continue; - - for (BedWarsMapsConfig.Position location : limits.locations) { - Pos spawnPos = new Pos(location.x(), location.y(), location.z()); - long currentItemCount = game.getInstanceContainer().getNearbyEntities(spawnPos, 1.5) - .stream() - .filter(ItemEntity.class::isInstance) - .map(ItemEntity.class::cast) - .filter(entity -> entity.getItemStack().material() == limits.material) - .mapToLong(entity -> entity.getItemStack().amount()) - .sum(); - - if (currentItemCount < limits.maxAmount) { - spawnItem(limits.material, limits.amount, spawnPos, Duration.ofSeconds(1)); - } - } - } - } - - private void resetDisplaysIfEventChanged(int diamondDelay, int emeraldDelay) { - if (lastDiamondDelay == diamondDelay && lastEmeraldDelay == emeraldDelay) return; - - for (Map.Entry> e : generatorDisplays.entrySet()) { - int max = e.getKey().equals("diamond") ? diamondDelay : emeraldDelay; - for (GeneratorDisplay d : e.getValue()) { - d.maxCountdown = max; - d.countdown = max; - d.tierDisplay.setText(Component.text(getTierLabelFor(e.getKey())).color(NamedTextColor.YELLOW)); - } - } - - lastDiamondDelay = diamondDelay; - lastEmeraldDelay = emeraldDelay; - } - - private void updateGeneratorDisplays() { - for (List displays : generatorDisplays.values()) { - for (GeneratorDisplay display : displays) { - display.countdown--; - if (display.countdown <= 0) display.countdown = display.maxCountdown; - - display.spawnDisplay.setText(MiniMessage.miniMessage().deserialize( - "Spawns in " + display.countdown + " seconds!")); - } - } - } - - private String getTierLabelFor(String type) { - GameEventPosition e = game.getEventManager().getCurrentEvent(); - int tier = 1; - - if ("diamond".equals(type)) { - if (e == GameEventPosition.DIAMOND_2 || e == GameEventPosition.EMERALD_2) tier = 2; - if (e == GameEventPosition.DIAMOND_3 || e == GameEventPosition.EMERALD_3) tier = 3; - } else if ("emerald".equals(type)) { - if (e == GameEventPosition.EMERALD_2) tier = 2; - if (e == GameEventPosition.EMERALD_3) tier = 3; - } - - return switch (tier) { - case 2 -> "Tier II"; - case 3 -> "Tier III"; - default -> "Tier I"; - }; - } - - private void spawnItem(Material material, int amount, Pos position, Duration pickupDelay) { - ItemStack itemToSpawn = ItemStack.of(material, amount) - .with(DataComponents.CUSTOM_DATA, new CustomData( - CompoundBinaryTag.builder().putBoolean("generator", true).build())); - - ItemEntity itemEntity = new ItemEntity(itemToSpawn); - itemEntity.setPickupDelay(pickupDelay); - itemEntity.setInstance(game.getInstanceContainer(), position); - - if (pickupDelay.equals(Duration.ofSeconds(1))) { - itemEntity.setVelocity(new Vec(0, 0.1, 0)); - } - } - - private Material getMaterialFromType(String materialType) { - @Subst("iron") String type = materialType.toLowerCase(); - return switch (type) { - case "iron" -> Material.IRON_INGOT; - case "gold" -> Material.GOLD_INGOT; - default -> Material.fromKey(Key.key(Key.MINECRAFT_NAMESPACE, type)); - }; - } - - private double calculateForgeMultiplier(Material material, int forgeLevel) { - if (material != Material.IRON_INGOT && material != Material.GOLD_INGOT) return 1.0; - - return switch (forgeLevel) { - case 1 -> 1.5; - case 2 -> 2.0; - case 3, 4 -> 3.0; - default -> 1.0; - }; - } - - public void stopAllGenerators() { - teamGeneratorTasks.values().stream().flatMap(List::stream).forEach(Task::cancel); - teamGeneratorTasks.clear(); - generatorDisplays.clear(); - generatorLimits.clear(); - - if (globalTicker != null) { - globalTicker.cancel(); - globalTicker = null; - } - } - - public void addTeamGeneratorTask(TeamKey teamKey, Task task) { - teamGeneratorTasks.computeIfAbsent(teamKey, k -> new ArrayList<>()).add(task); - } - - @Override - public void onEventChange(GameEventPosition previous, GameEventPosition current) { - resetDisplaysIfEventChanged( - (int) game.getEventManager().getDiamondDelaySeconds(), - (int) game.getEventManager().getEmeraldDelaySeconds()); - } - - private static class GeneratorDisplay { - private final TextDisplayEntity tierDisplay; - private final TextDisplayEntity spawnDisplay; - private int maxCountdown; - private int countdown; - - public GeneratorDisplay(TextDisplayEntity tierDisplay, TextDisplayEntity spawnDisplay, int delay) { - this.tierDisplay = tierDisplay; - this.spawnDisplay = spawnDisplay; - this.maxCountdown = delay; - this.countdown = delay; - } - } - - private record GeneratorLimits(Material material, int amount, int maxAmount, - List locations) { - } -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/TeamManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/TeamManager.java deleted file mode 100644 index 28c3ffdb3..000000000 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/TeamManager.java +++ /dev/null @@ -1,217 +0,0 @@ -package net.swofty.type.bedwarsgame.game; - -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; -import net.minestom.server.component.DataComponents; -import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.EquipmentSlot; -import net.minestom.server.entity.GameMode; -import net.minestom.server.entity.Player; -import net.minestom.server.item.ItemStack; -import net.minestom.server.item.Material; -import net.minestom.server.scoreboard.BelowNameTag; -import net.minestom.server.tag.Tag; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; -import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; -import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import org.tinylog.Logger; - -import java.util.*; -import java.util.stream.Collectors; - -public final class TeamManager { - private final Game game; - private final Map teamBedStatus = new EnumMap<>(TeamKey.class); - private final Map> teamUpgrades = new EnumMap<>(TeamKey.class); - private final Map> teamTraps = new EnumMap<>(TeamKey.class); - - public TeamManager(Game game) { - this.game = game; - } - - public Map assignPlayersToTeams() { - Map configuredTeams = game.getMapEntry().getConfiguration().getTeams(); - Map activeGameTeams = new EnumMap<>(TeamKey.class); - - teamBedStatus.clear(); - configuredTeams.keySet().forEach(teamKey -> teamBedStatus.put(teamKey, false)); - - game.getPlayers().forEach(player -> player.removeTag(Game.ELIMINATED_TAG)); - - List playersToAssign = new ArrayList<>(game.getPlayers()); - Collections.shuffle(playersToAssign); - - List> availableTeams = new ArrayList<>(configuredTeams.entrySet()); - Collections.shuffle(availableTeams); - - int teamSize = Math.max(1, game.getBedwarsGameType().getTeamSize()); - int playerIndex = 0; - BedWarsMapsConfig.Position spectatorPos = game.getMapEntry().getConfiguration().getLocations().getSpectator(); - - for (Map.Entry entry : availableTeams) { - if (playerIndex >= playersToAssign.size()) break; - - TeamKey teamKey = entry.getKey(); - MapTeam team = entry.getValue(); - boolean teamHasPlayers = false; - - for (int memberCount = 0; memberCount < teamSize && playerIndex < playersToAssign.size(); memberCount++) { - Player player = playersToAssign.get(playerIndex); - assignPlayerToTeam(player, teamKey, team, spectatorPos); - playerIndex++; - teamHasPlayers = true; - } - - if (teamHasPlayers) { - activeGameTeams.put(teamKey, team); - } - } - - handleUnassignedPlayers(playersToAssign, playerIndex, spectatorPos); - return activeGameTeams; - } - - private void assignPlayerToTeam(Player player, TeamKey teamKey, MapTeam team, - BedWarsMapsConfig.Position spectatorPos) { - player.setTag(Tag.String("team"), teamKey.name()); - - BedWarsMapsConfig.PitchYawPosition spawnPos = team.getSpawn(); - player.teleport(new Pos(spawnPos.x(), spawnPos.y(), spawnPos.z(), spawnPos.yaw(), spawnPos.pitch())); - player.setRespawnPoint(new Pos(spectatorPos.x(), spectatorPos.y(), spectatorPos.z())); - - player.setGameMode(GameMode.SURVIVAL); - player.getInventory().clear(); - player.getInventory().addItemStack(ItemStack.of(Material.WOODEN_SWORD)); - player.setEnableRespawnScreen(false); - - player.setDisplayName(Component.text(teamKey.chatColor() + "§l" + teamKey.getName() + " §r" + teamKey.chatColor() + player.getUsername())); - player.setBelowNameTag(new BelowNameTag("health", Component.text("20❤", NamedTextColor.RED))); - - equipTeamArmor(player, teamKey); - Logger.info("Assigned player {} to team {}", player.getUsername(), teamKey.getName()); - } - - public void equipTeamArmor(Player player, TeamKey teamKey) { - Integer armorLevel = player.getTag(TypeBedWarsGameLoader.ARMOR_LEVEL_TAG); - if (armorLevel == null) armorLevel = 0; - - Material boots = null; - Material leggings = switch (armorLevel) { - case 1 -> { - boots = Material.CHAINMAIL_BOOTS; - yield Material.CHAINMAIL_LEGGINGS; - } - case 2 -> { - boots = Material.IRON_BOOTS; - yield Material.IRON_LEGGINGS; - } - case 3 -> { - boots = Material.DIAMOND_BOOTS; - yield Material.DIAMOND_LEGGINGS; - } - default -> null; - }; - - net.minestom.server.color.Color minestomColor = new net.minestom.server.color.Color(teamKey.rgb()); - - if (boots != null && leggings != null) { - player.setEquipment(EquipmentSlot.BOOTS, ItemStack.of(boots)); - player.setEquipment(EquipmentSlot.LEGGINGS, ItemStack.of(leggings)); - } else { - player.setEquipment(EquipmentSlot.BOOTS, ItemStack.of(Material.LEATHER_BOOTS).with(DataComponents.DYED_COLOR, minestomColor)); - player.setEquipment(EquipmentSlot.LEGGINGS, ItemStack.of(Material.LEATHER_LEGGINGS).with(DataComponents.DYED_COLOR, minestomColor)); - } - - player.setEquipment(EquipmentSlot.CHESTPLATE, - ItemStack.of(Material.LEATHER_CHESTPLATE).with(DataComponents.DYED_COLOR, minestomColor)); - player.setEquipment(EquipmentSlot.HELMET, - ItemStack.of(Material.LEATHER_HELMET).with(DataComponents.DYED_COLOR, minestomColor)); - } - - private void handleUnassignedPlayers(List playersToAssign, int startIndex, - BedWarsMapsConfig.Position spectatorPos) { - if (startIndex >= playersToAssign.size()) return; - - int unassignedCount = playersToAssign.size() - startIndex; - Logger.warn("{} players were not assigned to teams as all slots were filled.", unassignedCount); - - for (int i = startIndex; i < playersToAssign.size(); i++) { - Player unassignedPlayer = playersToAssign.get(i); - unassignedPlayer.sendMessage(Component.text( - "All team slots were full. You have been moved to spectator.", NamedTextColor.YELLOW)); - unassignedPlayer.setGameMode(GameMode.SPECTATOR); - unassignedPlayer.teleport(new Pos(spectatorPos.x(), spectatorPos.y(), spectatorPos.z())); - } - } - - public int getTeamUpgradeLevel(TeamKey teamKey, String upgradeKey) { - return teamUpgrades.computeIfAbsent(teamKey, k -> new HashMap<>()).getOrDefault(upgradeKey, 0); - } - - public void setTeamUpgradeLevel(TeamKey teamKey, String upgradeKey, int level) { - teamUpgrades.computeIfAbsent(teamKey, k -> new HashMap<>()).put(upgradeKey, level); - } - - public List getTeamTraps(TeamKey teamKey) { - return teamTraps.computeIfAbsent(teamKey, k -> new ArrayList<>()); - } - - public void addTeamTrap(TeamKey teamKey, String trapKey) { - List traps = teamTraps.computeIfAbsent(teamKey, k -> new ArrayList<>()); - if (!traps.contains(trapKey)) { - traps.add(trapKey); - } - } - - public void removeTeamTrap(TeamKey teamKey, String trapKey) { - List traps = teamTraps.get(teamKey); - if (traps != null) { - traps.remove(trapKey); - if (traps.isEmpty()) { - teamTraps.remove(teamKey); - } - } - } - - public List getPlayersOnTeam(TeamKey teamKey) { - return game.getPlayers().stream() - .filter(player -> teamKey.equals(player.getTeamKey()) - && player.isOnline() - && !Boolean.TRUE.equals(player.getTag(Game.ELIMINATED_TAG))) - .collect(Collectors.toList()); - } - - public int countActivePlayersOnTeam(TeamKey teamKey) { - return (int) game.getPlayers().stream() - .filter(player -> teamKey.equals(player.getTeamKey()) - && player.isOnline() - && !Boolean.TRUE.equals(player.getTag(Game.ELIMINATED_TAG))) - .count(); - } - - public TeamKey getTeamKeyByName(String teamName) { - return Arrays.stream(TeamKey.values()) - .filter(k -> k.getName().equalsIgnoreCase(teamName)) - .findFirst() - .orElse(null); - } - - public void recordBedDestroyed(TeamKey teamKey) { - teamBedStatus.put(teamKey, false); - Logger.info("Bed destroyed for team: {}", teamKey.getName()); - } - - public boolean isBedAlive(TeamKey teamKey) { - return teamBedStatus.getOrDefault(teamKey, false); - } - - public void setBedStatus(TeamKey teamKey, boolean alive) { - teamBedStatus.put(teamKey, alive); - } - - public Map getTeamBedStatus() { - return new EnumMap<>(teamBedStatus); - } -} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGame.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGame.java new file mode 100644 index 000000000..862d59ce1 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGame.java @@ -0,0 +1,580 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import lombok.Getter; +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.title.TitlePart; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.GameMode; +import net.minestom.server.event.Event; +import net.minestom.server.instance.InstanceContainer; +import net.minestom.server.instance.block.Block; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.tag.Tag; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.commons.ChatUtility; +import net.swofty.commons.ServerType; +import net.swofty.commons.ServiceType; +import net.swofty.commons.bedwars.BedWarsGameType; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.commons.party.FullParty; +import net.swofty.proxyapi.ProxyService; +import net.swofty.type.bedwarsgame.BedWarsGameScoreboard; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.events.custom.BedDestroyedEvent; +import net.swofty.type.bedwarsgame.replay.BedWarsReplayManager; +import net.swofty.type.bedwarsgame.shop.TeamUpgradeId; +import net.swofty.type.bedwarsgame.shop.TrapId; +import net.swofty.type.bedwarsgame.shop.impl.AxeShopItem; +import net.swofty.type.bedwarsgame.shop.impl.PickaxeShopItem; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.bedwarsgame.user.ExperienceCause; +import net.swofty.type.bedwarsgame.user.TokenCause; +import net.swofty.type.bedwarsgame.util.BedWarsInventoryManipulator; +import net.swofty.type.game.game.AbstractTeamGame; +import net.swofty.type.game.game.CountdownConfig; +import net.swofty.type.game.game.GameState; +import net.swofty.type.game.game.event.GameTeamWinConditionEvent; +import net.swofty.type.game.game.event.PlayerAssignedTeamEvent; +import net.swofty.type.generic.data.datapoints.DatapointBedWarsHotbar; +import net.swofty.type.generic.event.HypixelEventHandler; +import net.swofty.type.generic.i18n.I18n; +import net.swofty.type.generic.party.PartyManager; +import org.tinylog.Logger; + +import java.util.*; + +@Getter +public class BedWarsGame extends AbstractTeamGame { + public static final Tag ELIMINATED_TAG = Tag.Boolean("eliminated"); + + private final BedWarsMapsConfig.MapEntry mapEntry; + private final BedWarsGameType gameType; + + private final BedWarsGeneratorManager generatorManager; + private final BedWarsWorldManager worldManager; + private final BedWarsRespawnHandler respawnHandler; + private final BedWarsGameEventManager gameEventManager; + private final BedWarsReplayManager replayManager; + private final SwappageManager swappageManager; + private final OneBlockManager oneBlockManager; + + private final Map> teamChests = new EnumMap<>(TeamKey.class); + private final Map> enderChests = new HashMap<>(); + private final Map trackers = new HashMap<>(); + + public BedWarsGame( + BedWarsMapsConfig.MapEntry mapEntry, + InstanceContainer instance, + BedWarsGameType gameType + ) { + // these need to happen before super() is called + this.mapEntry = mapEntry; + this.gameType = gameType; + + super(instance, event -> HypixelEventHandler.callCustomEvent((Event) event)); + + // Initialize teams from map config, constrained by game mode team count + List teamKeys = new ArrayList<>(mapEntry.getConfiguration().getTeams().keySet()); + Collections.shuffle(teamKeys); + int teamsToRegister = Math.min(gameType.getTeams(), teamKeys.size()); + for (int i = 0; i < teamsToRegister; i++) { + registerTeam(new BedWarsTeam(teamKeys.get(i))); + } + + // Initialize managers + this.generatorManager = new BedWarsGeneratorManager(this); + this.worldManager = new BedWarsWorldManager(this); + this.respawnHandler = new BedWarsRespawnHandler(this); + this.gameEventManager = new BedWarsGameEventManager(this); + this.swappageManager = new SwappageManager(this); + this.oneBlockManager = new OneBlockManager(this); + + // Initialize replay with service connection + ProxyService replayService = new ProxyService(ServiceType.REPLAY); + this.replayManager = new BedWarsReplayManager(this, replayService); + + // Start scoreboard + BedWarsGameScoreboard.start(this); + } + + @Override + protected CountdownConfig getCountdownConfig() { + return CountdownConfig.withAcceleration(30, 10, getMaxPlayers()); + } + + @Override + public int getMaxPlayers() { + return getTeams().size() * getTeamSize(); + } + + @Override + public int getMinPlayers() { + return getTeamSize() * Math.min(2, getTeams().size()); + } + + @Override + protected int getTeamSize() { + return Math.max(1, gameType.getTeamSize()); + } + + public boolean isBedAlive(TeamKey teamKey) { + return getTeam(teamKey.name()) + .map(BedWarsTeam::isBedAlive) + .orElse(false); + } + + public boolean isPlayerCurrentlyPlaying(UUID playerUuid) { + BedWarsPlayer player = getPlayer(playerUuid).get(); + return getPlayerTeam(playerUuid).isPresent() + && !Boolean.TRUE.equals(player.getTag(ELIMINATED_TAG)) + && !(player.getGameMode() == GameMode.ADVENTURE || player.getGameMode() == GameMode.SPECTATOR) + && !player.isInvisible(); + } + + /** + * Gets players on a specific team. + */ + public List getPlayersOnTeam(TeamKey teamKey) { + return getPlayers().stream() + .filter(p -> teamKey.equals(p.getTeamKey())) + .toList(); + } + + /** + * Gets team traps for a team. + */ + public List getTeamTraps(TeamKey teamKey) { + return getTeam(teamKey.name()) + .map(BedWarsTeam::getTraps) + .orElse(List.of()); + } + + public void equipTeamArmor(BedWarsPlayer player, TeamKey teamKey) { + respawnHandler.equipTeamArmor(player, teamKey); + } + + public void addTeamTrap(TeamKey teamKey, TrapId trapId) { + getTeam(teamKey.name()).ifPresent(team -> team.addTrap(trapId)); + } + + public void swapTeamState(BedWarsTeam first, BedWarsTeam second) { + first.swapState(second); + Map firstChest = teamChests.remove(first.getTeamKey()); + Map secondChest = teamChests.remove(second.getTeamKey()); + if (secondChest != null) teamChests.put(first.getTeamKey(), secondChest); + if (firstChest != null) teamChests.put(second.getTeamKey(), firstChest); + } + + public int getTeamUpgradeLevel(TeamKey teamKey, TeamUpgradeId upgradeId) { + return getTeam(teamKey.name()) + .map(team -> team.getUpgradeLevel(upgradeId)) + .orElse(0); + } + + public void onPlayerRejoin(BedWarsPlayer player, DisconnectedPlayerData data) { + restorePlayerData(player, data.savedData()); + player.setInstance(instance); + + Optional teamOpt = getPlayerTeam(player.getUuid()); + if (teamOpt.isEmpty()) { + player.sendTo(ServerType.BEDWARS_LOBBY); + return; + } + + BedWarsTeam team = teamOpt.get(); + String teamColor = team.getColorCode(); + player.setTeamName(team.getTeamKey()); + + broadcastMessage(Component.text(teamColor + player.getUsername() + " §7reconnected.")); + + if (!team.isBedAlive()) { + setupAsSpectator(player); + } else { + respawnHandler.startRespawn(player); + } + } + + // find a better place for this method + public static void literalSetupSpectator(BedWarsPlayer player) { + player.setGameMode(GameMode.ADVENTURE); + player.setInvisible(true); + player.setFlying(true); + player.getInventory().clear(); + } + + public void setupPlayer(BedWarsPlayer player) { + TeamKey teamKey = player.getTeamKey(); + MapTeam playerTeam = getMapEntry().getConfiguration().getTeams().get(teamKey); + HypixelPosition spawnPos = playerTeam.getSpawn(); + Pos spawnPoint = new Pos(spawnPos.x(), spawnPos.y(), spawnPos.z(), spawnPos.pitch(), spawnPos.yaw()); + + player.getInventory().clear(); + player.clearTitle(); + player.setVelocity(Vec.ZERO); // prevent high velocity movement on respawn + player.teleport(spawnPoint); + player.setRespawnPoint(spawnPoint); + player.setGameMode(GameMode.SURVIVAL); + player.setInvisible(false); + player.setFlying(false); + BedWarsInventoryManipulator.addItemWithHotbarPriority(player, ItemStack.of(Material.WOODEN_SWORD), DatapointBedWarsHotbar.HotbarItemType.MELEE); + player.setHealth(20f); + player.setFood(20); + equipTeamArmor(player, teamKey); + + // Give back the downgraded tools + AxeShopItem axeShopItem = new AxeShopItem(); + Integer currentAxeLevel = player.getTag(AxeShopItem.AXE_UPGRADE_TAG); + if (currentAxeLevel != null && currentAxeLevel > 0) { + BedWarsInventoryManipulator.addItemWithHotbarPriority(player, + ItemStack.of(axeShopItem.getTier(currentAxeLevel - 1).material()), + DatapointBedWarsHotbar.HotbarItemType.AXE); + } + + PickaxeShopItem pickaxeShopItem = new PickaxeShopItem(); + Integer currentPickaxeLevel = player.getTag(PickaxeShopItem.PICKAXE_UPGRADE_TAG); + if (currentPickaxeLevel != null && currentPickaxeLevel > 0) { + BedWarsInventoryManipulator.addItemWithHotbarPriority(player, + ItemStack.of(pickaxeShopItem.getTier(currentPickaxeLevel - 1).material()), + DatapointBedWarsHotbar.HotbarItemType.PICKAXE); + } + + if (gameType != BedWarsGameType.ONE_EIGHT) { + BedWarsInventoryManipulator.addItemWithHotbarPriority(player, TypeBedWarsGameLoader.getItemHandler().getItem("compass").getItemStack(), + DatapointBedWarsHotbar.HotbarItemType.COMPASS); + } + + // equip the player with team armor + equipTeamArmor(player, teamKey); + + Integer protectionLevel = player.getTag(TeamUpgradeId.REINFORCED_ARMOR.levelTag()); + if (protectionLevel != null) { + TypeBedWarsGameLoader.getTeamShopManager().getUpgrade(TeamUpgradeId.REINFORCED_ARMOR).applyEffect(this, teamKey, protectionLevel); + } + + Integer cushionedBootsLevel = player.getTag(TeamUpgradeId.CUSHIONED_BOOTS.levelTag()); + if (cushionedBootsLevel != null) { + TypeBedWarsGameLoader.getTeamShopManager().getUpgrade(TeamUpgradeId.CUSHIONED_BOOTS).applyEffect(this, teamKey, cushionedBootsLevel); + } + + Integer sharpnessLevel = player.getTag(TeamUpgradeId.SHARPNESS.levelTag()); + if (sharpnessLevel != null) { + TypeBedWarsGameLoader.getTeamShopManager().getUpgrade(TeamUpgradeId.SHARPNESS).applyEffect(this, teamKey, sharpnessLevel); + } + } + + @Override + protected boolean canPlayerRejoin(BedWarsPlayer player) { + return getPlayerTeam(player.getUuid()) + .map(BedWarsTeam::isBedAlive) + .orElse(false); + } + + @Override + protected Map savePlayerData(BedWarsPlayer player) { + Map data = new HashMap<>(); + data.put("armorLevel", player.getTag(TypeBedWarsGameLoader.ARMOR_LEVEL_TAG)); + return data; + } + + protected void restorePlayerData(BedWarsPlayer player, Map savedData) { + Integer armorLevel = (Integer) savedData.get("armorLevel"); + if (armorLevel != null) { + player.setTag(TypeBedWarsGameLoader.ARMOR_LEVEL_TAG, armorLevel); + } + } + + @Override + protected boolean isTeamViable(BedWarsTeam team) { + // Team is viable if bed is alive OR has active players OR has rejoinable disconnected players + if (team.isBedAlive()) return true; + + boolean hasActivePlayers = getPlayers().stream() + .anyMatch(p -> team.hasPlayer(p.getUuid()) && !Boolean.TRUE.equals(p.getTag(ELIMINATED_TAG))); + + boolean hasRejoinablePlayers = disconnectedPlayers.values().stream() + .anyMatch(info -> { + Optional t = getPlayerTeam(info.uuid()); + return t.isPresent() && t.get().getId().equals(team.getId()) && team.isBedAlive(); + }); + + return hasActivePlayers || hasRejoinablePlayers; + } + + public void onBedDestroyed(TeamKey teamKey, BedWarsPlayer destroyer) { + getTeam(teamKey.name()).ifPresent(team -> { + team.destroyBed(); + MapTeam mapTeam = mapEntry.getConfiguration().getTeams().get(teamKey); + if (mapTeam == null) { + Logger.error("No map team configuration found for team {}", teamKey.name()); + return; + } + BedWarsMapsConfig.TwoBlockPosition bedPos = mapTeam.getBed(); + if (bedPos == null || bedPos.feet() == null || bedPos.head() == null) { + Logger.error("No bed position found for team {}", teamKey.name()); + return; + } + + destroyer.getInstance().setBlock(bedPos.feet().asBlockVec(), Block.AIR); + destroyer.getInstance().setBlock(bedPos.head().asBlockVec(), Block.AIR); + + // Record to replay + if (replayManager.isRecording()) { + replayManager.recordBedDestroyed(teamKey, destroyer); + } + + eventDispatcher.accept(new BedDestroyedEvent( + gameId, + teamKey, + destroyer + )); + + checkWinConditions(); + }); + } + + /** + * Respawns a team's bed. Usually an admin action, Lucky Block Bed Wars beds can be placed at any location, + * which isn't supported yet. + */ + public void respawnBed(TeamKey teamKey) { + getTeam(teamKey.name()).ifPresent(team -> { + team.setBedAlive(true); + + // Place the bed blocks back + worldManager.placeBedForTeam(teamKey, mapEntry.getConfiguration().getTeams().get(teamKey)); + + // Record to replay + if (replayManager.isRecording()) { + replayManager.recordBedRespawned(teamKey); + } + + broadcastMessage(Component.text(teamKey.chatColor() + "Team " + teamKey.getName() + "'s §abed has been respawned!")); + }); + } + + public void onPlayerEliminated(BedWarsPlayer player) { + player.setTag(ELIMINATED_TAG, true); + setupAsSpectator(player); + checkWinConditions(); + + getPlayerTeam(player.getUuid()).ifPresent(team -> { + boolean allEliminated = getPlayers().stream() + .filter(p -> team.hasPlayer(p.getUuid())) + .allMatch(p -> Boolean.TRUE.equals(p.getTag(ELIMINATED_TAG))); + + boolean allDisconnectedOrEliminated = getPlayers().stream() + .filter(p -> team.hasPlayer(p.getUuid())) + .allMatch(p -> Boolean.TRUE.equals(p.getTag(ELIMINATED_TAG)) || !isPlayerCurrentlyPlaying(p.getUuid())); + + if (allEliminated || allDisconnectedOrEliminated) { + onTeamEliminated(team); + } + }); + } + + private void setupAsSpectator(BedWarsPlayer player) { + player.setGameMode(GameMode.ADVENTURE); + player.setInvisible(true); + player.setFlying(true); + player.setAllowFlying(true); + player.updateBelowTag(); + + if (replayManager.isRecording()) { + replayManager.recordPlayerInvisibility(player, true); + } + + HypixelPosition spectatorPos = mapEntry.getConfiguration().getLocations().getSpectator(); + if (spectatorPos != null) { + player.teleport(new Pos(spectatorPos.x(), spectatorPos.y(), spectatorPos.z())); + } + + player.sendTitlePart(TitlePart.TITLE, Component.text("SPECTATING", NamedTextColor.GRAY)); + player.sendTitlePart(TitlePart.SUBTITLE, Component.text("Your bed was destroyed.", NamedTextColor.RED)); + + player.getInventory().setItemStack(0, TypeBedWarsGameLoader.getItemHandler().getItem("teleporter").getItemStack()); + player.getInventory().setItemStack(4, TypeBedWarsGameLoader.getItemHandler().getItem("spectator_settings").getItemStack()); + player.getInventory().setItemStack(7, TypeBedWarsGameLoader.getItemHandler().getItem("play_again").getItemStack()); + player.getInventory().setItemStack(8, TypeBedWarsGameLoader.getItemHandler().getItem("leave_game").getItemStack()); + } + + public Map getActiveTeamConfigs() { + Map configs = new EnumMap<>(TeamKey.class); + Map allTeamConfigs = mapEntry.getConfiguration().getTeams(); + + for (BedWarsTeam team : getActiveTeams()) { + TeamKey key = team.getTeamKey(); + if (allTeamConfigs.containsKey(key)) { + configs.put(key, allTeamConfigs.get(key)); + } + } + + return configs; + } + + public void teleportPlayersToSpawns() { + Map teamConfigs = mapEntry.getConfiguration().getTeams(); + + for (BedWarsPlayer player : getPlayers()) { + getPlayerTeam(player.getUuid()).ifPresent(team -> { + MapTeam config = teamConfigs.get(team.getTeamKey()); + if (config != null) { + setupPlayer(player); + player.reveal(); + player.setDisplayName(Component.text( + team.getColorCode() + "§l" + team.firstLetter() + " §r" + team.getColorCode() + player.getUsername() + )); + } + }); + } + } + + public void startTimePlayedRewards() { + MinecraftServer.getSchedulerManager().buildTask(() -> { + if (state != GameState.IN_PROGRESS) return; + for (BedWarsPlayer player : getPlayers()) { + if (Boolean.TRUE.equals(player.getTag(ELIMINATED_TAG))) continue; // Skip eliminated spectators + player.token(TokenCause.TIME_PLAYED); + player.xp(ExperienceCause.TIME_PLAYED); + } + }).delay(TaskSchedule.minutes(1)).repeat(TaskSchedule.minutes(1)).schedule(); + } + + // this is per game type, dreams modes have different looks + public void sendGameStartMessage() { + String line = "■".repeat(50); + List messages = new ArrayList<>(); + messages.add(Component.text(line, NamedTextColor.GREEN)); + messages.add(Component.text(ChatUtility.FontInfo.center("§l" + I18n.string(gameType.getGameStartTitleKey())), NamedTextColor.WHITE)); + messages.add(Component.space()); + ChatUtility.FontInfo.wrap(I18n.string(gameType.getGameStartDescriptionKey())) + .forEach(message -> messages.add(Component.text(ChatUtility.FontInfo.center(message), NamedTextColor.YELLOW))); + messages.add(Component.space()); + messages.add(Component.text(line, NamedTextColor.GREEN)); + Audience audience = Audience.audience(getPlayers()); + for (Component msg : messages) { + audience.sendMessage(msg); + } + } + + public List getDisconnectedPlayerUuids() { + return new ArrayList<>(disconnectedPlayers.keySet()); + } + + @Override + public void autoAssignTeams() { + List unassignedPlayers = getPlayers().stream() + .filter(player -> !playerTeams.containsKey(player.getUuid())) + .toList(); + + if (unassignedPlayers.isEmpty() || getTeams().isEmpty()) { + return; + } + + Map playersByUuid = new HashMap<>(); + for (BedWarsPlayer player : unassignedPlayers) { + playersByUuid.put(player.getUuid(), player); + } + + List> groups = new ArrayList<>(); + Set processed = new HashSet<>(); + + for (BedWarsPlayer player : unassignedPlayers) { + if (!processed.add(player.getUuid())) { + continue; + } + + List group = new ArrayList<>(); + FullParty party = PartyManager.getPartyFromPlayer(player); + if (party != null) { + for (UUID partyMemberUuid : party.getParticipants()) { + BedWarsPlayer member = playersByUuid.get(partyMemberUuid); + if (member != null) { + group.add(member); + } + } + } + + if (group.isEmpty()) { + group.add(player); + } + + for (BedWarsPlayer member : group) { + processed.add(member.getUuid()); + } + groups.add(group); + } + + Collections.shuffle(groups); + groups.sort(Comparator.comparingInt((List group) -> group.size()).reversed()); + + List shuffledTeams = new ArrayList<>(getTeams()); + Collections.shuffle(shuffledTeams); + + Map teamPriority = new HashMap<>(); + for (int i = 0; i < shuffledTeams.size(); i++) { + teamPriority.put(shuffledTeams.get(i).getId(), i); + } + + for (List group : groups) { + BedWarsTeam targetTeam = selectTargetTeam(group.size(), teamPriority); + if (targetTeam != null) { + assignGroupToTeam(group, targetTeam); + continue; + } + + for (BedWarsPlayer member : group) { + BedWarsTeam fallbackTeam = selectTargetTeam(1, teamPriority); + if (fallbackTeam == null) { + break; + } + assignPlayerToTeam(member, fallbackTeam); + } + } + } + + private BedWarsTeam selectTargetTeam(int requiredSlots, Map teamPriority) { + return getTeams().stream() + .filter(team -> team.getPlayerCount() + requiredSlots <= getTeamSize()) + .min(Comparator + .comparingInt(BedWarsTeam::getPlayerCount) + .thenComparingInt(team -> teamPriority.getOrDefault(team.getId(), Integer.MAX_VALUE))) + .orElse(null); + } + + private void assignGroupToTeam(List players, BedWarsTeam team) { + for (BedWarsPlayer player : players) { + assignPlayerToTeam(player, team); + } + } + + private void assignPlayerToTeam(BedWarsPlayer player, BedWarsTeam team) { + reassignPlayer(player.getUuid(), team); + } + + public void reassignPlayer(UUID playerId, BedWarsTeam team) { + getPlayerTeam(playerId).ifPresent(current -> current.removePlayer(playerId)); + team.addPlayer(playerId); + playerTeams.put(playerId, team.getId()); + getPlayer(playerId).ifPresent(player -> eventDispatcher.accept(new PlayerAssignedTeamEvent<>( + gameId, player.getServerPlayer(), team + ))); + } + + // widens access modifier + @Override + public void checkWinConditions() { + super.checkWinConditions(); + } + + public void forceGameEnd() { + HypixelEventHandler.callCustomEvent(new GameTeamWinConditionEvent(gameId, Optional.empty())); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGameEventManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGameEventManager.java new file mode 100644 index 000000000..5e3796710 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGameEventManager.java @@ -0,0 +1,156 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minestom.server.MinecraftServer; +import net.minestom.server.timer.Task; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.type.bedwarsgame.events.custom.BedWarsGameEventAdvanceEvent; +import net.swofty.type.game.game.GameState; +import net.swofty.type.generic.event.HypixelEventHandler; + +@RequiredArgsConstructor +public class BedWarsGameEventManager { + private final BedWarsGame game; + + @Getter + private GamePhase currentPhase = GamePhase.NONE; + @Getter + private long secondsUntilNextPhase = 0; + + private Task ticker; + + public enum GamePhase { + NONE("None", 0, 30, 60), + DIAMOND_II("Diamond II", 6 * 60, 30, 60), + EMERALD_II("Emerald II", 2 * 6 * 60, 30, 60), + DIAMOND_III("Diamond III", 3 * 6 * 60, 30, 60), + EMERALD_III("Emerald III", 4 * 6 * 60, 30, 60), + BED_DESTRUCTION("Bed Destruction", 5 * 6 * 60, 30, 60), + SUDDEN_DEATH("Sudden Death", 5 * 6 * 60 + 10 * 60, 30, 60), + GAME_END("Game End", 5 * 6 * 60 + 20 * 60, 30, 60); + + @Getter + private final String displayName; + @Getter + private final int triggerTimeSeconds; + @Getter + private final int diamondSpawnSeconds; + @Getter + private final int emeraldSpawnSeconds; + + GamePhase(String displayName, int triggerTime, int diamondSpawn, int emeraldSpawn) { + this.displayName = displayName; + this.triggerTimeSeconds = triggerTime; + this.diamondSpawnSeconds = diamondSpawn; + this.emeraldSpawnSeconds = emeraldSpawn; + } + + public GamePhase next() { + int ordinal = this.ordinal(); + GamePhase[] values = values(); + return ordinal < values.length - 1 ? values[ordinal + 1] : this; + } + } + + public void start() { + if (ticker != null) return; + + currentPhase = GamePhase.NONE; + if (game.getGameType().isOneBlock()) { + currentPhase = GamePhase.SUDDEN_DEATH; + secondsUntilNextPhase = 5 * 60; + ticker = MinecraftServer.getSchedulerManager().buildTask(this::tick) + .delay(TaskSchedule.seconds(1)) + .repeat(TaskSchedule.seconds(1)) + .schedule(); + return; + } + secondsUntilNextPhase = + currentPhase.next().getTriggerTimeSeconds() + - currentPhase.getTriggerTimeSeconds(); + + ticker = MinecraftServer.getSchedulerManager().buildTask(this::tick) + .delay(TaskSchedule.seconds(1)) + .repeat(TaskSchedule.seconds(1)) + .schedule(); + } + + public void stop() { + if (ticker != null) { + ticker.cancel(); + ticker = null; + } + } + + private void tick() { + if (game.getState() != GameState.IN_PROGRESS) { + stop(); + return; + } + + secondsUntilNextPhase--; + + if (game.getGameType().isOneBlock()) return; + if (secondsUntilNextPhase <= 0) { + advancePhase(); + } + } + + public void endOneBlockGame() { + currentPhase = GamePhase.GAME_END; + secondsUntilNextPhase = 0; + game.forceGameEnd(); + } + + private void advancePhase() { + GamePhase previous = currentPhase; + currentPhase = currentPhase.next(); + + if (currentPhase != previous) { + secondsUntilNextPhase = currentPhase.next() != currentPhase + ? currentPhase.getTriggerTimeSeconds() + : Integer.MAX_VALUE; + + // Fire event + HypixelEventHandler.callCustomEvent(new BedWarsGameEventAdvanceEvent( + game.getGameId(), + previous.getDisplayName(), + currentPhase.getDisplayName(), + secondsUntilNextPhase + )); + + // Handle special phases + if (currentPhase == GamePhase.BED_DESTRUCTION) { + destroyAllBeds(); + } + } + } + + private void destroyAllBeds() { + // Would destroy all remaining beds and fire events + for (BedWarsTeam team : game.getTeams()) { + if (team.isBedAlive()) { + team.destroyBed(); + } + } + } + + public int getDiamondSpawnSeconds() { + return currentPhase.getDiamondSpawnSeconds(); + } + + public int getEmeraldSpawnSeconds() { + return currentPhase.getEmeraldSpawnSeconds(); + } + + @Deprecated(forRemoval = true) + public GamePhase getNextEvent() { + GamePhase next = currentPhase.next(); + return next != currentPhase ? next : null; + } + + public GamePhase getCurrentEvent() { + return currentPhase; + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGeneratorManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGeneratorManager.java new file mode 100644 index 000000000..2780b40f1 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsGeneratorManager.java @@ -0,0 +1,431 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.ItemEntity; +import net.minestom.server.instance.block.Block; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.timer.Task; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.commons.StringUtility; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.entity.TextDisplayEntity; +import net.swofty.type.bedwarsgame.item.impl.LuckyBlockItem; +import net.swofty.type.bedwarsgame.item.impl.LuckyBlockTier; +import net.swofty.type.bedwarsgame.shop.TeamUpgradeId; +import net.swofty.type.game.game.GameState; +import net.swofty.type.generic.entity.FloatingBlockEntity; +import org.tinylog.Logger; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +public class BedWarsGeneratorManager { + private final BedWarsGame game; + private final Map> teamGeneratorTasks = new EnumMap<>(TeamKey.class); + private final Map> generatorDisplays = new HashMap<>(); + private final Map generatorLimits = new HashMap<>(); + private Task globalTicker; + + public BedWarsGeneratorManager(BedWarsGame game) { + this.game = game; + } + + public void startTeamGenerators(Map activeTeams) { + BedWarsMapsConfig.MapEntry.MapConfiguration mapConfig = game.getMapEntry().getConfiguration(); + BedWarsMapsConfig.GeneratorSpeed generatorSpeed = mapConfig.getGeneratorSpeed(); + + if (generatorSpeed == null) { + Logger.warn("No generator speed configured for map"); + return; + } + + activeTeams.forEach((teamKey, team) -> { + HypixelPosition genLocation = team.getGenerator(); + if (genLocation == null) return; + + Pos spawnPosition = new Pos(genLocation.x(), genLocation.y(), genLocation.z()); + + // Start iron generator + startTeamGenerator(teamKey, BedWarsMapsConfig.GlobalGeneratorKey.IRON, generatorSpeed.getIronAmount(), + generatorSpeed.getIronDelaySeconds(), spawnPosition); + + // Start gold generator + startTeamGenerator(teamKey, BedWarsMapsConfig.GlobalGeneratorKey.GOLD, generatorSpeed.getGoldAmount(), + generatorSpeed.getGoldDelaySeconds(), spawnPosition); + }); + } + + // material type being string is annoying + private void startTeamGenerator(TeamKey teamKey, BedWarsMapsConfig.GlobalGeneratorKey materialType, + int baseAmount, int baseDelay, Pos spawnPosition) { + Material itemMaterial = getMaterialFromType(materialType); + if (itemMaterial == null) { + Logger.warn("Invalid material type: {} for team {}", materialType, teamKey.getName()); + return; + } + + AtomicInteger spawnRound = new AtomicInteger(); + Task task = MinecraftServer.getSchedulerManager().buildTask(() -> { + if (game.getState() != GameState.IN_PROGRESS) return; + + int forgeLevel = game.getTeamUpgradeLevel(teamKey, TeamUpgradeId.FORGE); + double multiplier = calculateForgeMultiplier(itemMaterial, forgeLevel); + + int finalAmount = (int) Math.round(baseAmount * multiplier); + if (finalAmount == 0 && baseAmount > 0 && multiplier > 1.0) finalAmount = 1; + + if (finalAmount > 0) { + if (game.getGameType().isLuckyBlock()) { + LuckyBlockTier tier = switch (spawnRound.getAndIncrement()) { + case 4 -> LuckyBlockTier.NORMAL; // not official timing + case 5 -> LuckyBlockTier.PROMISING; + default -> null; + }; + if (tier == null) return; + + LuckyBlockItem luckyBlock = (LuckyBlockItem) TypeBedWarsGameLoader.getItemHandler().getItem("lucky_block"); + spawnItem(luckyBlock.getItemStack(tier), 1, spawnPosition); + } + spawnItem(itemMaterial, finalAmount, spawnPosition); + } + + if (spawnRound.get() > 7) spawnRound.set(0); // not official timing + }).delay(TaskSchedule.seconds(baseDelay)).repeat(TaskSchedule.seconds(baseDelay)).schedule(); + + teamGeneratorTasks.computeIfAbsent(teamKey, _ -> new ArrayList<>()).add(task); + } + + public void startGlobalGenerators() { + BedWarsMapsConfig.MapEntry.MapConfiguration mapConfig = game.getMapEntry().getConfiguration(); + if (mapConfig.getGlobalGenerator() == null) return; + + mapConfig.getGlobalGenerator().forEach(this::setupGlobalGenerator); + + if (globalTicker != null) globalTicker.cancel(); + globalTicker = MinecraftServer.getSchedulerManager().buildTask(() -> { + updateGeneratorDisplays(); + tickGlobalGenerators(); + }).delay(TaskSchedule.seconds(1)).repeat(TaskSchedule.seconds(1)).schedule(); + } + + public void recordInitialGeneratorDisplays() { + if (!game.getReplayManager().isRecording()) return; + + for (Map.Entry> entry : generatorDisplays.entrySet()) { + BedWarsMapsConfig.GlobalGeneratorKey generatorType = entry.getKey(); + String tierLabel = getTierLabelFor(generatorType); + String capitalizedType = StringUtility.capitalize(generatorType.name()); + + List displays = entry.getValue(); + for (int i = 0; i < displays.size(); i++) { + GeneratorDisplay display = displays.get(i); + Pos position = display.spawnDisplay.getPosition(); + List textLines = List.of( + "§e" + tierLabel, + (generatorType.equals(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND) ? "§b§l" : "§2§l") + capitalizedType, + "§eSpawns in §c" + display.countdown + "§e seconds!" + ); + + game.getReplayManager().recordGeneratorDisplay( + display.spawnDisplay.getEntityId(), + display.spawnDisplay.getUuid(), + position, + textLines, + "generator", + generatorType + "_" + i + ); + } + } + } + + private void setupGlobalGenerator(BedWarsMapsConfig.GlobalGeneratorKey generatorType, BedWarsMapsConfig.MapEntry.MapConfiguration.GlobalGenerator config) { + Material itemMaterial = getMaterialFromType(generatorType); + if (itemMaterial == null) { + Logger.warn("Invalid material for global generator: {}", generatorType); + return; + } + + List locations = config.getLocations(); + if (locations == null || locations.isEmpty()) return; + + boolean isDiamond = generatorType.equals(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND); + int delaySeconds = isDiamond + ? game.getGameEventManager().getCurrentPhase().getDiamondSpawnSeconds() + : game.getGameEventManager().getCurrentPhase().getEmeraldSpawnSeconds(); + int maxAmount = isDiamond + ? game.getMapEntry().getConfiguration().getGeneratorSpeed().diamondMax + : game.getMapEntry().getConfiguration().getGeneratorSpeed().emeraldMax; + + setupGlobalGeneratorDisplays(generatorType, locations, delaySeconds); + generatorLimits.put(generatorType, new GeneratorLimits( + itemMaterial, 1, maxAmount, locations)); + } + + private void setupGlobalGeneratorDisplays(BedWarsMapsConfig.GlobalGeneratorKey generatorType, List locations, int delaySeconds) { + boolean isDiamond = generatorType.equals(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND); + NamedTextColor color = isDiamond ? NamedTextColor.AQUA : NamedTextColor.DARK_GREEN; + String capitalizedType = StringUtility.capitalize(generatorType.name()); + + for (HypixelPosition location : locations) { + double locY = location.y() + 5.0; + + TextDisplayEntity tierDisplay = new TextDisplayEntity( + Component.text("Tier I").color(NamedTextColor.YELLOW)); + tierDisplay.setInstance(game.getInstance(), new Pos(location.x(), locY, location.z())); + + locY -= 0.3; + TextDisplayEntity titleDisplay = new TextDisplayEntity( + Component.text(capitalizedType).color(color).decorate(TextDecoration.BOLD)); + titleDisplay.setInstance(game.getInstance(), new Pos(location.x(), locY, location.z())); + + locY -= 0.3; + TextDisplayEntity spawnDisplay = new TextDisplayEntity( + MiniMessage.miniMessage().deserialize("Spawns in " + delaySeconds + " seconds!")); + spawnDisplay.setInstance(game.getInstance(), new Pos(location.x(), locY, location.z())); + + float size = 0.6f; + locY -= size + 0.1 + 0.25; + FloatingBlockEntity blockDisplay = new FloatingBlockEntity( + getBlockFromType(generatorType), + size, + game.getInstance(), + new Pos(location.x(), locY, location.z()) + ); + blockDisplay.startAnimation(); + + generatorDisplays.computeIfAbsent(generatorType, _ -> new ArrayList<>()) + .add(new GeneratorDisplay(tierDisplay, titleDisplay, spawnDisplay, blockDisplay, delaySeconds)); + + if (game.getReplayManager().isRecording()) { + List textLines = List.of( + "§eTier I", + (isDiamond ? "§b§l" : "§2§l") + capitalizedType, + "§eSpawns in §c" + delaySeconds + "§e seconds!" + ); + game.getReplayManager().recordGeneratorDisplay( + spawnDisplay.getEntityId(), + spawnDisplay.getUuid(), + spawnDisplay.getPosition(), + textLines, + "generator", + generatorType + "_" + locations.indexOf(location) + ); + } + } + } + + private void tickGlobalGenerators() { + for (Map.Entry entry : generatorLimits.entrySet()) { + BedWarsMapsConfig.GlobalGeneratorKey type = entry.getKey(); + GeneratorLimits limits = entry.getValue(); + List displays = generatorDisplays.get(type); + + if (displays == null || displays.isEmpty()) continue; + + for (int i = 0; i < limits.locations.size(); i++) { + HypixelPosition location = limits.locations.get(i); + GeneratorDisplay display = i < displays.size() ? displays.get(i) : null; + + if (display == null) continue; + + display.countdown--; + if (display.countdown <= 0) { + Pos spawnPos = new Pos(location.x(), location.y() + 1, location.z()); + long currentItemCount = game.getInstance().getNearbyEntities(spawnPos, 1.5) + .stream() + .filter(ItemEntity.class::isInstance) + .map(ItemEntity.class::cast) + .filter(entity -> entity.getItemStack().material() == limits.material) + .mapToLong(entity -> entity.getItemStack().amount()) + .sum(); + + if (game.getGameType().isLuckyBlock()) { + display.round++; + + if (display.round % 4 != 0) continue; // not official timing + + boolean isDiamond = type.equals(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND); + boolean isEmerald = type.equals(BedWarsMapsConfig.GlobalGeneratorKey.EMERALD); + + LuckyBlockItem luckyBlock = (LuckyBlockItem) TypeBedWarsGameLoader.getItemHandler().getItem("lucky_block"); + if (isDiamond) { + spawnItem(luckyBlock.getItemStack(LuckyBlockTier.FORTUNATE), 1, spawnPos); + spawnItem(luckyBlock.getItemStack(LuckyBlockTier.OFFENSIVE), 1, spawnPos); + } + if (isEmerald) { + spawnItem(luckyBlock.getItemStack(LuckyBlockTier.MIRACLE), 1, spawnPos); + } + } + + if (currentItemCount < limits.maxAmount) { + spawnItem(limits.material, limits.amount, spawnPos); + } + + display.countdown = display.maxCountdown; + } + } + } + } + + private void updateGeneratorDisplays() { + for (List displays : generatorDisplays.values()) { + for (GeneratorDisplay display : displays) { + String newText = "§eSpawns in §c" + display.countdown + "§e seconds!"; + display.spawnDisplay.setText(MiniMessage.miniMessage().deserialize( + "Spawns in " + display.countdown + " seconds!")); + + // Record display update for replay + if (game.getReplayManager().isRecording()) { + game.getReplayManager().recordTextDisplayUpdate( + display.spawnDisplay.getEntityId(), + List.of(newText), + false, + 2 // Update third line (spawn timer) + ); + } + } + } + } + + public void updateDisplaysForEventChange() { + for (Map.Entry> e : generatorDisplays.entrySet()) { + int max = e.getKey().equals(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND) + ? game.getGameEventManager().getDiamondSpawnSeconds() + : game.getGameEventManager().getEmeraldSpawnSeconds(); + + String tierLabel = getTierLabelFor(e.getKey()); + + for (GeneratorDisplay d : e.getValue()) { + d.maxCountdown = max; + d.countdown = max; + d.tierDisplay.setText(Component.text(tierLabel).color(NamedTextColor.YELLOW)); + } + } + } + + private String getTierLabelFor(BedWarsMapsConfig.GlobalGeneratorKey type) { + BedWarsGameEventManager.GamePhase phase = game.getGameEventManager().getCurrentPhase(); + int tier = 1; + + if (type.equals(BedWarsMapsConfig.GlobalGeneratorKey.DIAMOND)) { + if (phase.ordinal() >= BedWarsGameEventManager.GamePhase.DIAMOND_II.ordinal()) tier = 2; + if (phase.ordinal() >= BedWarsGameEventManager.GamePhase.DIAMOND_III.ordinal()) tier = 3; + } else if (type.equals(BedWarsMapsConfig.GlobalGeneratorKey.EMERALD)) { + if (phase.ordinal() >= BedWarsGameEventManager.GamePhase.EMERALD_II.ordinal()) tier = 2; + if (phase.ordinal() >= BedWarsGameEventManager.GamePhase.EMERALD_III.ordinal()) tier = 3; + } + + return switch (tier) { + case 2 -> "Tier II"; + case 3 -> "Tier III"; + default -> "Tier I"; + }; + } + + public void stopAllGenerators() { + teamGeneratorTasks.values().stream().flatMap(List::stream).forEach(Task::cancel); + teamGeneratorTasks.clear(); + + // Remove all display entities + for (List displays : generatorDisplays.values()) { + for (GeneratorDisplay display : displays) { + display.tierDisplay.remove(); + display.titleDisplay.remove(); + display.spawnDisplay.remove(); + display.blockDisplay.remove(); + } + } + generatorDisplays.clear(); + generatorLimits.clear(); + + if (globalTicker != null) { + globalTicker.cancel(); + globalTicker = null; + } + } + + private void spawnItem(Material material, int amount, Pos position) { + spawnItem(ItemStack.of(material), amount, position); + } + + private void spawnItem(ItemStack stack, int amount, Pos position) { + ItemStack item = stack.withAmount(amount); + ItemEntity entity = new ItemEntity(item); + entity.setPickupDelay(Duration.ofMillis(500)); + entity.setInstance(game.getInstance(), position); + entity.setVelocity(new Vec(0, 0.1, 0)); + } + + private Material getMaterialFromType(BedWarsMapsConfig.GlobalGeneratorKey type) { + return switch (type) { + case IRON -> Material.IRON_INGOT; + case GOLD -> Material.GOLD_INGOT; + case DIAMOND -> Material.DIAMOND; + case EMERALD -> Material.EMERALD; + }; + } + + private Block getBlockFromType(BedWarsMapsConfig.GlobalGeneratorKey type) { + return switch (type) { + case IRON -> Block.IRON_BLOCK; + case GOLD -> Block.GOLD_BLOCK; + case DIAMOND -> Block.DIAMOND_BLOCK; + case EMERALD -> Block.EMERALD_BLOCK; + }; + } + + private double calculateForgeMultiplier(Material material, int forgeLevel) { + if (material != Material.IRON_INGOT && material != Material.GOLD_INGOT) return 1.0; + + return switch (forgeLevel) { + case 1 -> 1.5; + case 2 -> 2.0; + case 3, 4 -> 3.0; + default -> 1.0; + }; + } + + public void addTeamGeneratorTask(TeamKey teamKey, Task task) { + teamGeneratorTasks.computeIfAbsent(teamKey, _ -> new ArrayList<>()).add(task); + } + + private static class GeneratorDisplay { + private final TextDisplayEntity tierDisplay; + private final TextDisplayEntity titleDisplay; + private final TextDisplayEntity spawnDisplay; + private final FloatingBlockEntity blockDisplay; + private int maxCountdown; + private int countdown; + private int round = 0; + + public GeneratorDisplay(TextDisplayEntity tierDisplay, TextDisplayEntity titleDisplay, + TextDisplayEntity spawnDisplay, FloatingBlockEntity blockDisplay, int delay) { + this.tierDisplay = tierDisplay; + this.titleDisplay = titleDisplay; + this.spawnDisplay = spawnDisplay; + this.blockDisplay = blockDisplay; + this.maxCountdown = delay; + this.countdown = delay; + } + } + + private record GeneratorLimits(Material material, int amount, int maxAmount, + List locations) { + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsRespawnHandler.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsRespawnHandler.java new file mode 100644 index 000000000..0852e3a16 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsRespawnHandler.java @@ -0,0 +1,175 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import lombok.RequiredArgsConstructor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.title.Title; +import net.minestom.server.MinecraftServer; +import net.minestom.server.color.Color; +import net.minestom.server.component.DataComponents; +import net.minestom.server.entity.EquipmentSlot; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.timer.Task; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.respawn.RespawnHandler; + +import java.time.Duration; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +@RequiredArgsConstructor +public class BedWarsRespawnHandler implements RespawnHandler { + private static final int DEFAULT_RESPAWN_DELAY = 5; + + private final BedWarsGame game; + private final Map respawnTasks = new ConcurrentHashMap<>(); + + @Override + public boolean canRespawn(UUID playerId) { + return game.getPlayerTeam(playerId) + .map(BedWarsTeam::isBedAlive) + .orElse(false); + } + + @Override + public int getRespawnDelay(UUID playerId) { + return DEFAULT_RESPAWN_DELAY; + } + + @Override + public void startRespawn(BedWarsPlayer player) { + if (!canRespawn(player.getUuid())) { + game.onPlayerEliminated(player); + return; + } + + AtomicInteger countdown = new AtomicInteger(getRespawnDelay(player.getUuid())); + AtomicReference taskRef = new AtomicReference<>(); + + Task task = MinecraftServer.getSchedulerManager().buildTask(() -> { + if (!player.isOnline()) { + cancelRespawn(player.getUuid()); + return; + } + + int remaining = countdown.getAndDecrement(); + + if (remaining > 0) { + showRespawnTitle(player, remaining); + } else { + completeRespawn(player); + Task t = taskRef.get(); + if (t != null) t.cancel(); + respawnTasks.remove(player.getUuid()); + } + }).repeat(TaskSchedule.seconds(1)).schedule(); + + taskRef.set(task); + respawnTasks.put(player.getUuid(), task); + } + + @Override + public void cancelRespawn(UUID playerId) { + Task task = respawnTasks.remove(playerId); + if (task != null) { + task.cancel(); + } + } + + @Override + public boolean isRespawning(UUID playerId) { + return respawnTasks.containsKey(playerId); + } + + final Title.Times titleTimes = Title.Times.times(Duration.ofMillis(100), Duration.ofSeconds(1), Duration.ofMillis(100)); + + private void showRespawnTitle(BedWarsPlayer player, int seconds) { + Component mainTitleText = Component.text("YOU DIED!", NamedTextColor.RED); + Component subTitleText = MiniMessage.miniMessage().deserialize("You will respawn in " + seconds + " second" + (seconds == 1 ? "" : "s") + "!"); + Title title = Title.title(mainTitleText, subTitleText, titleTimes); + player.showTitle(title); + } + + public void equipTeamArmor(BedWarsPlayer player, BedWarsMapsConfig.TeamKey teamKey) { + final int armorLevel = getArmorLevel(player); + final Color teamColor = new Color(teamKey.rgb()); + + equipLegArmor(player, armorLevel, teamColor); + equipUpperArmor(player, teamColor); + } + + private int getArmorLevel(BedWarsPlayer player) { + return player.getTag(TypeBedWarsGameLoader.ARMOR_LEVEL_TAG) == null + ? 0 + : player.getTag(TypeBedWarsGameLoader.ARMOR_LEVEL_TAG); + } + + private void equipLegArmor(BedWarsPlayer player, int armorLevel, Color teamColor) { + ArmorTier tier = ArmorTier.fromLevel(armorLevel); + + if (tier == ArmorTier.LEATHER) { + player.setEquipment(EquipmentSlot.BOOTS, dyed(Material.LEATHER_BOOTS, teamColor)); + player.setEquipment(EquipmentSlot.LEGGINGS, dyed(Material.LEATHER_LEGGINGS, teamColor)); + return; + } + + player.setEquipment(EquipmentSlot.BOOTS, ItemStack.of(tier.boots())); + player.setEquipment(EquipmentSlot.LEGGINGS, ItemStack.of(tier.leggings())); + } + + private void equipUpperArmor(BedWarsPlayer player, Color teamColor) { + player.setEquipment(EquipmentSlot.CHESTPLATE, dyed(Material.LEATHER_CHESTPLATE, teamColor)); + player.setEquipment(EquipmentSlot.HELMET, dyed(Material.LEATHER_HELMET, teamColor)); + } + + private ItemStack dyed(Material material, Color color) { + return ItemStack.of(material) + .with(DataComponents.DYED_COLOR, color); + } + + private enum ArmorTier { + LEATHER(null, null), + CHAINMAIL(Material.CHAINMAIL_BOOTS, Material.CHAINMAIL_LEGGINGS), + IRON(Material.IRON_BOOTS, Material.IRON_LEGGINGS), + DIAMOND(Material.DIAMOND_BOOTS, Material.DIAMOND_LEGGINGS); + + private final Material boots; + private final Material leggings; + + ArmorTier(Material boots, Material leggings) { + this.boots = boots; + this.leggings = leggings; + } + + public Material boots() { + return boots; + } + + public Material leggings() { + return leggings; + } + + public static ArmorTier fromLevel(int level) { + return switch (level) { + case 1 -> CHAINMAIL; + case 2 -> IRON; + case 3 -> DIAMOND; + default -> LEATHER; + }; + } + } + + private void completeRespawn(BedWarsPlayer player) { + player.clearTitle(); + + game.setupPlayer(player); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsTeam.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsTeam.java new file mode 100644 index 000000000..8d713d09b --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsTeam.java @@ -0,0 +1,88 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import lombok.Getter; +import lombok.Setter; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.type.bedwarsgame.shop.TeamUpgradeId; +import net.swofty.type.bedwarsgame.shop.TrapId; +import net.swofty.type.game.game.team.SimpleGameTeam; + +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +@Getter +public class BedWarsTeam extends SimpleGameTeam { + private final TeamKey teamKey; + @Setter + private boolean bedAlive = false; + + private final Map upgrades = new EnumMap<>(TeamUpgradeId.class); + + private final List traps = new ArrayList<>(); + + public BedWarsTeam(TeamKey teamKey) { + super(teamKey.name(), teamKey.getName(), teamKey.chatColor()); + this.teamKey = teamKey; + } + + public boolean canRespawn() { + return bedAlive; + } + + public String firstLetter() { + return getName().substring(0, 1); + } + + /** + * Gets the level of an upgrade. + * + * @return The upgrade level, or 0 if not purchased + */ + public int getUpgradeLevel(TeamUpgradeId upgradeId) { + return upgrades.getOrDefault(upgradeId, 0); + } + + public void setUpgradeLevel(TeamUpgradeId upgradeId, int level) { + upgrades.put(upgradeId, level); + } + + public void destroyBed() { + this.bedAlive = false; + } + + public void addTrap(TrapId trapId) { + traps.add(trapId); + } + + public void removeTrap(TrapId trapId) { + traps.remove(trapId); + } + + public boolean hasTrap(TrapId trapId) { + return traps.contains(trapId); + } + + public int getTrapCount() { + return traps.size(); + } + + public void swapState(BedWarsTeam other) { + boolean previousBedAlive = bedAlive; + bedAlive = other.bedAlive; + other.bedAlive = previousBedAlive; + + Map previousUpgrades = new EnumMap<>(upgrades); + upgrades.clear(); + upgrades.putAll(other.upgrades); + other.upgrades.clear(); + other.upgrades.putAll(previousUpgrades); + + List previousTraps = new ArrayList<>(traps); + traps.clear(); + traps.addAll(other.traps); + other.traps.clear(); + other.traps.addAll(previousTraps); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsWorldManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsWorldManager.java new file mode 100644 index 000000000..d9b49006b --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/BedWarsWorldManager.java @@ -0,0 +1,367 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import lombok.RequiredArgsConstructor; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.VillagerProfession; +import net.minestom.server.instance.Instance; +import net.minestom.server.instance.InstanceContainer; +import net.minestom.server.instance.block.Block; +import net.minestom.server.item.Material; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.MapTeam; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.commons.mc.Vec3i; +import net.swofty.type.bedwarsgame.gui.GUIItemShop; +import net.swofty.type.bedwarsgame.gui.GUITeamShop; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.generic.collectibles.bedwars.BedWarsShopkeeperAppearanceService; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.AnimalConfiguration; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.entity.npc.configuration.VillagerConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; + +@RequiredArgsConstructor +public class BedWarsWorldManager { + private final BedWarsGame game; + private final List recordedShopNPCs = new ArrayList<>(); + private boolean shopNPCsRecorded = false; + + public void clearExistingBeds() { + InstanceContainer instance = game.getInstance(); + Map teams = game.getMapEntry().getConfiguration().getTeams(); + + for (MapTeam team : teams.values()) { + BedWarsMapsConfig.TwoBlockPosition bedPos = team.getBed(); + if (bedPos != null) { + clearBedBlocks(instance, bedPos); + } + } + } + + private void clearBedBlocks(InstanceContainer instance, BedWarsMapsConfig.TwoBlockPosition bedPos) { + if (bedPos.feet() != null) { + instance.setBlock( + bedPos.feet().x(), + bedPos.feet().y(), + bedPos.feet().z(), + Block.AIR + ); + } + if (bedPos.head() != null) { + instance.setBlock( + bedPos.head().x(), + bedPos.head().y(), + bedPos.head().z(), + Block.AIR + ); + } + } + + public void placeBeds(Map activeTeams) { + activeTeams.forEach(this::placeBedForTeam); + } + + /** + * Places a bed for a specific team. + */ + public void placeBedForTeam(TeamKey teamKey, MapTeam team) { + BedWarsMapsConfig.TwoBlockPosition bedPos = team.getBed(); + if (bedPos == null || bedPos.feet() == null || bedPos.head() == null) { + Logger.warn("Bed position not defined for team: {}", teamKey.getName()); + return; + } + + InstanceContainer instance = game.getInstance(); + Vec3i feetPos = bedPos.feet(); + Vec3i headPos = bedPos.head(); + + try { + Material bedMaterial = teamKey.bedMaterial(); + String facing = calculateBedFacing(feetPos, headPos); + + Block footBlock = bedMaterial.block() + .withProperty("part", "foot") + .withProperty("facing", facing); + Block headBlock = bedMaterial.block() + .withProperty("part", "head") + .withProperty("facing", facing); + + instance.setBlock(feetPos.x(), feetPos.y(), feetPos.z(), footBlock); + instance.setBlock(headPos.x(), headPos.y(), headPos.z(), headBlock); + + // Mark bed as alive in team + game.getTeam(teamKey.name()).ifPresent(t -> t.setBedAlive(true)); + + } catch (Exception e) { + Logger.error("Error placing bed for team {}: {}", teamKey.getName(), e.getMessage()); + } + } + + private String calculateBedFacing(Vec3i feet, Vec3i head) { + double dx = head.x() - feet.x(); + double dz = head.z() - feet.z(); + + if (Math.abs(dx) > Math.abs(dz)) { + return dx > 0 ? "east" : "west"; + } else { + return dz > 0 ? "south" : "north"; + } + } + + public void spawnShopNPCs(Map activeTeams) { + activeTeams.forEach((teamKey, team) -> { + if (team.getShop() == null) return; + + ShopkeeperSources sources = resolveShopkeeperSources(teamKey); + + HypixelPosition itemShopPos = team.getShop().item(); + HypixelPosition teamShopPos = team.getShop().team(); + + if (itemShopPos != null) { + Pos npcPos = new Pos(itemShopPos.x(), itemShopPos.y(), itemShopPos.z(), + itemShopPos.yaw(), itemShopPos.pitch()); + String[] holograms = new String[]{"§bITEM SHOP", "§e§lRIGHT CLICK"}; + + BedWarsShopkeeperAppearanceService.ShopkeeperAppearance appearance = + resolveShopkeeperAppearance(sources.itemShopPlayer()); + + HypixelNPC shopNpc = createShopNpc(npcPos, holograms, appearance, event -> { + BedWarsPlayer bwPlayer = (BedWarsPlayer) event.player(); + bwPlayer.openView(new GUIItemShop(bwPlayer.getGame())); + }); + shopNpc.register(); + + int npcEntityId = 10000 + teamKey.ordinal() * 2; // Generate unique entity ID + recordedShopNPCs.add(new RecordedShopNpc( + npcEntityId, + npcPos, + holograms, + "ITEM_SHOP", + appearance.replayEntityTypeId(), + appearance.textureValue(), + appearance.textureSignature() + )); + } + + if (teamShopPos != null) { + Pos npcPos = new Pos(teamShopPos.x(), teamShopPos.y(), teamShopPos.z(), + teamShopPos.yaw(), teamShopPos.pitch()); + String[] holograms = new String[]{"§bTEAM", "§bUPGRADES", "§e§lRIGHT CLICK"}; + + BedWarsShopkeeperAppearanceService.ShopkeeperAppearance appearance = + resolveShopkeeperAppearance(sources.teamShopPlayer()); + + HypixelNPC teamNpc = createShopNpc(npcPos, holograms, appearance, event -> { + BedWarsPlayer bwPlayer = (BedWarsPlayer) event.player(); + bwPlayer.openView(new GUITeamShop()); + }); + teamNpc.register(); + + int npcEntityId = 10000 + teamKey.ordinal() * 2 + 1; // Generate unique entity ID + recordedShopNPCs.add(new RecordedShopNpc( + npcEntityId, + npcPos, + holograms, + "TEAM_SHOP", + appearance.replayEntityTypeId(), + appearance.textureValue(), + appearance.textureSignature() + )); + } + }); + } + + private BedWarsShopkeeperAppearanceService.ShopkeeperAppearance resolveShopkeeperAppearance(BedWarsPlayer sourcePlayer) { + if (sourcePlayer == null) { + return BedWarsShopkeeperAppearanceService.defaultAppearance(); + } + return BedWarsShopkeeperAppearanceService.resolveSelected(sourcePlayer); + } + + private ShopkeeperSources resolveShopkeeperSources(TeamKey teamKey) { + List teamPlayers = new ArrayList<>(game.getPlayersOnTeam(teamKey)); + if (teamPlayers.isEmpty()) { + return new ShopkeeperSources(null, null); + } + + if (teamPlayers.size() == 1) { + BedWarsPlayer onlyPlayer = teamPlayers.getFirst(); + return new ShopkeeperSources(onlyPlayer, onlyPlayer); + } + + Collections.shuffle(teamPlayers, ThreadLocalRandom.current()); + return new ShopkeeperSources(teamPlayers.get(0), teamPlayers.get(1)); + } + + private HypixelNPC createShopNpc( + Pos npcPos, + String[] holograms, + BedWarsShopkeeperAppearanceService.ShopkeeperAppearance appearance, + Consumer clickAction + ) { + return switch (appearance.kind()) { + case HUMAN -> new HypixelNPC(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return holograms; + } + + @Override + public Pos position(HypixelPlayer player) { + return npcPos; + } + + @Override + public String texture(HypixelPlayer player) { + return appearance.textureValue(); + } + + @Override + public String signature(HypixelPlayer player) { + return appearance.textureSignature() == null ? "" : appearance.textureSignature(); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public Instance instance() { + return game.getInstance(); + } + }) { + @Override + public void onClick(NPCInteractEvent event) { + clickAction.accept(event); + } + }; + case VILLAGER -> new HypixelNPC(new VillagerConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return holograms; + } + + @Override + public Pos position(HypixelPlayer player) { + return npcPos; + } + + @Override + public VillagerProfession profession() { + return appearance.villagerProfession(); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public Instance instance() { + return game.getInstance(); + } + }) { + @Override + public void onClick(NPCInteractEvent event) { + clickAction.accept(event); + } + }; + case MOB -> new HypixelNPC(new AnimalConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return holograms; + } + + @Override + public Pos position(HypixelPlayer player) { + return npcPos; + } + + @Override + public EntityType entityType() { + return appearance.entityType(); + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public Instance instance() { + return game.getInstance(); + } + }) { + @Override + public void onClick(NPCInteractEvent event) { + clickAction.accept(event); + } + }; + }; + } + + public void spawnTemporaryItemShop(Pos position) { + BedWarsShopkeeperAppearanceService.ShopkeeperAppearance appearance = + BedWarsShopkeeperAppearanceService.defaultAppearance(); + HypixelNPC shopNpc = createShopNpc( + position, + new String[]{"§bITEM SHOP", "§e§lRIGHT CLICK", "§7Disappears in 30 seconds"}, + appearance, + event -> { + BedWarsPlayer player = (BedWarsPlayer) event.player(); + if (player.getGame() == game && game.getState() == net.swofty.type.game.game.GameState.IN_PROGRESS) { + player.openView(new GUIItemShop(game)); + } + } + ); + shopNpc.register(); + net.minestom.server.MinecraftServer.getSchedulerManager().buildTask(shopNpc::unregister) + .delay(net.minestom.server.timer.TaskSchedule.seconds(30)) + .schedule(); + } + + public void recordShopNpcsForReplay() { + if (shopNPCsRecorded || !game.getReplayManager().isRecording()) { + return; + } + for (RecordedShopNpc npc : recordedShopNPCs) { + game.getReplayManager().recordShopNpc( + npc.entityId(), + npc.position(), + npc.holograms(), + npc.npcType(), + npc.replayEntityTypeId(), + npc.replayTextureValue(), + npc.replayTextureSignature() + ); + } + shopNPCsRecorded = true; + } + + private record ShopkeeperSources(BedWarsPlayer itemShopPlayer, BedWarsPlayer teamShopPlayer) { + } + + private record RecordedShopNpc( + int entityId, + Pos position, + String[] holograms, + String npcType, + int replayEntityTypeId, + String replayTextureValue, + String replayTextureSignature + ) { + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/OneBlockManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/OneBlockManager.java new file mode 100644 index 000000000..bce28ad48 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/OneBlockManager.java @@ -0,0 +1,88 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import net.kyori.adventure.text.Component; +import net.minestom.server.MinecraftServer; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.timer.Task; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.shop.ShopItem; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public class OneBlockManager { + private static final int GAME_LENGTH_SECONDS = 5 * 60; + + private final BedWarsGame game; + private final List itemPool = new ArrayList<>(); + private Task ticker; + private int elapsedSeconds; + private int itemIntervalSeconds = 5; + + public OneBlockManager(BedWarsGame game) { + this.game = game; + Material.values().stream() + .filter(material -> material != Material.AIR) + .map(ItemStack::of) + .forEach(itemPool::add); + for (ShopItem item : TypeBedWarsGameLoader.getShopManager().getAllItems()) { + itemPool.add(item.getDisplay().withAmount(item.getAmount())); + } + } + + public void start() { + if (!game.getGameType().isOneBlock() || ticker != null) return; + + ticker = MinecraftServer.getSchedulerManager().buildTask(this::tick) + .delay(TaskSchedule.seconds(1)) + .repeat(TaskSchedule.seconds(1)) + .schedule(); + } + + public void stop() { + if (ticker != null) { + ticker.cancel(); + ticker = null; + } + } + + private void tick() { + if (game.getState() != GameState.IN_PROGRESS) { + stop(); + return; + } + + elapsedSeconds++; + if (elapsedSeconds == 60) { + itemIntervalSeconds = 4; + game.broadcastMessage(Component.translatable("bedwars.new_item_in_4")); + } else if (elapsedSeconds == 150) { + itemIntervalSeconds = 3; + game.broadcastMessage(Component.translatable("bedwars.new_item_in_3")); + } else if (elapsedSeconds == 240) { + itemIntervalSeconds = 1; + game.broadcastMessage(Component.translatable("bedwars.new_item_in_1")); + } + + if (elapsedSeconds % itemIntervalSeconds == 0) { + giveRandomItems(); + } + if (elapsedSeconds >= GAME_LENGTH_SECONDS) { + game.getGameEventManager().endOneBlockGame(); + stop(); + } + } + + private void giveRandomItems() { + for (BedWarsPlayer player : game.getPlayers()) { + if (!game.isPlayerCurrentlyPlaying(player.getUuid())) continue; + ItemStack item = itemPool.get(ThreadLocalRandom.current().nextInt(itemPool.size())); + player.getInventory().addItemStack(item); + } + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/SwappageManager.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/SwappageManager.java new file mode 100644 index 000000000..433f83e65 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/SwappageManager.java @@ -0,0 +1,103 @@ +package net.swofty.type.bedwarsgame.game.v2; + +import lombok.RequiredArgsConstructor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.minimessage.translation.Argument; +import net.kyori.adventure.title.Title; +import net.minestom.server.MinecraftServer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.timer.Task; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; +import net.swofty.type.generic.i18n.I18n; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +@RequiredArgsConstructor +public class SwappageManager { + private final BedWarsGame game; + private Task task; + + public void start() { + if (!game.getGameType().isSwappage() || task != null) return; + scheduleNext(); + } + + public void stop() { + if (task != null) task.cancel(); + task = null; + } + + private void scheduleNext() { + int seconds = ThreadLocalRandom.current().nextInt(60, 241); + task = MinecraftServer.getSchedulerManager().buildTask(() -> { + task = null; + if (game.getState() != GameState.IN_PROGRESS) return; + swapPartition(game.getViableTeams().stream().filter(BedWarsTeam::isBedAlive).toList()); + swapPartition(game.getViableTeams().stream().filter(team -> !team.isBedAlive()).toList()); + scheduleNext(); + }).delay(TaskSchedule.seconds(seconds)).schedule(); + } + + private void swapPartition(List source) { + List teams = new ArrayList<>(source); + Collections.shuffle(teams); + for (int i = 0; i + 1 < teams.size(); i += 2) { + swap(teams.get(i), teams.get(i + 1)); + } + } + + private void swap(BedWarsTeam first, BedWarsTeam second) { + List firstPlayers = new ArrayList<>(first.getPlayerIds()); + List secondPlayers = new ArrayList<>(second.getPlayerIds()); + List firstPositions = activePositions(firstPlayers); + List secondPositions = activePositions(secondPlayers); + + game.swapTeamState(first, second); + firstPlayers.forEach(uuid -> game.reassignPlayer(uuid, second)); + secondPlayers.forEach(uuid -> game.reassignPlayer(uuid, first)); + + updatePlayers(firstPlayers, second, secondPositions); + updatePlayers(secondPlayers, first, firstPositions); + } + + private List activePositions(List players) { + return players.stream() + .map(game::getPlayer) + .flatMap(Optional::stream) + .filter(player -> game.isPlayerCurrentlyPlaying(player.getUuid())) + .map(BedWarsPlayer::getPosition) + .toList(); + } + + private void updatePlayers(List playerIds, BedWarsTeam team, List positions) { + for (UUID uuid : playerIds) { + game.getPlayer(uuid).ifPresent(player -> { + player.setDisplayName(player.getColouredName()); + player.updateBelowTag(); + game.equipTeamArmor(player, team.getTeamKey()); + + if (!game.getRespawnHandler().isRespawning(uuid) + && game.isPlayerCurrentlyPlaying(uuid) && !positions.isEmpty()) { + player.teleport(positions.get(ThreadLocalRandom.current().nextInt(positions.size()))); + player.playTeleportSound(); + } + + var teamName = Component.text(team.getName(), TextColor.color(team.getTeamKey().rgb())); + player.showTitle(Title.title( + Component.translatable("bedwars.swap_title"), + I18n.t("bedwars.swap_subtitle", Argument.component("team", teamName)) + )); + player.sendMessage(I18n.t("bedwars.swap_team_changed", Argument.component("team", teamName))); + }); + } + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedBrokenListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedBrokenListener.java new file mode 100644 index 000000000..ec73f99b4 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedBrokenListener.java @@ -0,0 +1,39 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.events.custom.BedDestroyedEvent; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class BedBrokenListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onBedDestroyed(BedDestroyedEvent event) { + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.gameId()); + BedWarsMapsConfig.TeamKey teamKey = event.teamKey(); + if (game == null) return; + + BedWarsPlayer destroyer = event.destroyer(); + BedWarsMapsConfig.TeamKey destroyerTeamKey = destroyer.getTeamKey(); + if (destroyerTeamKey == null) { + throw new IllegalStateException("Destroyer team key is null for player " + destroyer.getUsername()); + } + + game.broadcastMessage(Component.newline().append(Component.text("§f§lBED DESTRUCTION > " + teamKey.chatColor() + teamKey.getName() + " Bed §7has been destroyed by " + destroyerTeamKey.chatColor() + event.destroyer().getUsername() + "§7!")).appendNewline()); + + for (BedWarsPlayer player : game.getPlayers()) { + player.playSound(Sound.sound(Key.key("minecraft:entity.wither.death"), + Sound.Source.MASTER, 1f, 1f), Sound.Emitter.self()); + } + + game.checkWinConditions(); + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsCountdownListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsCountdownListener.java new file mode 100644 index 000000000..83b6661ef --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsCountdownListener.java @@ -0,0 +1,60 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.CountdownCancelledEvent; +import net.swofty.type.game.game.event.CountdownTickEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class BedWarsCountdownListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onCountdownTick(CountdownTickEvent event) { + // Find the game for this event + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.gameId()); + if (game == null) return; + + // Only announce at specific intervals + if (!event.shouldAnnounce()) return; + + Component message = createCountdownMessage(event.remainingSeconds()); + + if (message == null) return; + + for (BedWarsPlayer player : game.getPlayers()) { + player.sendMessage(message); + player.playSound( + Sound.sound() + .type(Key.key("minecraft:block.note_block.pling")) + .volume(1f) + .pitch(1f) + .build() + ); + } + } + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onCountdownCancelled(CountdownCancelledEvent event) { + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.gameId()); + if (game == null) return; + + game.broadcastMessage(Component.text(event.reason())); + } + + private Component createCountdownMessage(int seconds) { + if (seconds > 10) { + return Component.text("§eThe game starts in " + seconds + " seconds!"); + } else if (seconds == 10) { + return Component.text("§eThe game starts in §610§e seconds!"); + } else if (seconds > 0) { + return Component.text("§eThe game starts in §c" + seconds + " §eseconds!"); + } + return null; + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsGameEventListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsGameEventListener.java new file mode 100644 index 000000000..348aee6b9 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsGameEventListener.java @@ -0,0 +1,37 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.events.custom.BedWarsGameEventAdvanceEvent; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class BedWarsGameEventListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onGameEventAdvance(BedWarsGameEventAdvanceEvent event) { + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.gameId()); + if (game == null) return; + + // update displays + game.getGeneratorManager().updateDisplaysForEventChange(); + + // Record to replay + if (game.getReplayManager().isRecording()) { + // Determine generator type and tier from event name + String eventName = event.currentEvent().toLowerCase(); + if (eventName.contains("diamond")) { + byte tier = 1; + if (eventName.contains("ii")) tier = 2; + else if (eventName.contains("iii")) tier = 3; + game.getReplayManager().recordGeneratorUpgrade((byte) 0, tier); + } else if (eventName.contains("emerald")) { + byte tier = 1; + if (eventName.contains("ii")) tier = 2; + else if (eventName.contains("iii")) tier = 3; + game.getReplayManager().recordGeneratorUpgrade((byte) 1, tier); + } + } + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsGameStateListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsGameStateListener.java new file mode 100644 index 000000000..ebe255493 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/BedWarsGameStateListener.java @@ -0,0 +1,43 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.game.game.event.GameStateChangeEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; +import org.tinylog.Logger; + +// todo: move functionality here +public class BedWarsGameStateListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onGameStateChange(GameStateChangeEvent event) { + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.gameId()); + if (game == null) return; + + Logger.info("BedWars game {} state changed: {} -> {}", + event.gameId(), event.previousState(), event.newState()); + + if (event.isCountdownStart()) { + onCountdownStarted(game); + } else if (event.isGameStart()) { + onGameStarted(game); + } else if (event.isGameEnd()) { + onGameEnded(game); + } + } + + private void onCountdownStarted(BedWarsGame game) { + // Could update scoreboard, play sounds, etc. + } + + private void onGameStarted(BedWarsGame game) { + Logger.info("BedWars game {} has officially started with {} players", + game.getGameId(), game.getPlayers().size()); + } + + private void onGameEnded(BedWarsGame game) { + Logger.info("BedWars game {} has ended", game.getGameId()); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameDisposalListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameDisposalListener.java new file mode 100644 index 000000000..24e674c47 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameDisposalListener.java @@ -0,0 +1,37 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.game.game.event.GameDisposeEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class GameDisposalListener implements HypixelEventClass { + private static final int MAX_UNREGISTER_ATTEMPTS = 120; + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onGameDispose(GameDisposeEvent event) { + BedWarsGame disposedGame = TypeBedWarsGameLoader.getGameById(event.gameId()); + TypeBedWarsGameLoader.getGames().removeIf(game -> game.getGameId().equals(event.gameId())); + + if (disposedGame != null) { + disposedGame.getSwappageManager().stop(); + unregisterInstanceWhenEmpty(disposedGame, 0); + } + } + + private void unregisterInstanceWhenEmpty(BedWarsGame game, int attempts) { + if (game.getInstance().getPlayers().isEmpty() || attempts >= MAX_UNREGISTER_ATTEMPTS) { + MinecraftServer.getInstanceManager().unregisterInstance(game.getInstance()); + return; + } + + MinecraftServer.getSchedulerManager().buildTask(() -> unregisterInstanceWhenEmpty(game, attempts + 1)) + .delay(TaskSchedule.millis(500)) + .schedule(); + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameEndListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameEndListener.java new file mode 100644 index 000000000..3610d9990 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameEndListener.java @@ -0,0 +1,155 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minestom.server.MinecraftServer; +import net.minestom.server.entity.GameMode; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.commons.ChatUtility; +import net.swofty.commons.ServerType; +import net.swofty.commons.bedwars.BedwarsLevelUtil; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.bedwarsgame.stats.BedWarsStatsRecorder; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.GameTeamWinConditionEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; +import net.swofty.type.generic.guild.GuildManager; +import org.tinylog.Logger; + +import java.util.Optional; + +public class GameEndListener implements HypixelEventClass { + + private static final String THICK_BAR = "§a§l▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬"; + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onGameEnd(GameTeamWinConditionEvent event) { + String gameId = event.gameId(); + BedWarsGame game = TypeBedWarsGameLoader.getGameById(gameId); + + // Show results to all players + for (BedWarsPlayer player : game.getPlayers()) { + player.playSound(Sound.sound(Key.key("minecraft:ui.toast.challenge_complete"), + Sound.Source.MASTER, 1f, 1f), Sound.Emitter.self()); + + // Record win + event.team().ifPresent(team -> { + if (team.hasPlayer(player.getUuid())) { + if (player.allowsPersistentProgress()) { + BedWarsStatsRecorder.recordWin(player, game.getGameType()); + player.getAchievementHandler().addProgressByTrigger("bedwars.wins", 1); + GuildManager.recordProgress(player, 0, true); + } + } + }); + + player.setGameMode(GameMode.ADVENTURE); + if (player.allowsPersistentProgress()) GuildManager.recordProgress(player, 20, false); + } + + boolean isRecording = game.getReplayManager().isRecording(); + game.getReplayManager().stopRecording(); + + game.getGeneratorManager().stopAllGenerators(); + game.getGameEventManager().stop(); + game.getSwappageManager().stop(); + game.getOneBlockManager().stop(); + + Logger.info("Ending game " + gameId); + game.end(); + + for (BedWarsPlayer player : game.getPlayers()) { + player.sendMessage(Component.text(THICK_BAR)); + player.sendMessage(Component.text(ChatUtility.FontInfo.center("§lBed Wars"), NamedTextColor.WHITE)); + player.sendMessage(Component.empty()); + + event.team().ifPresent(team -> { + String playerNamesConcatenated = team.getPlayerIds().stream() + .map(game::getPlayer) + .filter(Optional::isPresent) + .map(p -> LegacyComponentSerializer.legacySection().serialize(p.get().getColouredName())) + .reduce((a, b) -> a + "§7," + b) + .orElse(""); + player.sendMessage(Component.text(ChatUtility.FontInfo.center(team.getColorCode() + team.getName() + " §7- " + playerNamesConcatenated), NamedTextColor.WHITE)); + player.sendMessage(Component.empty()); + }); + + player.sendMessage(Component.text(ChatUtility.FontInfo.center("§e§l1st Killer §7- Username §7- 0"))); + player.sendMessage(Component.text(ChatUtility.FontInfo.center("§6§l2nd Killer §7- Username §7- 0"))); + player.sendMessage(Component.text(ChatUtility.FontInfo.center("§c§l3rd Killer §7- Username §7- 0"))); + player.sendMessage(Component.empty()); + player.sendMessage(Component.text(THICK_BAR)); + } + + MinecraftServer.getSchedulerManager().buildTask(() -> { + for (BedWarsPlayer player : game.getPlayers()) { + player.sendMessage(Component.text(THICK_BAR)); + player.sendMessage(Component.text(ChatUtility.FontInfo.center("§lReward Summary"), NamedTextColor.WHITE)); + player.sendMessage(Component.empty()); + player.sendMessage(Component.text(" §7You earned:")); + player.sendMessage(Component.text(" §f• §2" + player.getTokensThisGame() + " Bed Wars Tokens")); + player.sendMessage(Component.text(" §f• §3" + player.getHypixelXpThisGame() + " Hypixel Experience")); + player.sendMessage(Component.text(" §f• §20 Guild Experience")); + player.sendMessage(Component.empty()); + player.sendMessage(Component.text(ChatUtility.FontInfo.center("Bed Wars XP"), NamedTextColor.AQUA)); + + long currentLevel = player.getCurrentBedWarsLevel(); + player.sendMessage(Component.text( + "§f §bLevel " + currentLevel + " §bLevel " + (currentLevel + 1) + )); + + long experience = player.getCurrentBedWarsExperience(); + int progress = BedwarsLevelUtil.calculateExperienceSinceLastLevel(experience); + int maxExperience = BedwarsLevelUtil.calculateMaxExperienceFromExperience(experience); + + double percentage = Math.min(1.0, (double) progress / maxExperience); + int filledSquares = (int) Math.round(percentage * 34); + StringBuilder progressBar = new StringBuilder("§8["); + for (int i = 0; i < 34; i++) { + if (i < filledSquares) { + progressBar.append("§b■"); + } else { + progressBar.append("§7■"); + } + } + progressBar.append("§8]"); + player.sendMessage(Component.text("§f " + progressBar)); + + String prettyExperience = String.format("%,d", experience); + String prettyMaxExperience = String.format("%,d", maxExperience); + + String percentageString = String.format("%.1f", percentage * 100); + + player.sendMessage(ChatUtility.FontInfo.center( + "§b" + prettyExperience + " §7/ §a" + prettyMaxExperience + " §7(" + percentageString + "%)" + )); + + player.sendMessage(Component.empty()); + player.sendMessage("§7You earned §b" + player.getXpThisGame() + " §bBed Wars XP"); + player.sendMessage(Component.empty()); + // xp multipliers shown here + player.sendMessage(Component.text(THICK_BAR)); + if (isRecording) { + player.sendMessage(Component.text("§aThis game has been recorded. §6Click here to watch the Replay!").clickEvent( + ClickEvent.runCommand("/replay " + game.getReplayManager().getRecorder().getReplayId()) + )); + } + player.sendMessage(Component.empty()); + } + }).delay(TaskSchedule.seconds(2)).schedule(); + + MinecraftServer.getSchedulerManager().buildTask(() -> { + game.getPlayers().forEach(p -> p.sendTo(ServerType.BEDWARS_LOBBY)); + game.dispose(); + }).delay(TaskSchedule.seconds(7)).schedule(); + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameStartListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameStartListener.java new file mode 100644 index 000000000..8a74c8223 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/GameStartListener.java @@ -0,0 +1,123 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.translation.Argument; +import net.minestom.server.MinecraftServer; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.GameState; +import net.swofty.type.game.game.event.GameStartEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; +import net.swofty.type.generic.i18n.I18n; +import org.tinylog.Logger; + +import java.util.Comparator; +import java.util.Map; + +public class GameStartListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onGameStart(GameStartEvent event) { + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.getGameId()); + Logger.info("Starting BedWars game {}", event.gameId()); + + // Prepare world + game.getWorldManager().clearExistingBeds(); + + // Assign players to teams + game.autoAssignTeams(); + game.getActiveTeams().forEach(team -> team.setBedAlive(true)); + + // Get active teams and set up their areas + Map activeTeamConfigs = game.getActiveTeamConfigs(); + + game.getWorldManager().placeBeds(activeTeamConfigs); + if (!game.getGameType().isOneBlock()) { + game.getWorldManager().spawnShopNPCs(activeTeamConfigs); + } + + // Start generators + if (!game.getGameType().isOneBlock()) { + game.getGeneratorManager().startTeamGenerators(activeTeamConfigs); + game.getGeneratorManager().startGlobalGenerators(); + } + + // Start game event progression + game.getGameEventManager().start(); + game.getOneBlockManager().start(); + + // Teleport players to their spawn points + game.teleportPlayersToSpawns(); + + // Start time-played XP task + game.startTimePlayedRewards(); + + // Start replay recording + game.getReplayManager().startRecording(); + + // Send game start message + game.sendGameStartMessage(); + game.getSwappageManager().start(); + + // just correct in case + MinecraftServer.getSchedulerManager().scheduleTask(() -> { + if (game.getState() != GameState.IN_PROGRESS) { + return TaskSchedule.stop(); + } + for (BedWarsPlayer player : game.getPlayers()) { + player.updateBelowTag(); + } + return TaskSchedule.seconds(10); + }, TaskSchedule.seconds(1)); + + MinecraftServer.getSchedulerManager().scheduleTask(() -> { + if (game.getState() != GameState.IN_PROGRESS) { + return TaskSchedule.stop(); + } + game.getTrackers().forEach((uuid, teamKey) -> { + game.getPlayer(uuid).ifPresentOrElse(player -> { + // get closest player from teamKey + BedWarsPlayer target = game.getPlayersOnTeam(teamKey) + .stream() + .filter(t -> !t.getUuid().equals(uuid)) + .min(Comparator.comparingDouble(t -> + player.getPosition().distanceSquared(t.getPosition()) + )) + .orElse(null); + + // team could be completely eliminated + if (target == null) { + game.getTrackers().remove(uuid); + return; + } + + int distance = (int) Math.sqrt( + player.getPosition().distanceSquared(target.getPosition()) + ); + + Component playerColouredName = target.getDisplayName(); + if (playerColouredName == null) { + playerColouredName = Component.text(target.getUsername()); + } + + player.sendActionBar( + I18n.t( + "bedwars.tracking_player", + Argument.component("name", playerColouredName), + Argument.string("distance", String.valueOf(distance)) + ) + ); + }, () -> game.getTrackers().remove(uuid)); + }); + return TaskSchedule.seconds(2); + }, TaskSchedule.seconds(15)); + + Logger.info("BedWars game {} started with {} active teams", event.gameId(), activeTeamConfigs.size()); + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerGameDisconnectListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerGameDisconnectListener.java new file mode 100644 index 000000000..ab16c0d1f --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerGameDisconnectListener.java @@ -0,0 +1,27 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.text.Component; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.PlayerDisconnectGameEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class PlayerGameDisconnectListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onPlayerDisconnect(PlayerDisconnectGameEvent event) { + BedWarsPlayer player = (BedWarsPlayer) event.player(); + BedWarsGame game = player.getGame(); + if (game != null) { + String teamColor = game.getPlayerTeam(player.getUuid()) + .map(BedWarsTeam::getColorCode) + .orElse("§7"); + + game.broadcastMessage(Component.text(teamColor + player.getUsername() + " §7disconnected.")); + } + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerJoinGameListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerJoinGameListener.java new file mode 100644 index 000000000..756c6b6b8 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerJoinGameListener.java @@ -0,0 +1,65 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.minestom.server.coordinate.Pos; +import net.minestom.server.entity.GameMode; +import net.swofty.commons.mc.HypixelPosition; +import net.swofty.commons.party.FullParty; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.PlayerPostJoinGameEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; +import net.swofty.type.generic.party.PartyManager; + +import java.util.Random; +import java.util.UUID; + +public class PlayerJoinGameListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onPlayerJoinGame(PlayerPostJoinGameEvent event) { + BedWarsPlayer player = (BedWarsPlayer) event.player(); + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.getGameId()); + + HypixelPosition waiting = game.getMapEntry().getConfiguration().getLocations().getWaiting(); + + if (player.getInstance() == null || player.getInstance().getUuid() != game.getInstance().getUuid()) { + player.setInstance(game.getInstance(), new Pos(waiting.x(), waiting.y(), waiting.z())); + } + + player.setEnableRespawnScreen(false); + player.setFlying(false); + player.setGameMode(GameMode.ADVENTURE); + player.getInventory().setItemStack(8, + TypeBedWarsGameLoader.getItemHandler().getItem("leave_game").getItemStack()); + + HypixelPosition spec = game.getMapEntry().getConfiguration().getLocations().getSpectator(); + player.setRespawnPoint(new Pos(spec.x(), spec.y(), spec.z())); + + player.setGameId(event.getGameId()); + String randomLetters = UUID.randomUUID().toString().replaceAll("-", "") + .substring(0, new Random().nextInt(10) + 4); + player.setDisplayName(Component.text(randomLetters, NamedTextColor.WHITE, TextDecoration.OBFUSCATED)); + + FullParty party = PartyManager.getPartyFromPlayer(player); + + for (BedWarsPlayer p : game.getPlayers()) { + boolean shouldObfuscate = true; + if (party != null) { + shouldObfuscate = !party.getParticipants().contains(p.getUuid()); + } + if (shouldObfuscate && p.getUuid().compareTo(player.getUuid()) == 0) { + shouldObfuscate = false; + } + String name = shouldObfuscate ? "§k" + randomLetters : LegacyComponentSerializer.legacySection().serialize(player.getColouredName()); + p.sendMessage(name + " §ehas joined (§b" + game.getPlayers().size() + "§e/§b" + game.getMaxPlayers() + "§e)!"); + } + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerLeaveListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerLeaveListener.java new file mode 100644 index 000000000..a90b1d736 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerLeaveListener.java @@ -0,0 +1,27 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.text.Component; +import net.swofty.commons.ServerType; +import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.PlayerLeaveGameEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +import java.util.Random; + +public class PlayerLeaveListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onPlayerLeave(PlayerLeaveGameEvent event) { + BedWarsPlayer player = (BedWarsPlayer) event.player(); + player.sendTo(ServerType.BEDWARS_LOBBY); + BedWarsGame game = TypeBedWarsGameLoader.getGameById(event.gameId()); + if (game == null) return; + if (!game.getState().isWaiting()) return; + + game.broadcastMessage(Component.text("§k" + player.getFakeUuid().toString().substring(0, new Random().nextInt(10) + 4) + " §ehas quit!")); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerRejoinGameListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerRejoinGameListener.java new file mode 100644 index 000000000..7684171a7 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerRejoinGameListener.java @@ -0,0 +1,20 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.PlayerRejoinGameEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class PlayerRejoinGameListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onPlayerGameRejoin(PlayerRejoinGameEvent event) { + BedWarsPlayer player = (BedWarsPlayer) event.player(); + BedWarsGame game = player.getGame(); + + game.onPlayerRejoin(player, event.disconnectedPlayerData()); + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerTeamAssignationListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerTeamAssignationListener.java new file mode 100644 index 000000000..089b0c8c7 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/PlayerTeamAssignationListener.java @@ -0,0 +1,32 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.minestom.server.MinecraftServer; +import net.minestom.server.scoreboard.TeamBuilder; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.game.game.event.PlayerAssignedTeamEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +public class PlayerTeamAssignationListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void onPlayerTeamAssign(PlayerAssignedTeamEvent event) { + BedWarsPlayer player = (BedWarsPlayer) event.player(); + player.setTeamName(event.team().getTeamKey()); + + TextColor textColor = TextColor.color(event.team().getTeamKey().rgb()); + NamedTextColor color = NamedTextColor.nearestTo(textColor); // possible performance hit? + player.setTeam(new TeamBuilder(event.team().getName(), MinecraftServer.getTeamManager()) + .prefix(Component.text(event.team().firstLetter(), textColor, TextDecoration.BOLD).appendSpace()) + .teamColor(color) + .build()); + player.getTeam().sendUpdatePacket(); + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/TeamEliminationListener.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/TeamEliminationListener.java new file mode 100644 index 000000000..61216454e --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/game/v2/listener/TeamEliminationListener.java @@ -0,0 +1,43 @@ +package net.swofty.type.bedwarsgame.game.v2.listener; + +import net.kyori.adventure.text.Component; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.bedwarsgame.replay.BedWarsReplayManager; +import net.swofty.type.bedwarsgame.stats.BedWarsStatsRecorder; +import net.swofty.type.game.game.event.TeamEliminatedEvent; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; + +import java.util.Optional; + +public class TeamEliminationListener implements HypixelEventClass { + + @HypixelEvent(node = EventNodes.CUSTOM, requireDataLoaded = false) + public void run(TeamEliminatedEvent event) { + BedWarsTeam team = event.team(); + String teamColor = team.getColorCode(); + String teamName = team.getName(); + + BedWarsGame game = (BedWarsGame) event.game(); + team.getPlayerIds().stream() + .map(game::getPlayer) + .flatMap(Optional::stream) + .forEach(player -> { + BedWarsStatsRecorder.recordBedLost(player, game.getGameType()); + BedWarsStatsRecorder.recordLoss(player, game.getGameType()); + }); + + game.broadcastMessage(Component.text("")); + game.broadcastMessage(Component.text("§f§lTEAM ELIMINATED > §c" + teamColor + teamName + " §chas been eliminated!")); + game.broadcastMessage(Component.text("")); + + BedWarsReplayManager replayManager = game.getReplayManager(); + + // Record to replay + if (replayManager.isRecording()) { + replayManager.recordTeamElimination(team.getTeamKey()); + } + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIEnderChest.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIEnderChest.java index 6ecc5bfc4..7d109f8b0 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIEnderChest.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIEnderChest.java @@ -1,77 +1,78 @@ package net.swofty.type.bedwarsgame.gui; -import net.minestom.server.event.inventory.InventoryCloseEvent; -import net.minestom.server.event.inventory.InventoryPreClickEvent; -import net.minestom.server.inventory.Inventory; import net.minestom.server.inventory.InventoryType; import net.minestom.server.item.ItemStack; -import net.swofty.type.bedwarsgame.game.Game; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; -import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.generic.gui.v2.StatefulView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.ViewSession; +import net.swofty.type.generic.gui.v2.context.ClickContext; +import net.swofty.type.generic.gui.v2.context.ViewContext; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -public class GUIEnderChest extends HypixelInventoryGUI { - - public GUIEnderChest() { - super("Ender Chest", InventoryType.CHEST_3_ROW); - } +public class GUIEnderChest implements StatefulView { @Override - public void setItems(InventoryGUIOpenEvent event) { - BedWarsPlayer player = (BedWarsPlayer) event.player(); - Game game = player.getGame(); - if (game == null) return; - - Map enderChest = game.getEnderchests().get(player); - if (enderChest != null) { - for (Map.Entry entry : enderChest.entrySet()) { - if (entry.getKey() < size.getSize()) { - set(entry.getKey(), entry.getValue().builder(), true); - } - } - } + public State initialState() { + return new State(); } @Override - public void onClose(InventoryCloseEvent event, CloseReason reason) { - super.onClose(event, reason); - - HypixelPlayer player = (HypixelPlayer) event.getPlayer(); - closeSave(player); + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Ender Chest", InventoryType.CHEST_3_ROW); } - @Override - public void suddenlyQuit(Inventory inventory, HypixelPlayer player) { - super.suddenlyQuit(inventory, player); - closeSave(player); - } - - private void closeSave(HypixelPlayer p) { - BedWarsPlayer player = (BedWarsPlayer) p; - Game game = player.getGame(); - if (game == null) return; + @Override + public void layout(ViewLayout layout, State state, ViewContext ctx) { + BedWarsPlayer player = (BedWarsPlayer) ctx.player(); + BedWarsGame game = player.getGame(); - Map enderChest = new ConcurrentHashMap<>(); - for (int slot = 0; slot < getInventory().getSize(); slot++) { - ItemStack item = getInventory().getItemStack(slot); - if (!item.isAir()) { - enderChest.put(slot, item); - } - } + for (int slot = 0; slot < InventoryType.CHEST_3_ROW.getSize(); slot++) { + int targetSlot = slot; + layout.editable(slot, (s, c) -> { + if (game == null) { + return ItemStack.AIR.builder(); + } + Map enderChest = game.getEnderChests().get(player.getUuid()); + if (enderChest == null) { + return ItemStack.AIR.builder(); + } + return enderChest.getOrDefault(targetSlot, ItemStack.AIR).builder(); + }, (changedSlot, oldItem, newItem, s) -> { + }); + } - game.getEnderchests().put(player, enderChest); - } + layout.allowHotkey(true); + } @Override - public boolean allowHotkeying() { + public boolean onBottomClick(ClickContext click, ViewContext ctx) { return true; } @Override - public void onBottomClick(InventoryPreClickEvent event) { + public void onClose(State state, ViewContext ctx, ViewSession.CloseReason reason) { + BedWarsPlayer player = (BedWarsPlayer) ctx.player(); + BedWarsGame game = player.getGame(); + if (game == null) { + return; + } + + Map enderChest = new ConcurrentHashMap<>(); + for (int slot = 0; slot < ctx.inventory().getSize(); slot++) { + ItemStack item = ctx.inventory().getItemStack(slot); + if (!item.isAir()) { + enderChest.put(slot, item); + } + } + + game.getEnderChests().put(player.getUuid(), enderChest); + } + public record State() { } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java index e8ef366e9..f49cdd828 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIItemShop.java @@ -8,23 +8,23 @@ import net.minestom.server.component.DataComponents; import net.minestom.server.entity.EquipmentSlot; import net.minestom.server.entity.Player; -import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.InventoryType; import net.minestom.server.inventory.click.Click; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.game.Game; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.shop.ShopItem; import net.swofty.type.bedwarsgame.shop.ShopManager; import net.swofty.type.bedwarsgame.shop.UpgradeableItemTier; import net.swofty.type.bedwarsgame.shop.UpgradeableShopItem; import net.swofty.type.bedwarsgame.user.BedWarsPlayer; -import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; -import net.swofty.type.generic.gui.inventory.item.GUIItem; +import net.swofty.type.generic.gui.v2.StatefulView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; import net.swofty.type.generic.user.HypixelPlayer; import org.jetbrains.annotations.Nullable; @@ -36,7 +36,7 @@ import static net.kyori.adventure.text.format.TextDecoration.ITALIC; import static net.swofty.type.bedwarsgame.util.ComponentManipulator.noItalic; -public class GUIItemShop extends HypixelInventoryGUI { +public class GUIItemShop implements StatefulView { private static final ItemStack QUICK_BUY = ItemStack.builder(Material.NETHER_STAR) .customName(Component.text("Quick Buy").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.AQUA)) @@ -73,411 +73,320 @@ public class GUIItemShop extends HypixelInventoryGUI { private static final ItemStack ROTATING_ITEMS = ItemStack.builder(Material.REDSTONE_TORCH) .customName(Component.text("Rotating Items").decorationIfAbsent(ITALIC, TextDecoration.State.FALSE).color(NamedTextColor.GREEN)) .build(); + private static final List> TIERED_ITEM_GROUPS = List.of( List.of(Material.LEATHER_BOOTS, Material.GOLDEN_BOOTS, Material.CHAINMAIL_BOOTS, Material.IRON_BOOTS, Material.DIAMOND_BOOTS, Material.NETHERITE_BOOTS) ); + private final ShopManager shopService = TypeBedWarsGameLoader.shopManager; - private int currentPage = 0; - private final Game game; + private final BedWarsGame game; - public GUIItemShop(Game game) { - super("Item Shop", InventoryType.CHEST_6_ROW); + public GUIItemShop(BedWarsGame game) { this.game = game; } @Override - public boolean allowHotkeying() { - return true; + public State initialState() { + return new State(0); } @Override - public void onOpen(InventoryGUIOpenEvent e) { - updateGUI(e.player()); + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Item Shop", InventoryType.CHEST_6_ROW); } @Override - public void onBottomClick(InventoryPreClickEvent e) { - e.setCancelled(true); + public void layout(ViewLayout layout, State state, ViewContext ctx) { + layout.allowHotkey(false); + + for (int slot = 9; slot <= 17; slot++) { + layout.slot(slot, ItemStackCreator.createNamedItemStack(Material.BLACK_STAINED_GLASS_PANE)); + } + layout.slot(state.currentPage() + 9, ItemStackCreator.createNamedItemStack(Material.GREEN_STAINED_GLASS_PANE)); + + addCategoryButton(layout, 0, QUICK_BUY, state.currentPage(), 0); + addCategoryButton(layout, 1, BLOCKS, state.currentPage(), 1); + addCategoryButton(layout, 2, WEAPONS, state.currentPage(), 2); + addCategoryButton(layout, 3, ARMOR, state.currentPage(), 3); + addCategoryButton(layout, 4, TOOLS, state.currentPage(), 4); + addCategoryButton(layout, 5, BOWS, state.currentPage(), 5); + addCategoryButton(layout, 6, POTIONS, state.currentPage(), 6); + addCategoryButton(layout, 7, UTILITY, state.currentPage(), 7); + addCategoryButton(layout, 8, ROTATING_ITEMS, state.currentPage(), 8); + + populateShopItems(layout, shopService, game, state.currentPage(), null, c -> c.session(State.class).refresh()); } - private void updateGUI(HypixelPlayer p) { - fill(ItemStackCreator.createNamedItemStack(Material.BLACK_STAINED_GLASS_PANE), 9, 17); - set(currentPage + 9, ItemStackCreator.createNamedItemStack(Material.GREEN_STAINED_GLASS_PANE)); - set(new GUIClickableItem(0) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 0; - updateGUI(player); - playClickSound(player); - } + private void addCategoryButton(ViewLayout layout, int slot, ItemStack icon, int currentPage, int targetPage) { + layout.slot(slot, + (s, c) -> convertToClickToView(icon, currentPage, targetPage), + (click, c) -> { + c.session(State.class).update(prev -> prev.withCurrentPage(targetPage)); + playClickSound(click.player()); + } + ); + } - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(QUICK_BUY, currentPage, 0); - } - }); - - set(new GUIClickableItem(1) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 1; - updateGUI(player); - playClickSound(player); - } + private ItemStack.Builder convertToClickToView(ItemStack itemStack, int currentPage, int index) { + ItemStack.Builder builder = itemStack.builder(); + if (currentPage != index) { + return builder.lore(noItalic(Component.text("Click to view!").color(NamedTextColor.YELLOW))); + } + return builder; + } - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(BLOCKS, currentPage, 1); - } - }); - - set(new GUIClickableItem(2) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 2; - updateGUI(player); - playClickSound(player); - } + public static void populateShopItems(ViewLayout layout, + ShopManager shopService, + BedWarsGame game, + @Nullable Integer currentPage, + @Nullable ShopItem quickBuyEditor, + Consumer update) { + int[] shopSlots = { + 19, 20, 21, 22, 23, 24, 25, + 28, 29, 30, 31, 32, 33, 34, + 37, 38, 39, 40, 41, 42, 43 + }; - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(WEAPONS, currentPage, 2); - } - }); - - set(new GUIClickableItem(3) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 3; - updateGUI(player); - playClickSound(player); - } + if (currentPage != null && currentPage == 8) { + layout.slot(49, (s, c) -> ItemStackCreator.getStack("§aWhat are Rotating Items?", Material.PAPER, 1, List.of( + "§7Rotating Items are items that are", + "§7only available for a limited amount of", + "§7time. They may disappear and be", + "§7replaced with another temporary", + "§7item at any time." + ))); + } - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(ARMOR, currentPage, 3); - } - }); - - set(new GUIClickableItem(4) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 4; - updateGUI(player); - playClickSound(player); - } + if (currentPage != null && currentPage == 0) { + layout.slot(45, (_, _) -> ItemStackCreator.getStack( + "§aTracker Shop", + Material.COMPASS, + 1, + "§7Purchase tracking upgrade for your", + "§7compass which will track each player", + "§7on a specific team until you die." + ), (_, context) -> { + context.push(new TrackerShopView()); + }); + layout.slot(53, (_, _) -> ItemStackCreator.getStack("§aHotbar Manager", Material.BLAZE_POWDER, 1, "§7Edit preferred slots for your items", "§7per category.", "", "§eClick to edit!"), (_, context) -> { + context.push(new net.swofty.type.generic.gui.impl.HotbarManagerView()); + }); + } - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(TOOLS, currentPage, 4); - } - }); - - set(new GUIClickableItem(5) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 5; - updateGUI(player); - playClickSound(player); - } + for (int i = 0; i < shopSlots.length; i++) { + int slot = shopSlots[i]; + int index = i; - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(BOWS, currentPage, 5); - } - }); - - set(new GUIClickableItem(6) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 6; - updateGUI(player); - playClickSound(player); + layout.slot(slot, + (s, c) -> renderShopItem(c, shopService, game, currentPage, quickBuyEditor, index), + (click, c) -> handleShopItemClick(click.player(), click.click(), c, shopService, game, currentPage, quickBuyEditor, index, update) + ); + } + } + + private static ItemStack.Builder renderShopItem(ViewContext context, + ShopManager shopService, + BedWarsGame game, + @Nullable Integer currentPage, + @Nullable ShopItem quickBuyEditor, + int index) { + BedWarsPlayer player = (BedWarsPlayer) context.player(); + ShopItem shopItem; + if ((currentPage != null && currentPage == 0) || quickBuyEditor != null) { + shopItem = shopService.getQuickShopItem(player, index); + } else if (currentPage != null) { + shopItem = shopService.getShopItem(currentPage, index); + } else { + throw new IllegalStateException("Current page cannot be null when getting shop items!"); + } + + if (shopItem == null) { + if (quickBuyEditor != null) { + return ItemStackCreator.getStack( + "§cEmpty slot!", + Material.RED_STAINED_GLASS_PANE, + 1, + List.of("§eClick to set!") + ); } + if (currentPage != 0) return ItemStack.builder(Material.AIR); + return ItemStackCreator.getStack( + "§cEmpty slot!", + Material.RED_STAINED_GLASS_PANE, + 1, + List.of("§7This is a Quick Buy Slot! §bShift Click", "§7any item in the shop to add it here.") + ); + } - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(POTIONS, currentPage, 6); + if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { + int nextLevel = upgradeableShopItem.getNextLevel(player); + UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); + boolean hasEnough = hasPlayerEnoughCurrencyForTier(game, player, nextTier); + + List lore = new ArrayList<>(); + if (quickBuyEditor != null) { + lore.add("§eClick to replace!"); + } else { + lore.add("§7Cost: " + nextTier.currency().getColor() + nextTier.price().apply(game.getGameType()) + " " + nextTier.currency().getName()); + lore.add(" "); + if (upgradeableShopItem.getDescription() != null && !upgradeableShopItem.getDescription().isEmpty()) { + lore.addAll(StringUtility.splitByNewLine(upgradeableShopItem.getDescription(), "§7")); + lore.add(" "); + } + + boolean isItemInQuickBuy = shopService.isItemIDinQuickBuy(player, upgradeableShopItem.getId()); + if (currentPage != 0 && !isItemInQuickBuy) { + lore.add("§bShift Click to add to Quick Buy"); + } else if (currentPage == 0 && isItemInQuickBuy) { + lore.add("§bShift Click to remove from Quick Buy"); + } + if (nextLevel >= upgradeableShopItem.getTiers().size()) { + lore.add("§cYou have already purchased the maximum tier of this item!"); + } else if (hasEnough) { + lore.add("§eClick to buy!"); + } else { + lore.add("§cYou don't have enough " + nextTier.currency().getName() + "!"); + } } - }); - - set(new GUIClickableItem(7) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 7; - updateGUI(player); - playClickSound(player); + + String name = quickBuyEditor != null || hasEnough ? "§a" + nextTier.name() : "§c" + nextTier.name(); + + return ItemStackCreator.getStack( + name, + nextTier.material(), + 1, + lore + ); + } + + boolean hasEnough = hasPlayerEnoughCurrency(game, player, shopItem); + ItemStack displayItem = shopItem.getDisplay(player); + List lore = new ArrayList<>(); + if (quickBuyEditor != null) { + lore.add("§eClick to replace!"); + } else { + lore.add("§7Cost: " + shopItem.getCurrency().getColor() + shopItem.getPrice().apply(game.getGameType()) + " " + shopItem.getCurrency().getName()); + lore.add(" "); + if (shopItem.getDescription() != null && !shopItem.getDescription().isEmpty()) { + lore.addAll(StringUtility.splitByNewLine(shopItem.getDescription(), "§7")); + lore.add(" "); } - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(UTILITY, currentPage, 7); + boolean isItemInQuickBuy = shopService.isItemIDinQuickBuy(player, shopItem.getId()); + if (currentPage != 0 && !isItemInQuickBuy) { + lore.add("§bShift Click to add to Quick Buy"); + } else if (currentPage == 0 && isItemInQuickBuy) { + lore.add("§bShift Click to remove from Quick Buy"); } - }); - - set(new GUIClickableItem(8) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer player) { - currentPage = 8; - updateGUI(player); - playClickSound(player); + if (!hasEnough) { + lore.add("§cYou don't have enough " + shopItem.getCurrency().getName() + "!"); + } else if (!shopItem.isOwned(player)) { + lore.add("§aUNLOCKED"); + } else if (hasBetterItem(player, displayItem.material())) { + lore.add("§cYou already have a better item!"); + } else { + lore.add("§eClick to buy!"); } + } - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return convertToClickToView(ROTATING_ITEMS, currentPage, 8); - } - }); + Component name = quickBuyEditor != null + ? Component.text("§a" + shopItem.getName()) + : hasEnough && shopItem.isOwned(player) ? Component.text("§a" + shopItem.getName()) : Component.text("§c" + shopItem.getName()); - populateShopItems(this, shopService, game, currentPage, null, this::updateGUI); - updateItemStacks(getInventory(), getPlayer()); + return ItemStackCreator.updateLore( + displayItem.builder().set(DataComponents.CUSTOM_NAME, name), + lore + ); } - private ItemStack.Builder convertToClickToView(ItemStack itemStack, int currentPage, int index) { - ItemStack.Builder builder = itemStack.builder(); + private static void handleShopItemClick(HypixelPlayer p, + Click click, + ViewContext ctx, + ShopManager shopService, + BedWarsGame game, + @Nullable Integer currentPage, + @Nullable ShopItem quickBuyEditor, + int index, + Consumer update) { + BedWarsPlayer player = (BedWarsPlayer) p; + ShopItem shopItem; + if ((currentPage != null && currentPage == 0) || quickBuyEditor != null) { + shopItem = shopService.getQuickShopItem(player, index); + } else if (currentPage != null) { + shopItem = shopService.getShopItem(currentPage, index); + } else { + throw new IllegalStateException("Current page cannot be null when clicking shop items!"); + } - if (currentPage != index) { - return builder.lore(noItalic(Component.text("Click to view!").color(NamedTextColor.YELLOW))); + if (quickBuyEditor != null) { + shopService.setQuickBuyItem(player, index, quickBuyEditor); + player.sendMessage("§aAdded " + quickBuyEditor.getName() + " to Quick Buy!"); + ctx.replace(new GUIItemShop(game)); + return; } - return builder; - } + if (shopItem == null) return; - public static void populateShopItems(HypixelInventoryGUI gui, ShopManager shopService, Game game, @Nullable Integer currentPage, @Nullable ShopItem quickBuyEditor, Consumer update) { - int[] shopSlots = { - 19, 20, 21, 22, 23, 24, 25, - 28, 29, 30, 31, 32, 33, 34, - 37, 38, 39, 40, 41, 42, 43 - }; + if (click instanceof Click.LeftShift || click instanceof Click.RightShift) { + boolean isInQuickBuy = shopService.isItemIDinQuickBuy(player, shopItem.getId()); + if (isInQuickBuy) { + if (currentPage != 0) return; + shopService.removeQuickBuyItem(player, shopItem); + player.sendMessage(noItalic(Component.text("Removed " + shopItem.getName() + " from Quick Buy!").color(NamedTextColor.RED))); + } else { + ctx.replace(new GUIQuickBuyEditor(game, shopItem)); + } + playClickSound(player); + update.accept(ctx); + return; + } - for (int i = 0; i < shopSlots.length; i++) { - int slot = shopSlots[i]; - int index = i; + if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { + int nextLevel = upgradeableShopItem.getNextLevel(player); + if (nextLevel >= upgradeableShopItem.getTiers().size()) { + player.sendMessage(noItalic(Component.text("You have already purchased the maximum tier of this item!").color(NamedTextColor.RED))); + return; + } - if (currentPage != null && currentPage == 8) { - gui.set(new GUIItem(49) { - - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - return ItemStackCreator.getStack("§aWhat are Rotating Items?", Material.PAPER, 1, List.of( - "§7Rotating Items are items that are", - "§7only available for a limited amount of", - "§7time. They may disappear and be", - "§7replaced with another temporary", - "§7item at any time." - )); - } - }); + UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); + if (!hasPlayerEnoughCurrencyForTier(game, player, nextTier)) { + int owned = Arrays.stream(player.getInventory().getItemStacks()) + .filter(s -> s.material() == nextTier.currency().getMaterial()) + .mapToInt(ItemStack::amount) + .sum(); + int needed = nextTier.price().apply(game.getGameType()) - owned; + player.sendMessage(noItalic(Component.text("You don't have enough " + nextTier.currency().getName() + "! Need " + needed + " more!").color(NamedTextColor.RED))); + return; } - gui.set(new GUIClickableItem(slot) { - @Override - public void run(InventoryPreClickEvent e, HypixelPlayer p) { - BedWarsPlayer player = (BedWarsPlayer) p; - ShopItem shopItem; - if ((currentPage != null && currentPage == 0 ) || quickBuyEditor != null) { - shopItem = shopService.getQuickShopItem(player, index); - } else if (currentPage != null) { - shopItem = shopService.getShopItem(currentPage, index); - } else { - throw new IllegalStateException("Current page cannot be null when clicking shop items!"); - } - - if (quickBuyEditor != null) { - shopService.setQuickBuyItem(player, index, quickBuyEditor); - player.closeInventory(); - new GUIItemShop(game).open(player); - player.sendMessage("§aAdded " + quickBuyEditor.getName() + " to Quick Buy!"); - return; - } - - if (shopItem == null) return; - - Click click = e.getClick(); - if (click instanceof Click.LeftShift || click instanceof Click.RightShift) { - boolean isInQuickBuy = shopService.isItemIDinQuickBuy(player, shopItem.getId()); - if (isInQuickBuy) { - if (currentPage != 0) return; - shopService.removeQuickBuyItem(player, shopItem); - player.sendMessage(noItalic(Component.text("Removed " + shopItem.getName() + " from Quick Buy!").color(NamedTextColor.RED))); - } else { - player.closeInventory(); - new GUIQuickBuyEditor(game, shopItem).open(player); - } - playClickSound(player); - update.accept(player); - return; - } - - if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { - int nextLevel = upgradeableShopItem.getNextLevel(player); - if (nextLevel >= upgradeableShopItem.getTiers().size()) { - player.sendMessage(noItalic(Component.text("You have already purchased the maximum tier of this item!").color(NamedTextColor.RED))); - return; - } - UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); - if (!hasPlayerEnoughCurrencyForTier(game, player, nextTier)) { - int owned = Arrays.stream(player.getInventory().getItemStacks()) - .filter(s -> s.material() == nextTier.currency().getMaterial()) - .mapToInt(ItemStack::amount) - .sum(); - int needed = nextTier.price().apply(game.getBedwarsGameType()) - owned; - player.sendMessage(noItalic(Component.text("You don't have enough " + nextTier.currency().getName() + "! Need " + needed + " more!").color(NamedTextColor.RED))); - return; - } - upgradeableShopItem.handlePurchase(player, game.getBedwarsGameType()); - player.sendMessage(noItalic(Component.text("You purchased " + nextTier.name() + "!").color(NamedTextColor.GREEN))); - playBuySound(player); - update.accept(player); - return; - } - - if (!hasPlayerEnoughCurrency(game, player, shopItem)) { - player.sendMessage(noItalic(Component.text("You don't have enough " + shopItem.getCurrency().getName() + "!").color(NamedTextColor.RED))); - return; - } - if (!shopItem.isOwned(player)) { - player.sendMessage(noItalic(Component.text("You already have the highest tier available!").color(NamedTextColor.RED))); - return; - } - - - if (hasBetterItem(player, shopItem.getDisplay().material())) { - player.sendMessage("§cYou already have a better item!"); - return; - } - shopItem.handlePurchase(player, game.getBedwarsGameType()); - playBuySound(player); - update.accept(player); - } + upgradeableShopItem.handlePurchase(player, game.getGameType()); + player.sendMessage(noItalic(Component.text("You purchased " + nextTier.name() + "!").color(NamedTextColor.GREEN))); + playBuySound(player); + update.accept(ctx); + return; + } - @Override - public ItemStack.Builder getItem(HypixelPlayer p) { - BedWarsPlayer player = (BedWarsPlayer) p; - ShopItem shopItem; - if ((currentPage != null && currentPage == 0 ) || quickBuyEditor != null) { - shopItem = shopService.getQuickShopItem(player, index); - } else if (currentPage != null) { - shopItem = shopService.getShopItem(currentPage, index); - } else { - throw new IllegalStateException("Current page cannot be null when getting shop items!"); - } - - if (shopItem == null) { - if (quickBuyEditor != null) { - return ItemStackCreator.getStack( - "§cEmpty slot!", - Material.RED_STAINED_GLASS_PANE, - 1, - List.of("§eClick to set!") - ); - } - if (currentPage != 0) return ItemStack.builder(Material.AIR); - return ItemStackCreator.getStack( - "§cEmpty slot!", - Material.RED_STAINED_GLASS_PANE, - 1, - List.of("§7This is a Quick Buy Slot! §bShift Click", "§7any item in the shop to add it here.") - ); - } - - if (shopItem instanceof UpgradeableShopItem upgradeableShopItem) { - int nextLevel = upgradeableShopItem.getNextLevel(player); - UpgradeableItemTier nextTier = upgradeableShopItem.getNextTier(player); - boolean hasEnough = hasPlayerEnoughCurrencyForTier(game, player, nextTier); - - List lore = new ArrayList<>(); - if (quickBuyEditor != null) { - lore.add("§eClick to replace!"); - } else { - lore.add( - "§7Cost: " + nextTier.currency().getColor() + nextTier.price().apply(game.getBedwarsGameType()) + " " + nextTier.currency().getName() - ); - lore.add(" "); - if (upgradeableShopItem.getDescription() != null && !upgradeableShopItem.getDescription().isEmpty()) { - lore.addAll(StringUtility.splitByNewLine(upgradeableShopItem.getDescription(), "§7")); - lore.add(" "); - } - - boolean isItemInQuickBuy = shopService.isItemIDinQuickBuy(player, upgradeableShopItem.getId()); - if (currentPage != 0 && !isItemInQuickBuy) { - lore.add("§bShift Click to add to Quick Buy"); - } else if (currentPage == 0 && isItemInQuickBuy) { - lore.add("§bShift Click to remove from Quick Buy"); - } - if (nextLevel >= upgradeableShopItem.getTiers().size()) { - lore.add("§cYou have already purchased the maximum tier of this item!"); - } else if (hasEnough) { - lore.add("§eClick to buy!"); - } else { - lore.add("§cYou don't have enough " + nextTier.currency().getName() + "!"); - } - } - - String name; - if (quickBuyEditor != null) { - name = "§a" + nextTier.name(); - } else { - name = hasEnough ? "§a" + nextTier.name() : "§c" + nextTier.name(); - } - - return ItemStackCreator.getStack( - name, - nextTier.material(), - 1, - lore - ); - } - - boolean hasEnough = hasPlayerEnoughCurrency(game, player, shopItem); - List lore = new ArrayList<>(); - if (quickBuyEditor != null) { - lore.add("§eClick to replace!"); - } else { - lore.add( - "§7Cost: " + shopItem.getCurrency().getColor() + shopItem.getPrice().apply(game.getBedwarsGameType()) + " " + shopItem.getCurrency().getName() - ); - lore.add(" "); - if (shopItem.getDescription() != null && !shopItem.getDescription().isEmpty()) { - lore.addAll(StringUtility.splitByNewLine(shopItem.getDescription(), "§7")); - lore.add(" "); - } - - boolean isItemInQuickBuy = shopService.isItemIDinQuickBuy(player, shopItem.getId()); - if (currentPage != 0 && !isItemInQuickBuy) { - lore.add("§bShift Click to add to Quick Buy"); - } else if (currentPage == 0 && isItemInQuickBuy) { - lore.add("§bShift Click to remove from Quick Buy"); - } - if (!hasEnough) { - lore.add("§cYou don't have enough " + shopItem.getCurrency().getName() + "!"); - } else if (!shopItem.isOwned(player)) { - lore.add("§aUNLOCKED"); - } else if (hasBetterItem(player, shopItem.getDisplay().material())) { - lore.add("§cYou already have a better item!"); - } else { - lore.add("§eClick to buy!"); - } - } - - Component name; - if (quickBuyEditor != null) { - name = Component.text("§a" + shopItem.getName()); - } else { - name = hasEnough && shopItem.isOwned(player) ? Component.text("§a" + shopItem.getName()) : Component.text("§c" + shopItem.getName()); - } - - return ItemStackCreator.updateLore( - shopItem.getDisplay().builder().set(DataComponents.CUSTOM_NAME, name), - lore - ); - } - }); + if (!hasPlayerEnoughCurrency(game, player, shopItem)) { + player.sendMessage(noItalic(Component.text("You don't have enough " + shopItem.getCurrency().getName() + "!").color(NamedTextColor.RED))); + return; + } + if (!shopItem.isOwned(player)) { + player.sendMessage(noItalic(Component.text("You already have the highest tier available!").color(NamedTextColor.RED))); + return; } + + if (hasBetterItem(player, shopItem.getDisplay(player).material())) { + player.sendMessage("§cYou already have a better item!"); + return; + } + + shopItem.handlePurchase(player, game.getGameType()); + playBuySound(player); + update.accept(ctx); } - private static boolean hasPlayerEnoughCurrency(Game game, HypixelPlayer player, ShopItem shopItem) { - int requiredAmount = shopItem.getPrice().apply(game.getBedwarsGameType()); + private static boolean hasPlayerEnoughCurrency(BedWarsGame game, HypixelPlayer player, ShopItem shopItem) { + int requiredAmount = shopItem.getPrice().apply(game.getGameType()); Material currencyMaterial = shopItem.getCurrency().getMaterial(); int playerAmount = 0; @@ -490,8 +399,8 @@ private static boolean hasPlayerEnoughCurrency(Game game, HypixelPlayer player, return playerAmount >= requiredAmount; } - private static boolean hasPlayerEnoughCurrencyForTier(Game game, HypixelPlayer player, UpgradeableItemTier tier) { - int required = tier.price().apply(game.getBedwarsGameType()); + private static boolean hasPlayerEnoughCurrencyForTier(BedWarsGame game, HypixelPlayer player, UpgradeableItemTier tier) { + int required = tier.price().apply(game.getGameType()); Material cur = tier.currency().getMaterial(); int have = 0; for (ItemStack it : player.getInventory().getItemStacks()) { @@ -535,4 +444,9 @@ private static void playBuySound(HypixelPlayer player) { player.playSound(Sound.sound(Key.key("minecraft:entity.experience_orb.pickup"), Sound.Source.MASTER, 1.0f, 1.0f)); } + public record State(int currentPage) { + public State withCurrentPage(int page) { + return new State(page); + } + } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIPurchaseEnemyTracker.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIPurchaseEnemyTracker.java new file mode 100644 index 000000000..e45f0fbe4 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIPurchaseEnemyTracker.java @@ -0,0 +1,168 @@ +package net.swofty.type.bedwarsgame.gui; + +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.bedwarsgame.util.BedWarsInventoryManipulator; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class GUIPurchaseEnemyTracker extends StatelessView { + + private static final int TRACKER_PRICE = 2; + private static final int[] TEAM_SLOTS = {10, 11, 12, 13, 14, 15, 16, 19}; + + @Override + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Purchase Enemy Tracker", InventoryType.CHEST_4_ROW); + } + + @Override + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + Components.back(layout, 31, ctx); + + if (!(ctx.player() instanceof BedWarsPlayer player)) { + return; + } + + BedWarsGame game = player.getGame(); + TeamKey ownTeam = GUIQuickCommunications.resolveTeamKey(player); + if (game == null || ownTeam == null) { + layout.slot(13, ItemStackCreator.getStack( + "§cUnavailable", + Material.BARRIER, + 1, + "§7You must be in an active game", + "§7to purchase an enemy tracker." + )); + return; + } + + List enemyTeams = getEnemyTeams(game, ownTeam); + if (enemyTeams.isEmpty()) { + layout.slot(13, ItemStackCreator.getStack( + "§aNo enemies left", + Material.LIME_STAINED_GLASS_PANE, + 1, + "§7There are no enemy teams", + "§7left to track." + )); + return; + } + + boolean trackersUnlocked = enemyTeams.stream().noneMatch(game::isBedAlive); + int optionCount = Math.min(enemyTeams.size(), TEAM_SLOTS.length); + for (int i = 0; i < optionCount; i++) { + TeamKey targetTeam = enemyTeams.get(i); + int slot = TEAM_SLOTS[i]; + + layout.slot(slot, + (s, c) -> buildTrackerItem(player, targetTeam, trackersUnlocked), + (click, context) -> { + if (!(click.player() instanceof BedWarsPlayer clickPlayer)) { + return; + } + + handleTrackerPurchase(clickPlayer, game, targetTeam, trackersUnlocked, context); + } + ); + } + } + + private ItemStack.Builder buildTrackerItem(BedWarsPlayer player, TeamKey targetTeam, boolean trackersUnlocked) { + boolean trackingThisTeam = isTrackingTeam(player, targetTeam); + boolean canAfford = BedWarsInventoryManipulator.hasEnoughMaterial(player, Material.EMERALD, TRACKER_PRICE); + + String nameColor = trackersUnlocked && (canAfford || trackingThisTeam) ? "§a" : "§c"; + String teamName = targetTeam.chatColor() + targetTeam.getName(); + + List lore = new ArrayList<>(); + lore.add("§7Purchase tracking upgrade for your"); + lore.add("§7compass which will track each player"); + lore.add("§7on a specific team until you die."); + lore.add(""); + lore.add("§7Cost: §2" + TRACKER_PRICE + " Emeralds"); + lore.add(""); + + if (!trackersUnlocked) { + lore.add("§cUnlocks when all enemy beds are destroyed!"); + } else if (trackingThisTeam) { + lore.add("§aYou are already tracking this team!"); + } else if (canAfford) { + lore.add("§eClick to purchase!"); + } else { + lore.add("§cYou don't have enough Emeralds!"); + } + + return ItemStackCreator.getStack( + nameColor + "Track Team " + teamName, + targetTeam.bedMaterial(), + 1, + lore + ); + } + + private void handleTrackerPurchase(BedWarsPlayer player, + BedWarsGame game, + TeamKey targetTeam, + boolean trackersUnlocked, + ViewContext ctx) { + if (!trackersUnlocked) { + player.sendMessage("§cUnlocks when all enemy beds are destroyed!"); + GUIQuickCommunications.playClickSound(player); + return; + } + + if (isTrackingTeam(player, targetTeam)) { + player.sendMessage("§cYou are already tracking this team!"); + GUIQuickCommunications.playClickSound(player); + return; + } + + if (!BedWarsInventoryManipulator.hasEnoughMaterial(player, Material.EMERALD, TRACKER_PRICE)) { + player.sendMessage("§cYou don't have enough Emeralds!"); + GUIQuickCommunications.playClickSound(player); + return; + } + + BedWarsInventoryManipulator.removeItems(player, Material.EMERALD, TRACKER_PRICE); + game.getTrackers().put(player.getUuid(), targetTeam); + player.sendMessage("§aYour compass is now tracking " + targetTeam.chatColor() + "Team " + targetTeam.getName() + "§a!"); + + GUIQuickCommunications.playBuySound(player); + ctx.session(DefaultState.class).refresh(); + } + + private boolean isTrackingTeam(BedWarsPlayer player, TeamKey teamKey) { + BedWarsGame game = player.getGame(); + if (game == null) { + return false; + } + + TeamKey trackedTeam = game.getTrackers().get(player.getUuid()); + return trackedTeam == teamKey; + } + + private List getEnemyTeams(BedWarsGame game, TeamKey ownTeam) { + return game.getTeams().stream() + .filter(BedWarsTeam::hasPlayers) + .map(BedWarsTeam::getTeamKey) + .filter(team -> team != ownTeam) + .sorted(Comparator.comparingInt(Enum::ordinal)) + .toList(); + } + +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickBuyEditor.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickBuyEditor.java index 20f3ec903..5aa9bc23b 100644 --- a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickBuyEditor.java +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickBuyEditor.java @@ -2,66 +2,62 @@ import net.kyori.adventure.text.Component; import net.minestom.server.component.DataComponents; -import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.InventoryType; -import net.minestom.server.item.ItemStack; import net.swofty.commons.StringUtility; import net.swofty.type.bedwarsgame.TypeBedWarsGameLoader; -import net.swofty.type.bedwarsgame.game.Game; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; import net.swofty.type.bedwarsgame.shop.ShopItem; import net.swofty.type.bedwarsgame.shop.ShopManager; -import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.gui.inventory.ItemStackCreator; -import net.swofty.type.generic.gui.inventory.item.GUIItem; -import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ClickContext; +import net.swofty.type.generic.gui.v2.context.ViewContext; import java.util.ArrayList; import java.util.List; -public class GUIQuickBuyEditor extends HypixelInventoryGUI { +public class GUIQuickBuyEditor extends StatelessView { private final ShopManager shopService = TypeBedWarsGameLoader.shopManager; private final ShopItem shopItem; - private final Game game; + private final BedWarsGame game; - public GUIQuickBuyEditor(Game game, ShopItem shopItem) { - super("Adding to Quick Buy...", InventoryType.CHEST_6_ROW); + public GUIQuickBuyEditor(BedWarsGame game, ShopItem shopItem) { this.shopItem = shopItem; this.game = game; } @Override - public void onOpen(InventoryGUIOpenEvent e) { - set(new GUIItem(4) { - @Override - public ItemStack.Builder getItem(HypixelPlayer player) { - List lore = new ArrayList<>(); - lore.add( - "§7Cost: " + shopItem.getCurrency().getColor() + shopItem.getPrice().apply(game.getBedwarsGameType()) + " " + shopItem.getCurrency().getName() - ); - lore.add(" "); - if (shopItem.getDescription() != null && !shopItem.getDescription().isEmpty()) { - lore.addAll(StringUtility.splitByNewLine(shopItem.getDescription(), "§7")); - lore.add(" "); - } - lore.add("§eAdding item to Quick Slot!"); + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Adding to Quick Buy...", InventoryType.CHEST_6_ROW); + } - return ItemStackCreator.updateLore( - shopItem.getDisplay().builder().set(DataComponents.CUSTOM_NAME, Component.text("§a" + shopItem.getName())), - lore - ); + @Override + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + layout.slot(4, (s, c) -> { + List lore = new ArrayList<>(); + lore.add("§7Cost: " + shopItem.getCurrency().getColor() + shopItem.getPrice().apply(game.getGameType()) + " " + shopItem.getCurrency().getName()); + lore.add(" "); + if (shopItem.getDescription() != null && !shopItem.getDescription().isEmpty()) { + lore.addAll(StringUtility.splitByNewLine(shopItem.getDescription(), "§7")); + lore.add(" "); } + lore.add("§eAdding item to Quick Slot!"); + + return ItemStackCreator.updateLore( + shopItem.getDisplay().builder().set(DataComponents.CUSTOM_NAME, Component.text("§a" + shopItem.getName())), + lore + ); }); - GUIItemShop.populateShopItems(this, shopService, game, null, shopItem, null); - updateItemStacks(getInventory(), getPlayer()); - } - @Override - public boolean allowHotkeying() { - return false; + GUIItemShop.populateShopItems(layout, shopService, game, null, shopItem, _ -> { + }); } @Override - public void onBottomClick(InventoryPreClickEvent e) { - + public boolean onBottomClick(ClickContext click, ViewContext ctx) { + return false; } } diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickCommunications.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickCommunications.java new file mode 100644 index 000000000..0f1437d95 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUIQuickCommunications.java @@ -0,0 +1,211 @@ +package net.swofty.type.bedwarsgame.gui; + +import net.kyori.adventure.key.Key; +import net.kyori.adventure.sound.Sound; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.Material; +import net.swofty.commons.bedwars.BedWarsGameType; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +public class GUIQuickCommunications extends StatelessView { + + @Override + public ViewConfiguration configuration() { + return new ViewConfiguration<>("Quick Communications", InventoryType.CHEST_5_ROW); + } + + @Override + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + addSendButton( + layout, + 10, + "§aHello ( ゚◡゚)/!", + Material.BOOK, + "§aHello ( ゚◡゚)/!" + ); + addSendButton( + layout, + 11, + "§aI'm coming back to base!", + Material.BOOK, + "§aI'm coming back to base!" + ); + addSendButton( + layout, + 12, + "§aI'm defending!", + Material.IRON_BARS, + "§aI'm defending!" + ); + addSelectButton( + layout, + 13, + "§aI'm attacking!", + Material.IRON_SWORD, + () -> GUISelectAnOption.forTeamCommunication("I'm attacking"), + "§7You will be able to select the Team.", + "", + "§eClick to select!" + ); + addSelectButton( + layout, + 14, + "§aI'm collecting resources!", + Material.DIAMOND, + () -> GUISelectAnOption.forResourceCommunication("I'm collecting"), + "§7You will be able to select the", + "§7Resource.", + "", + "§eClick to select!" + ); + addSelectButton( + layout, + 15, + "§aI have resources!", + Material.CHEST, + () -> GUISelectAnOption.forResourceCommunication("I have"), + "§7You will be able to select the", + "§7Resource.", + "", + "§eClick to select!" + ); + addSendButton( + layout, + 20, + "§aThank You!", + Material.BOOK, + "§aThank You!" + ); + addSendButton( + layout, + 21, + "§aGet back to base!", + Material.BOOK, + "§aGet back to base!" + ); + addSendButton( + layout, + 22, + "§aPlease defend!", + Material.IRON_BARS, + "§aPlease defend!" + ); + addSelectButton( + layout, + 23, + "§aLet's attack!", + Material.IRON_SWORD, + () -> GUISelectAnOption.forTeamCommunication("Let's attack"), + "§7You will be able to select the Team.", + "", + "§eClick to select!" + ); + addSelectButton( + layout, + 24, + "§aWe need resources!", + Material.DIAMOND, + () -> GUISelectAnOption.forResourceCommunication("We need"), + "§7You will be able to select the", + "§7Resource.", + "", + "§eClick to select!" + ); + addSendButton( + layout, + 25, + "§aPlayer incoming!!", + Material.FEATHER, + "§aPlayer incoming!!" + ); + + Components.back(layout, 40, ctx); + } + + private void addSendButton(ViewLayout layout, + int slot, + String title, + Material icon, + String message) { + layout.slot(slot, ItemStackCreator.getStack( + title, + icon, + 1, + "", + "§eClick to send!" + ), (click, context) -> { + if (!(click.player() instanceof BedWarsPlayer player)) { + return; + } + + sendTeamQuickMessage(player, message); + playClickSound(player); + player.closeInventory(); + }); + } + + private void addSelectButton(ViewLayout layout, + int slot, + String title, + Material icon, + Supplier selectViewSupplier, + String... lore) { + layout.slot(slot, ItemStackCreator.getStack(title, icon, 1, lore), (click, context) -> { + playClickSound(click.player()); + context.push(selectViewSupplier.get()); + }); + } + + static void sendTeamQuickMessage(BedWarsPlayer player, String message) { + BedWarsGame game = player.getGame(); + if (game == null) { + return; + } + + TeamKey teamKey = resolveTeamKey(player); + List receivers; + if (game.getGameType() == BedWarsGameType.ONE_EIGHT || teamKey == null) { + receivers = new ArrayList<>(game.getPlayers()); + } else { + receivers = game.getPlayersOnTeam(teamKey); + } + + String formatted = "§a§lTEAM > §r" + player.getFullDisplayName() + "§f: " + message; + receivers.forEach(receiver -> receiver.sendMessage(formatted)); + } + + static TeamKey resolveTeamKey(BedWarsPlayer player) { + String teamName = player.getTeamName(); + if (teamName == null) { + return null; + } + + try { + return TeamKey.valueOf(teamName); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + static void playClickSound(HypixelPlayer player) { + player.playSound(Sound.sound(Key.key("minecraft:ui.button.click"), Sound.Source.MASTER, 1.0f, 1.0f)); + } + + static void playBuySound(HypixelPlayer player) { + player.playSound(Sound.sound(Key.key("minecraft:entity.experience_orb.pickup"), Sound.Source.MASTER, 1.0f, 1.0f)); + } +} diff --git a/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUISelectAnOption.java b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUISelectAnOption.java new file mode 100644 index 000000000..408ac4418 --- /dev/null +++ b/type.bedwarsgame/src/main/java/net/swofty/type/bedwarsgame/gui/GUISelectAnOption.java @@ -0,0 +1,160 @@ +package net.swofty.type.bedwarsgame.gui; + +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.commons.bedwars.map.BedWarsMapsConfig.TeamKey; +import net.swofty.type.bedwarsgame.game.v2.BedWarsGame; +import net.swofty.type.bedwarsgame.game.v2.BedWarsTeam; +import net.swofty.type.bedwarsgame.user.BedWarsPlayer; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.v2.Components; +import net.swofty.type.generic.gui.v2.DefaultState; +import net.swofty.type.generic.gui.v2.StatelessView; +import net.swofty.type.generic.gui.v2.ViewConfiguration; +import net.swofty.type.generic.gui.v2.ViewLayout; +import net.swofty.type.generic.gui.v2.context.ViewContext; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.function.Function; + +public class GUISelectAnOption extends StatelessView { + + private static final int[] RESOURCE_SLOTS = {10, 12, 14, 16}; + private static final int[] TEAM_SLOTS = {10, 11, 12, 13, 14, 15, 16, 19}; + + private final String title; + private final Function> optionSupplier; + + public GUISelectAnOption() { + this("Select an option:", _ -> buildResourceOptions("I'm collecting")); + } + + private GUISelectAnOption(String title, Function> optionSupplier) { + this.title = title; + this.optionSupplier = optionSupplier; + } + + public static GUISelectAnOption forResourceCommunication(String prefix) { + return new GUISelectAnOption("Select an option:", _ -> buildResourceOptions(prefix)); + } + + public static GUISelectAnOption forTeamCommunication(String prefix) { + return new GUISelectAnOption("Select a team:", ctx -> buildTeamOptions(ctx, prefix)); + } + + @Override + public ViewConfiguration configuration() { + return ViewConfiguration.withString((_, _) -> title, InventoryType.CHEST_4_ROW); + } + + @Override + public void layout(ViewLayout layout, DefaultState state, ViewContext ctx) { + List

implements Game

{ + protected final String gameId; + protected final InstanceContainer instance; + protected final Map players = new ConcurrentHashMap<>(); + protected final Map disconnectedPlayers = new ConcurrentHashMap<>(); + + @Getter + protected final Consumer eventDispatcher; + + protected GameState state = GameState.WAITING; + protected DefaultGameCountdown countdown; + + /** + * Stores minimal data about disconnected players for rejoin. + */ + public record DisconnectedPlayerData( + UUID uuid, + String username, + long disconnectTime, + Map savedData + ) { + } + + protected AbstractGame(InstanceContainer instance, Consumer eventDispatcher) { + this.gameId = UUID.randomUUID().toString(); + this.instance = instance; + this.eventDispatcher = eventDispatcher; + this.countdown = createCountdown(); + } + + /** + * Creates the countdown controller for this game. + * Override to customize countdown behavior. + */ + protected DefaultGameCountdown createCountdown() { + return new DefaultGameCountdown( + gameId, + getCountdownConfig(), + eventDispatcher, + this::onCountdownComplete, + this::onCountdownCancelled, + this::hasMinimumPlayers + ); + } + + /** + * @return The countdown configuration for this game type + */ + protected CountdownConfig getCountdownConfig() { + return CountdownConfig.DEFAULT; + } + + /** + * Called when countdown completes. Triggers game start. + */ + protected void onCountdownComplete() { + start(); + } + + protected void onCountdownCancelled() { + if (state == GameState.COUNTDOWN) { + setState(GameState.WAITING); + } + } + + @Override + public String getGameId() { + return gameId; + } + + @Override + public GameState getState() { + return state; + } + + @Override + public InstanceContainer getInstance() { + return instance; + } + + @Override + public Collection

getPlayers() { + return Collections.unmodifiableCollection(players.values()); + } + + @Override + public Optional

getPlayer(UUID uuid) { + return Optional.ofNullable(players.get(uuid)); + } + + @Override + public GameCountdownController getCountdown() { + return countdown; + } + + @Override + public JoinResult join(P player) { + if (players.containsKey(player.getUuid())) { + return new JoinResult.Denied("Player is already in this game"); + } + + PlayerPreJoinGameEvent event = new PlayerPreJoinGameEvent(gameId, player.getServerPlayer()); + eventDispatcher.accept(event); + + if (event.isCancelled()) { + return new JoinResult.Denied(event.getCancelReason() != null ? event.getCancelReason() : "Join cancelled"); + } + + if (state != GameState.WAITING && state != GameState.COUNTDOWN) { + return new JoinResult.Denied("Game already in progress"); + } + + if (getAvailableSlots() <= 0) { + return new JoinResult.Denied("Game is full"); + } + + players.put(player.getUuid(), player); + player.setGameId(gameId); + + eventDispatcher.accept(new PlayerPostJoinGameEvent( + gameId, + player.getServerPlayer(), + players.size(), + getMaxPlayers() + )); + + if (hasMinimumPlayers() && !countdown.isActive()) { + setState(GameState.COUNTDOWN); + countdown.start(); + } + + return new JoinResult.Success(); + } + + @Override + public void leave(P player) { + if (!players.containsKey(player.getUuid())) return; + + players.remove(player.getUuid()); + player.setGameId(null); + + if (this instanceof AbstractTeamGame teamGame) { + teamGame.removeFromTeam(player); + } + + eventDispatcher.accept(new PlayerLeaveGameEvent( + gameId, + player.getServerPlayer(), + PlayerLeaveGameEvent.LeaveReason.VOLUNTARY + )); + + if (state == GameState.IN_PROGRESS) { + checkWinConditions(); + } + } + + /** + * Handles player disconnection during an active game. + */ + public void handleDisconnect(P player) { + if (state != GameState.IN_PROGRESS) { + leave(player); + return; + } + + UUID uuid = player.getUuid(); + boolean canRejoin = canPlayerRejoin(player); + + if (canRejoin) { + disconnectedPlayers.put(uuid, new DisconnectedPlayerData( + uuid, + player.getServerPlayer().getUsername(), + System.currentTimeMillis(), + savePlayerData(player) + )); + } + + players.remove(uuid); + + eventDispatcher.accept(new PlayerDisconnectGameEvent( + gameId, + player.getServerPlayer(), + canRejoin + )); + + checkWinConditions(); + } + + public boolean handleRejoin(P player) { + DisconnectedPlayerData data = disconnectedPlayers.remove(player.getUuid()); + if (data == null || state != GameState.IN_PROGRESS) { + return false; + } + + players.put(player.getUuid(), player); + player.setGameId(gameId); + + eventDispatcher.accept(new PlayerRejoinGameEvent( + gameId, + player.getServerPlayer(), + data + )); + + return true; + } + + /** + * Checks if a disconnected player can rejoin. + */ + public boolean hasDisconnectedPlayer(UUID uuid) { + return disconnectedPlayers.containsKey(uuid); + } + + @Override + public void start() { + if (state != GameState.WAITING && state != GameState.COUNTDOWN) return; + if (countdown.isActive()) { + countdown.terminate(); + } + + setState(GameState.IN_PROGRESS); + + eventDispatcher.accept(new GameStartEvent(gameId)); + } + + @Override + public void end() { + if (state == GameState.ENDING || state == GameState.TERMINATED) return; + + setState(GameState.ENDING); + } + + @Override + public void dispose() { + setState(GameState.TERMINATED); + countdown.terminate(); + players.clear(); + disconnectedPlayers.clear(); + eventDispatcher.accept(new GameDisposeEvent( + gameId + )); + } + + /** + * Sets the game state and fires a state change event. + */ + protected void setState(GameState newState) { + if (this.state == newState) return; + + GameState oldState = this.state; + this.state = newState; + + eventDispatcher.accept(new GameStateChangeEvent(gameId, oldState, newState)); + } + + protected void checkWinConditions() { + eventDispatcher.accept( + new GameWinConditionEvent( + gameId + ) + ); + } + + /** + * Determines if a player can rejoin after disconnecting. + * Override for game-specific logic (e.g., bed status in BedWars). + */ + protected boolean canPlayerRejoin(P player) { + return true; + } + + /** + * Saves player data when they disconnect for potential rejoin. + * Override to save game-specific data. + */ + protected Map savePlayerData(P player) { + return new HashMap<>(); + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/AbstractTeamGame.java b/type.game/src/main/java/net/swofty/type/game/game/AbstractTeamGame.java new file mode 100644 index 000000000..7815698d5 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/AbstractTeamGame.java @@ -0,0 +1,192 @@ +package net.swofty.type.game.game; + +import net.kyori.adventure.audience.Audience; +import net.kyori.adventure.text.Component; +import net.minestom.server.instance.InstanceContainer; +import net.swofty.type.game.game.event.GameTeamWinConditionEvent; +import net.swofty.type.game.game.event.PlayerAssignedTeamEvent; +import net.swofty.type.game.game.event.TeamEliminatedEvent; +import net.swofty.type.game.game.team.GameTeam; +import net.swofty.type.game.game.team.TeamManager; +import org.tinylog.Logger; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Base game implementation with team assignment and team-based win conditions. + * + * @param

The player type + * @param The team type + */ +public abstract class AbstractTeamGame

+ extends AbstractGame

implements TeamManager { + + protected final Map teams = new LinkedHashMap<>(); + protected final Map playerTeams = new HashMap<>(); + + protected AbstractTeamGame(InstanceContainer instance, Consumer eventDispatcher) { + super(instance, eventDispatcher); + } + + /** + * Registers teams for this game. + * Call this during initialization. + */ + protected void registerTeam(T team) { + teams.put(team.getId(), team); + } + + @Override + public Collection getTeams() { + return Collections.unmodifiableCollection(teams.values()); + } + + @Override + public Optional getTeam(String teamId) { + return Optional.ofNullable(teams.get(teamId)); + } + + @Override + public Optional getPlayerTeam(UUID playerId) { + String teamId = playerTeams.get(playerId); + return teamId != null ? getTeam(teamId) : Optional.empty(); + } + + @Override + public void removeFromTeam(P player) { + String currentTeamId = playerTeams.remove(player.getUuid()); + if (currentTeamId != null) { + getTeam(currentTeamId).ifPresent(team -> team.removePlayer(player.getUuid())); + } + } + + @Override + public Collection getActiveTeams() { + return teams.values().stream() + .filter(GameTeam::hasPlayers) + .collect(Collectors.toList()); + } + + @Override + public Collection getViableTeams() { + return teams.values().stream() + .filter(this::isTeamViable) + .collect(Collectors.toList()); + } + + /** + * Determines if a team can still win the game. + */ + protected abstract boolean isTeamViable(T team); + + protected void onTeamEliminated(T team) { + eventDispatcher.accept(new TeamEliminatedEvent<>( + this, + team + )); + } + + public void broadcastMessage(Component message) { + Audience.audience(getPlayers().stream().map(GameParticipant::getServerPlayer).toList()).sendMessage(message); + } + + /** + * Checks if two players are on the same team. + * + * @param first uuid of the first player + * @param second uuid of the second player + * @return true if both players are on the same team, false otherwise + */ + public boolean isSameTeam(UUID first, UUID second) { + String team1 = playerTeams.get(first); + String team2 = playerTeams.get(second); + return team1 != null && team1.equals(team2); + } + + /** + * Auto-assigns all unassigned players to teams. + * Override for custom assignment logic. + */ + public void autoAssignTeams() { + List

unassignedPlayers = players.values().stream() + .filter(p -> !playerTeams.containsKey(p.getUuid())) + .collect(Collectors.toList()); + + if (unassignedPlayers.isEmpty() || teams.isEmpty()) { + return; + } + + Collections.shuffle(unassignedPlayers); + int teamSize = getTeamSize(); + + List shuffledTeams = new ArrayList<>(teams.values()); + Collections.shuffle(shuffledTeams); + Map teamPriority = new HashMap<>(); + for (int i = 0; i < shuffledTeams.size(); i++) { + teamPriority.put(shuffledTeams.get(i).getId(), i); + } + + for (P player : unassignedPlayers) { + T targetTeam = teams.values().stream() + .filter(team -> team.getPlayerCount() < teamSize) + .min((left, right) -> { + int byCount = Integer.compare(left.getPlayerCount(), right.getPlayerCount()); + if (byCount != 0) { + return byCount; + } + + int leftPriority = teamPriority.getOrDefault(left.getId(), Integer.MAX_VALUE); + int rightPriority = teamPriority.getOrDefault(right.getId(), Integer.MAX_VALUE); + return Integer.compare(leftPriority, rightPriority); + }) + .orElse(null); + + if (targetTeam != null) { + removeFromTeam(player); + targetTeam.addPlayer(player.getUuid()); + playerTeams.put(player.getUuid(), targetTeam.getId()); + + eventDispatcher.accept(new PlayerAssignedTeamEvent<>( + gameId, + player.getServerPlayer(), + targetTeam + )); + } + } + } + + /** + * @return The maximum team size for this game + */ + protected abstract int getTeamSize(); + + @Override + protected void checkWinConditions() { + if (state != GameState.IN_PROGRESS) return; + + List viableTeams = getViableTeams().stream().toList(); + Logger.info("Viable teams: {}", viableTeams.stream().map(T::getName).toList()); + if (viableTeams.size() <= 1) { + T winner = viableTeams.isEmpty() ? null : viableTeams.getFirst(); + + Logger.info("Game {} ended. Winner: {}", gameId, winner != null ? winner.getName() : "None"); + + eventDispatcher.accept( + new GameTeamWinConditionEvent<>( + gameId, + Optional.ofNullable(winner) + ) + ); + } + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/CountdownConfig.java b/type.game/src/main/java/net/swofty/type/game/game/CountdownConfig.java new file mode 100644 index 000000000..c7dbd3dcc --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/CountdownConfig.java @@ -0,0 +1,61 @@ +package net.swofty.type.game.game; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Controls countdown timing and announcements. + */ +public record CountdownConfig( + int durationSeconds, + int[] announcementTimes, + int acceleratedDurationSeconds, + int accelerationPlayerThreshold +) { + public static final CountdownConfig DEFAULT = new CountdownConfig( + 30, + new int[]{30, 20, 15, 10, 5, 4, 3, 2, 1}, + 10, + -1 // no accel + ); + + public CountdownConfig { + if (durationSeconds < 0) { + throw new IllegalArgumentException("durationSeconds must not be negative"); + } + if (acceleratedDurationSeconds < 0) { + throw new IllegalArgumentException("acceleratedDurationSeconds must not be negative"); + } + announcementTimes = Arrays.copyOf( + Objects.requireNonNull(announcementTimes, "announcementTimes"), + announcementTimes.length + ); + } + + @Override + public int[] announcementTimes() { + return Arrays.copyOf(announcementTimes, announcementTimes.length); + } + + public static CountdownConfig simple(int durationSeconds) { + return new CountdownConfig(durationSeconds, new int[]{10, 5, 4, 3, 2, 1}, durationSeconds, -1); + } + + public static CountdownConfig withAcceleration(int normalDuration, int acceleratedDuration, int playerThreshold) { + return new CountdownConfig( + normalDuration, + new int[]{30, 20, 15, 10, 5, 4, 3, 2, 1}, + acceleratedDuration, + playerThreshold + ); + } + + public boolean shouldAnnounce(int seconds) { + for (int announcementTime : announcementTimes) { + if (announcementTime == seconds) { + return true; + } + } + return false; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/DefaultGameCountdown.java b/type.game/src/main/java/net/swofty/type/game/game/DefaultGameCountdown.java new file mode 100644 index 000000000..58dfea6fb --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/DefaultGameCountdown.java @@ -0,0 +1,184 @@ +package net.swofty.type.game.game; + +import net.minestom.server.MinecraftServer; +import net.minestom.server.timer.Task; +import net.minestom.server.timer.TaskSchedule; +import net.swofty.type.game.game.event.CountdownCancelledEvent; +import net.swofty.type.game.game.event.CountdownTickEvent; + +import java.util.function.Consumer; + +public class DefaultGameCountdown implements GameCountdownController { + private final String gameId; + private final CountdownConfig config; + private final Consumer eventDispatcher; + private final Runnable onComplete; + private final Runnable onCancelled; + private final CanStartCheck canStartCheck; + + private int remainingSeconds; + private boolean active = false; + private boolean paused = false; + private Task countdownTask; + + @FunctionalInterface + public interface CanStartCheck { + boolean canContinue(); + } + + /** + * Creates a new countdown controller. + * + * @param gameId The game ID for events + * @param config Countdown configuration + * @param eventDispatcher event consumer, such as HypixelEventHandler::callCustomEvent + * @param onComplete Called when countdown completes + * @param canStartCheck Check if countdown should continue (e.g., has minimum players) + */ + public DefaultGameCountdown( + String gameId, + CountdownConfig config, + Consumer eventDispatcher, + Runnable onComplete, + CanStartCheck canStartCheck + ) { + this(gameId, config, eventDispatcher, onComplete, () -> { + }, canStartCheck); + } + + public DefaultGameCountdown( + String gameId, + CountdownConfig config, + Consumer eventDispatcher, + Runnable onComplete, + Runnable onCancelled, + CanStartCheck canStartCheck + ) { + this.gameId = gameId; + this.config = config; + this.eventDispatcher = eventDispatcher; + this.onComplete = onComplete; + this.onCancelled = onCancelled; + this.canStartCheck = canStartCheck; + this.remainingSeconds = config.durationSeconds(); + } + + @Override + public boolean start() { + if (active || !canStartCheck.canContinue()) { + return false; + } + + active = true; + paused = false; + remainingSeconds = config.durationSeconds(); + + dispatchTickEvent(); + + countdownTask = MinecraftServer.getSchedulerManager() + .buildTask(this::tick) + .delay(TaskSchedule.seconds(1)) + .repeat(TaskSchedule.seconds(1)) + .schedule(); + + return true; + } + + @Override + public void terminate() { + if (!active) return; + + active = false; + cancelTask(); + } + + @Override + public boolean pause() { + if (!active || paused) return false; + paused = true; + return true; + } + + @Override + public boolean resume() { + if (!active || !paused) return false; + paused = false; + return true; + } + + @Override + public boolean isActive() { + return active; + } + + @Override + public boolean isPaused() { + return paused; + } + + @Override + public int getRemainingSeconds() { + return remainingSeconds; + } + + @Override + public void setRemainingSeconds(int seconds) { + this.remainingSeconds = Math.max(0, seconds); + if (active) { + dispatchTickEvent(); + } + } + + @Override + public void accelerate(int newDuration) { + if (remainingSeconds > newDuration) { + remainingSeconds = newDuration; + if (active) { + dispatchTickEvent(); + } + } + } + + private void tick() { + if (!active) { + cancelTask(); + return; + } + + if (paused) { + return; + } + + if (!canStartCheck.canContinue()) { + terminate(); + onCancelled.run(); + eventDispatcher.accept(new CountdownCancelledEvent(gameId, "§cWe don't have enough players! Start cancelled.")); + return; + } + + remainingSeconds--; + dispatchTickEvent(); + + if (remainingSeconds <= 0) { + active = false; + cancelTask(); + onComplete.run(); + } + } + + private void dispatchTickEvent() { + eventDispatcher.accept(new CountdownTickEvent( + gameId, + remainingSeconds, + config.shouldAnnounce(remainingSeconds) + )); + } + + private void cancelTask() { + if (countdownTask != null) { + countdownTask.cancel(); + countdownTask = null; + } + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/Game.java b/type.game/src/main/java/net/swofty/type/game/game/Game.java new file mode 100644 index 000000000..0dfdc8ef8 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/Game.java @@ -0,0 +1,95 @@ +package net.swofty.type.game.game; + +import net.minestom.server.instance.InstanceContainer; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; + +public interface Game

{ + + String getGameId(); + + GameState getState(); + + InstanceContainer getInstance(); + + Collection

getPlayers(); + + /** + * @return The maximum number of players this game can hold + */ + int getMaxPlayers(); + + /** + * @return The minimum number of players required to start + */ + int getMinPlayers(); + + /** + * @return Number of available slots + */ + default int getAvailableSlots() { + return Math.max(0, getMaxPlayers() - getPlayers().size()); + } + + /** + * @return Whether new players can join this game + */ + default boolean canAcceptPlayers() { + return getState() == GameState.WAITING && getAvailableSlots() > 0; + } + + /** + * @return Whether the game has minimum players to start + */ + default boolean hasMinimumPlayers() { + return getPlayers().size() >= getMinPlayers(); + } + + /** + * Attempts to add a player to the game. + * @param player The player to add + * @return Result of the join attempt + */ + JoinResult join(P player); + + /** + * Removes a player from the game. + * @param player The player to remove + */ + void leave(P player); + + /** + * Gets a player by their UUID. + * @param uuid The player's UUID + * @return The player, if present + */ + Optional

getPlayer(UUID uuid); + + /** + * Starts the game. Called when countdown finishes. + */ + void start(); + + /** + * Ends the game. + */ + void end(); + + /** + * Cleans up resources when the game is disposed. + */ + void dispose(); + + /** + * @return The countdown controller for this game + */ + GameCountdownController getCountdown(); + + sealed interface JoinResult { + record Success() implements JoinResult {} + record Denied(String reason) implements JoinResult {} + record Redirect(String targetServer) implements JoinResult {} + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/GameCountdownController.java b/type.game/src/main/java/net/swofty/type/game/game/GameCountdownController.java new file mode 100644 index 000000000..ab30c1159 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/GameCountdownController.java @@ -0,0 +1,27 @@ +package net.swofty.type.game.game; + +public interface GameCountdownController { + boolean start(); + + void terminate(); + + default boolean pause() { + return false; + } + + default boolean resume() { + return false; + } + + boolean isActive(); + + default boolean isPaused() { + return false; + } + + int getRemainingSeconds(); + + void setRemainingSeconds(int seconds); + + void accelerate(int newDuration); +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/GameParticipant.java b/type.game/src/main/java/net/swofty/type/game/game/GameParticipant.java new file mode 100644 index 000000000..59406e543 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/GameParticipant.java @@ -0,0 +1,17 @@ +package net.swofty.type.game.game; + +import net.minestom.server.entity.Player; + +import java.util.UUID; + +public interface GameParticipant { + UUID getUuid(); + + boolean isOnline(); + + String getGameId(); + + void setGameId(String gameId); + + Player getServerPlayer(); +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/GameState.java b/type.game/src/main/java/net/swofty/type/game/game/GameState.java new file mode 100644 index 000000000..0c80b67be --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/GameState.java @@ -0,0 +1,21 @@ +package net.swofty.type.game.game; + +public enum GameState { + WAITING, + COUNTDOWN, + IN_PROGRESS, + ENDING, + TERMINATED; + + public boolean isInProgress() { + return this == IN_PROGRESS; + } + + public boolean isWaiting() { + return this == WAITING || this == COUNTDOWN; + } + + public boolean isEnding() { + return this == ENDING || this == TERMINATED; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/CountdownCancelledEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/CountdownCancelledEvent.java new file mode 100644 index 000000000..4b0caf00a --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/CountdownCancelledEvent.java @@ -0,0 +1,11 @@ +package net.swofty.type.game.game.event; + +public record CountdownCancelledEvent( + String gameId, + String reason +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/CountdownTickEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/CountdownTickEvent.java new file mode 100644 index 000000000..3cdcf8eeb --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/CountdownTickEvent.java @@ -0,0 +1,16 @@ +package net.swofty.type.game.game.event; + +public record CountdownTickEvent( + String gameId, + int remainingSeconds, + boolean shouldAnnounce +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } + + public boolean isComplete() { + return remainingSeconds <= 0; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/GameDisposeEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/GameDisposeEvent.java new file mode 100644 index 000000000..b0f795808 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/GameDisposeEvent.java @@ -0,0 +1,8 @@ +package net.swofty.type.game.game.event; + +public record GameDisposeEvent(String gameId) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/GameEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/GameEvent.java new file mode 100644 index 000000000..d284b38c8 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/GameEvent.java @@ -0,0 +1,7 @@ +package net.swofty.type.game.game.event; + +import net.minestom.server.event.Event; + +public interface GameEvent extends Event { + String getGameId(); +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/GameStartEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/GameStartEvent.java new file mode 100644 index 000000000..36cf193b9 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/GameStartEvent.java @@ -0,0 +1,8 @@ +package net.swofty.type.game.game.event; + +public record GameStartEvent(String gameId) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/GameStateChangeEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/GameStateChangeEvent.java new file mode 100644 index 000000000..1c3fa363f --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/GameStateChangeEvent.java @@ -0,0 +1,39 @@ +package net.swofty.type.game.game.event; + +import net.swofty.type.game.game.GameState; + +/** + * Event fired when a game's state changes. + * Listen to this for game lifecycle management. + */ +public record GameStateChangeEvent( + String gameId, + GameState previousState, + GameState newState +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } + + /** + * @return true if the game just started (transitioned to IN_PROGRESS) + */ + public boolean isGameStart() { + return newState == GameState.IN_PROGRESS && previousState != GameState.IN_PROGRESS; + } + + /** + * @return true if the game just ended (transitioned to ENDING) + */ + public boolean isGameEnd() { + return newState == GameState.ENDING && previousState != GameState.ENDING; + } + + /** + * @return true if countdown just started + */ + public boolean isCountdownStart() { + return newState == GameState.COUNTDOWN && previousState == GameState.WAITING; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/GameTeamWinConditionEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/GameTeamWinConditionEvent.java new file mode 100644 index 000000000..d382e26c9 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/GameTeamWinConditionEvent.java @@ -0,0 +1,16 @@ +package net.swofty.type.game.game.event; + +import net.swofty.type.game.game.team.GameTeam; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public record GameTeamWinConditionEvent( + @NotNull String gameId, + Optional team +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/GameWinConditionEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/GameWinConditionEvent.java new file mode 100644 index 000000000..afa504710 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/GameWinConditionEvent.java @@ -0,0 +1,10 @@ +package net.swofty.type.game.game.event; + +public record GameWinConditionEvent( + String gameId +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/PlayerAssignedTeamEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerAssignedTeamEvent.java new file mode 100644 index 000000000..113975deb --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerAssignedTeamEvent.java @@ -0,0 +1,14 @@ +package net.swofty.type.game.game.event; + +import net.minestom.server.entity.Player; + +public record PlayerAssignedTeamEvent( + String gameId, + Player player, + T team +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/PlayerDisconnectGameEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerDisconnectGameEvent.java new file mode 100644 index 000000000..7a0fc3c8f --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerDisconnectGameEvent.java @@ -0,0 +1,18 @@ +package net.swofty.type.game.game.event; + +import net.minestom.server.entity.Player; + +/** + * Event fired when a player disconnects during an active game. + * Different from PlayerLeaveGameEvent - this tracks disconnection for potential rejoin. + */ +public record PlayerDisconnectGameEvent( + String gameId, + Player player, + boolean canRejoin +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/PlayerEliminatedEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerEliminatedEvent.java new file mode 100644 index 000000000..88ab5da51 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerEliminatedEvent.java @@ -0,0 +1,40 @@ +package net.swofty.type.game.game.event; + +import java.util.UUID; + +/** + * Event fired when a player is eliminated from the game. + * This is different from leaving - the player may stay as spectator. + */ +public record PlayerEliminatedEvent( + String gameId, + UUID playerId, + String playerName, + UUID eliminatorId, + String eliminatorName, + EliminationCause cause +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } + + /** + * Creates an elimination event without a specific eliminator (e.g., void death). + */ + public static PlayerEliminatedEvent withoutEliminator(String gameId, UUID playerId, String playerName, EliminationCause cause) { + return new PlayerEliminatedEvent(gameId, playerId, playerName, null, null, cause); + } + + public boolean hasEliminator() { + return eliminatorId != null; + } + + public enum EliminationCause { + KILLED, + VOID, + ENVIRONMENT, + DISCONNECTED, + OTHER + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/PlayerLeaveGameEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerLeaveGameEvent.java new file mode 100644 index 000000000..398c32ad2 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerLeaveGameEvent.java @@ -0,0 +1,21 @@ +package net.swofty.type.game.game.event; + +import net.minestom.server.entity.Player; + +public record PlayerLeaveGameEvent( + String gameId, + Player player, + LeaveReason reason +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } + + public enum LeaveReason { + VOLUNTARY, + KICKED, + ELIMINATED, + GAME_END + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/PlayerPostJoinGameEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerPostJoinGameEvent.java new file mode 100644 index 000000000..69570984b --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerPostJoinGameEvent.java @@ -0,0 +1,15 @@ +package net.swofty.type.game.game.event; + +import net.minestom.server.entity.Player; + +public record PlayerPostJoinGameEvent( + String gameId, + Player player, + int currentPlayerCount, + int maxPlayerCount +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/PlayerPreJoinGameEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerPreJoinGameEvent.java new file mode 100644 index 000000000..4ec5f2598 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerPreJoinGameEvent.java @@ -0,0 +1,46 @@ +package net.swofty.type.game.game.event; + +import lombok.Getter; +import net.minestom.server.entity.Player; +import net.minestom.server.event.trait.CancellableEvent; +import net.minestom.server.event.trait.PlayerEvent; + +/** + * Event fired when a player attempts to join a game. + * Can be cancelled to prevent the join. + */ +public class PlayerPreJoinGameEvent implements GameEvent, PlayerEvent, CancellableEvent { + private final String gameId; + @Getter + private final Player player; + + private boolean cancelled = false; + @Getter + private String cancelReason = null; + + public PlayerPreJoinGameEvent(String gameId, Player player) { + this.gameId = gameId; + this.player = player; + } + + @Override + public String getGameId() { + return gameId; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + public void cancel(String reason) { + this.cancelled = true; + this.cancelReason = reason; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/PlayerRejoinGameEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerRejoinGameEvent.java new file mode 100644 index 000000000..2acb7b407 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/PlayerRejoinGameEvent.java @@ -0,0 +1,15 @@ +package net.swofty.type.game.game.event; + +import net.minestom.server.entity.Player; +import net.swofty.type.game.game.AbstractGame; + +public record PlayerRejoinGameEvent( + String gameId, + Player player, + AbstractGame.DisconnectedPlayerData disconnectedPlayerData +) implements GameEvent { + @Override + public String getGameId() { + return gameId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/event/TeamEliminatedEvent.java b/type.game/src/main/java/net/swofty/type/game/game/event/TeamEliminatedEvent.java new file mode 100644 index 000000000..624eb8955 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/event/TeamEliminatedEvent.java @@ -0,0 +1,14 @@ +package net.swofty.type.game.game.event; + +import net.swofty.type.game.game.AbstractTeamGame; +import net.swofty.type.game.game.team.GameTeam; + +public record TeamEliminatedEvent( + AbstractTeamGame game, + T team +) implements GameEvent { + @Override + public String getGameId() { + return game.getGameId(); + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/respawn/RespawnHandler.java b/type.game/src/main/java/net/swofty/type/game/game/respawn/RespawnHandler.java new file mode 100644 index 000000000..7e6308ca6 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/respawn/RespawnHandler.java @@ -0,0 +1,45 @@ +package net.swofty.type.game.game.respawn; + +import java.util.UUID; + +/** + * Interface for handling player respawns in games. + * + * @param

The player type + */ +public interface RespawnHandler

{ + /** + * Determines if a player can respawn. + * + * @param playerId The player's UUID + * @return true if the player can respawn + */ + boolean canRespawn(UUID playerId); + + /** + * Gets the respawn delay for a player. + * + * @param playerId The player's UUID + * @return Respawn delay in seconds + */ + int getRespawnDelay(UUID playerId); + + /** + * Starts the respawn process for a player. + * + * @param player The player to respawn + */ + void startRespawn(P player); + + /** + * Cancels a pending respawn. + * + * @param playerId The player's UUID + */ + void cancelRespawn(UUID playerId); + + /** + * Checks if a player is currently in respawn process. + */ + boolean isRespawning(UUID playerId); +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/team/GameTeam.java b/type.game/src/main/java/net/swofty/type/game/game/team/GameTeam.java new file mode 100644 index 000000000..ba4022359 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/team/GameTeam.java @@ -0,0 +1,35 @@ +package net.swofty.type.game.game.team; + +import java.util.Collection; +import java.util.UUID; + +public interface GameTeam { + String getId(); + String getName(); + + /** + * @return The legacy color code for the team (e.g., "§c" for red) + */ + String getColorCode(); + + Collection getPlayerIds(); + + default int getPlayerCount() { + return getPlayerIds().size(); + } + + /** + * @return Whether this team has any players + */ + default boolean hasPlayers() { + return !getPlayerIds().isEmpty(); + } + + void addPlayer(UUID playerId); + + void removePlayer(UUID playerId); + + default boolean hasPlayer(UUID playerId) { + return getPlayerIds().contains(playerId); + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/team/SimpleGameTeam.java b/type.game/src/main/java/net/swofty/type/game/game/team/SimpleGameTeam.java new file mode 100644 index 000000000..41e0d9c65 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/team/SimpleGameTeam.java @@ -0,0 +1,50 @@ +package net.swofty.type.game.game.team; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class SimpleGameTeam implements GameTeam { + private final String id; + private final String name; + private final String colorCode; + private final Set playerIds = ConcurrentHashMap.newKeySet(); + + public SimpleGameTeam(String id, String name, String colorCode) { + this.id = id; + this.name = name; + this.colorCode = colorCode; + } + + @Override + public String getId() { + return id; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getColorCode() { + return colorCode; + } + + @Override + public Collection getPlayerIds() { + return Collections.unmodifiableSet(playerIds); + } + + @Override + public void addPlayer(UUID playerId) { + playerIds.add(playerId); + } + + @Override + public void removePlayer(UUID playerId) { + playerIds.remove(playerId); + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/game/team/TeamManager.java b/type.game/src/main/java/net/swofty/type/game/game/team/TeamManager.java new file mode 100644 index 000000000..11f3485be --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/game/team/TeamManager.java @@ -0,0 +1,44 @@ +package net.swofty.type.game.game.team; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; + +/** + * Interface for team management in team-based games. + * + * @param The team type + * @param

The player type + */ +public interface TeamManager { + Collection getTeams(); + + /** + * Gets a team by its identifier. + */ + Optional getTeam(String teamId); + + /** + * Gets the team a player is on. + */ + Optional getPlayerTeam(UUID playerId); + + /** + * Removes a player from their team. + */ + void removeFromTeam(P player); + + /** + * @return Active teams (teams with players) + */ + Collection getActiveTeams(); + + default int getActiveTeamCount() { + return getActiveTeams().size(); + } + + /** + * @return Viable teams (can still win the game) + */ + Collection getViableTeams(); +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/ReplayError.java b/type.game/src/main/java/net/swofty/type/game/replay/ReplayError.java new file mode 100644 index 000000000..12ebf6b4a --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/ReplayError.java @@ -0,0 +1,24 @@ +package net.swofty.type.game.replay; + +import lombok.Getter; + +@Getter +public enum ReplayError { + UNSUPPORTED_CODEC(3, "UNSUPPORTED CODEC {}"), + REPLAY_NOT_FOUND(404, "REPLAY NOT FOUND"), + JAVA_EXCEPTION(500, "UNKNOWN EXCEPTION"), + REPLAY_INCOMPLETE(501, "REPLAY INCOMPLETE"), + ; + + private final int code; + private final String message; + + ReplayError(int code, String message) { + this.code = code; + this.message = message; + } + + public String format() { + return "ERROR-" + this.code + " - " + this.message; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/ReplayMetadata.java b/type.game/src/main/java/net/swofty/type/game/replay/ReplayMetadata.java new file mode 100644 index 000000000..150f01e47 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/ReplayMetadata.java @@ -0,0 +1,41 @@ +package net.swofty.type.game.replay; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.swofty.commons.ServerType; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +@Getter +@Setter +@Builder +public class ReplayMetadata { + private UUID replayId; + private String gameId; + private ServerType serverType; + private String serverId; + private String gameTypeName; + private String mapName; + private String mapHash; + private int version; + private long startTime; + private long endTime; + private int durationTicks; + private Map players; + private Map> teams; + private Map teamInfo; + private String winnerId; + private double mapCenterX; + private double mapCenterZ; + private long dataSize; + + public record TeamInfo( + String name, + String colorCode, + int color // RGB int + ) { + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/ReplayRecorder.java b/type.game/src/main/java/net/swofty/type/game/replay/ReplayRecorder.java new file mode 100644 index 000000000..bf84077a8 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/ReplayRecorder.java @@ -0,0 +1,263 @@ +package net.swofty.type.game.replay; + +import lombok.Getter; +import net.swofty.commons.ServerType; +import net.swofty.commons.protocol.objects.replay.ReplayDataBatchProtocolObject; +import net.swofty.commons.protocol.objects.replay.ReplayEndProtocolObject; +import net.swofty.commons.protocol.objects.replay.ReplayMapUploadProtocolObject; +import net.swofty.commons.protocol.objects.replay.ReplayStartProtocolObject; +import net.swofty.commons.replay.protocol.ReplayCompression; +import net.swofty.commons.replay.protocol.ReplayDataWriter; +import net.swofty.type.game.replay.recordable.Recordable; +import org.tinylog.Logger; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +/** + * remember: + * 1. Create a ReplayRecorder when game starts + * 2. Call tick() every server tick + * 3. Call record() to add recordables + * 4. Call finish() when game ends + */ +public class ReplayRecorder { + private static final int BATCH_SIZE = 1000; + private static final int BATCH_INTERVAL_TICKS = 200; // 10 seconds at 20 TPS + + @Getter + private final UUID replayId; + private final String gameId; + private final ServerType serverType; + private final Consumer serviceSender; + + private final ConcurrentLinkedQueue buffer = new ConcurrentLinkedQueue<>(); + private final AtomicInteger batchIndex = new AtomicInteger(0); + + @Getter + private volatile int currentTick = 0; + private volatile int lastBatchTick = 0; + private volatile boolean recording = false; + private volatile boolean finished = false; + + // Map center for coordinate optimization + private double mapCenterX = 0; + private double mapCenterZ = 0; + + /** + * Creates a new replay recorder. + * + * @param gameId The game ID + * @param serverType The server type + * @param serviceSender Function to send protocol messages to replay service + */ + public ReplayRecorder(String gameId, ServerType serverType, Consumer serviceSender) { + this.replayId = UUID.randomUUID(); + this.gameId = gameId; + this.serverType = serverType; + this.serviceSender = serviceSender; + } + + public void start( + String gameTypeName, + String serverId, + String mapName, + String mapHash, + Map players, + Map> teams, + Map teamInfo + ) { + recording = true; + currentTick = 0; + lastBatchTick = 0; + + var startMessage = new ReplayStartProtocolObject.StartMessage( + replayId, + gameId, + serverType, + serverId, + gameTypeName, + mapName, + mapHash, + System.currentTimeMillis(), + mapCenterX, + mapCenterZ, + players, + teams, + teamInfo + ); + + serviceSender.accept(startMessage); + Logger.info("Started replay recording {} for game {}", replayId, gameId); + } + + public void setMapCenter(double x, double z) { + this.mapCenterX = x; + this.mapCenterZ = z; + } + + public void tick() { + if (!recording || finished) return; + + currentTick++; + + // Check if we should send a batch + if (shouldSendBatch()) { + sendBatch(); + } + } + + public void record(Recordable recordable) { + if (!recording || finished) return; + + recordable.setTick(currentTick); + buffer.offer(recordable); + + if (buffer.size() >= BATCH_SIZE) { + sendBatch(); + } + } + + public void recordAll(Collection recordables) { + if (!recording || finished) return; + + for (Recordable recordable : recordables) { + recordable.setTick(currentTick); + buffer.offer(recordable); + } + + if (buffer.size() >= BATCH_SIZE) { + sendBatch(); + } + } + + private boolean shouldSendBatch() { + return !buffer.isEmpty() && (currentTick - lastBatchTick >= BATCH_INTERVAL_TICKS); + } + + private void sendBatch() { + if (buffer.isEmpty()) return; + + List toSend = new ArrayList<>(); + Recordable r; + while ((r = buffer.poll()) != null) { + toSend.add(r); + } + + if (toSend.isEmpty()) return; + + int startTick = toSend.getFirst().getTick(); + int endTick = toSend.getLast().getTick(); + + try { + byte[] data = serializeRecordables(toSend); + byte[] compressedData = ReplayCompression.compress(data); + + var batchMessage = new ReplayDataBatchProtocolObject.BatchMessage( + replayId, + batchIndex.getAndIncrement(), + startTick, + endTick, + toSend.size(), + compressedData + ); + + serviceSender.accept(batchMessage); + lastBatchTick = currentTick; + + Logger.debug("Sent batch {} with {} recordables ({} bytes -> {} bytes)", + batchMessage.batchIndex(), toSend.size(), data.length, compressedData.length); + + } catch (IOException e) { + Logger.error(e, "Failed to serialize recordables"); + } + } + + private byte[] serializeRecordables(List recordables) throws IOException { + ReplayDataWriter writer = new ReplayDataWriter(); + for (Recordable recordable : recordables) { + writer.writeVarInt(recordable.getTick()); + writer.writeByte(recordable.getType().getId()); + recordable.write(writer); + } + return writer.toByteArray(); + } + + public void finish() { + if (finished) return; + finished = true; + recording = false; + + sendBatch(); + + var endMessage = new ReplayEndProtocolObject.EndMessage( + replayId, + System.currentTimeMillis(), + currentTick + ); + + serviceSender.accept(endMessage); + Logger.info("Finished replay recording {} ({} ticks)", replayId, currentTick); + } + + public void uploadMapIfNeeded(String mapHash, String mapName, byte[] compressedData) { + var uploadMessage = new ReplayMapUploadProtocolObject.MapUploadMessage( + mapHash, + mapName, + compressedData + ); + serviceSender.accept(uploadMessage); + } + + /** + * @return The start tick of the current buffer + */ + public int getStartTick() { + return lastBatchTick; + } + + /** + * @return The number of recordables in the buffer + */ + public int getRecordableCount() { + return buffer.size(); + } + + /** + * Flushes and returns the current batch of data without sending it. + * Returns null if buffer is empty. + */ + public byte[] flushBatch() { + if (buffer.isEmpty()) return null; + + List toFlush = new ArrayList<>(); + Recordable r; + while ((r = buffer.poll()) != null) { + toFlush.add(r); + } + + if (toFlush.isEmpty()) return null; + + try { + lastBatchTick = currentTick; + return serializeRecordables(toFlush); + } catch (IOException e) { + Logger.error(e, "Failed to serialize recordables for flush"); + return null; + } + } + + /** + * @return Whether recording is active + */ + public boolean isRecording() { + return recording && !finished; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/ReplayVersion.java b/type.game/src/main/java/net/swofty/type/game/replay/ReplayVersion.java new file mode 100644 index 000000000..d7fda0e95 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/ReplayVersion.java @@ -0,0 +1,17 @@ +package net.swofty.type.game.replay; + +public final class ReplayVersion { + public static final int CURRENT_VERSION = 1; + + public static final int MIN_SUPPORTED_VERSION = 1; + + static { + //noinspection ConstantValue + if (CURRENT_VERSION < MIN_SUPPORTED_VERSION) { + throw new IllegalStateException("Current replay version is less than minimum supported version"); + } + } + + private ReplayVersion() { + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/BlockChangeDispatcher.java b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/BlockChangeDispatcher.java new file mode 100644 index 000000000..b89833c64 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/BlockChangeDispatcher.java @@ -0,0 +1,54 @@ +package net.swofty.type.game.replay.dispatcher; + +import net.swofty.type.game.replay.ReplayRecorder; +import net.swofty.type.game.replay.recordable.RecordableBlockChange; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class BlockChangeDispatcher implements ReplayDispatcher { + private ReplayRecorder recorder; + + private final Queue pendingChanges = new ConcurrentLinkedQueue<>(); + + public BlockChangeDispatcher() { + } + + @Override + public void initialize(ReplayRecorder recorder) { + this.recorder = recorder; + } + + public void recordBlockChange(int x, int y, int z, int previousBlock, int newBlock) { + pendingChanges.offer(new PendingBlockChange( + x, y, z, + newBlock, + previousBlock + )); + } + + @Override + public void tick() { + PendingBlockChange change; + while ((change = pendingChanges.poll()) != null) { + recorder.record(new RecordableBlockChange( + change.x, change.y, change.z, + change.newBlockStateId, + change.previousBlockStateId + )); + } + } + + @Override + public void cleanup() { + pendingChanges.clear(); + } + + @Override + public String getName() { + return "BlockChange"; + } + + private record PendingBlockChange(int x, int y, int z, int newBlockStateId, int previousBlockStateId) { + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/DispatcherManager.java b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/DispatcherManager.java new file mode 100644 index 000000000..f9ba6e603 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/DispatcherManager.java @@ -0,0 +1,52 @@ +package net.swofty.type.game.replay.dispatcher; + +import net.swofty.type.game.replay.ReplayRecorder; + +import java.util.ArrayList; +import java.util.List; + +public class DispatcherManager { + private final ReplayRecorder recorder; + private final List dispatchers = new ArrayList<>(); + + public DispatcherManager(ReplayRecorder recorder) { + this.recorder = recorder; + } + + public void register(ReplayDispatcher dispatcher) { + dispatcher.initialize(recorder); + dispatchers.add(dispatcher); + } + + public void tick() { + for (ReplayDispatcher dispatcher : dispatchers) { + try { + dispatcher.tick(); + } catch (Exception e) { + // Log but don't crash + org.tinylog.Logger.error(e, "Dispatcher {} tick failed", dispatcher.getName()); + } + } + } + + public void cleanup() { + for (ReplayDispatcher dispatcher : dispatchers) { + try { + dispatcher.cleanup(); + } catch (Exception e) { + org.tinylog.Logger.error(e, "Dispatcher {} cleanup failed", dispatcher.getName()); + } + } + dispatchers.clear(); + } + + @SuppressWarnings("unchecked") + public T getDispatcher(Class type) { + for (ReplayDispatcher dispatcher : dispatchers) { + if (type.isInstance(dispatcher)) { + return (T) dispatcher; + } + } + return null; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/EntityLocationDispatcher.java b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/EntityLocationDispatcher.java new file mode 100644 index 000000000..c41f9afa8 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/EntityLocationDispatcher.java @@ -0,0 +1,80 @@ +package net.swofty.type.game.replay.dispatcher; + +import net.minestom.server.entity.Entity; +import net.minestom.server.instance.Instance; +import net.swofty.type.game.replay.ReplayRecorder; +import net.swofty.type.game.replay.recordable.RecordableEntityLocations; + +import java.util.HashMap; +import java.util.Map; + +public class EntityLocationDispatcher implements ReplayDispatcher { + private ReplayRecorder recorder; + private Instance instance; + + private final Map lastLocations = new HashMap<>(); + + private static final double POSITION_THRESHOLD = 0.01; + private static final float ROTATION_THRESHOLD = 0.5f; + + public EntityLocationDispatcher(Instance instance) { + this.instance = instance; + } + + @Override + public void initialize(ReplayRecorder recorder) { + this.recorder = recorder; + } + + @Override + public void tick() { + RecordableEntityLocations locations = new RecordableEntityLocations(); + + for (Entity entity : instance.getEntities()) { + int entityId = entity.getEntityId(); + + double x = entity.getPosition().x(); + double y = entity.getPosition().y(); + double z = entity.getPosition().z(); + float yaw = entity.getPosition().yaw(); + float pitch = entity.getPosition().pitch(); + boolean onGround = entity.isOnGround(); + + CachedLocation cached = lastLocations.get(entityId); + if (cached == null || hasChanged(cached, x, y, z, yaw, pitch)) { + locations.addEntry(entityId, x, y, z, yaw, pitch, onGround); + lastLocations.put(entityId, new CachedLocation(x, y, z, yaw, pitch)); + } + } + + // Only record if there are changes + if (!locations.getEntries().isEmpty()) { + recorder.record(locations); + } + + // Clean up removed entities + lastLocations.keySet().removeIf(id -> + instance.getEntityById(id) == null + ); + } + + private boolean hasChanged(CachedLocation cached, double x, double y, double z, float yaw, float pitch) { + return Math.abs(cached.x - x) > POSITION_THRESHOLD || + Math.abs(cached.y - y) > POSITION_THRESHOLD || + Math.abs(cached.z - z) > POSITION_THRESHOLD || + Math.abs(cached.yaw - yaw) > ROTATION_THRESHOLD || + Math.abs(cached.pitch - pitch) > ROTATION_THRESHOLD; + } + + @Override + public void cleanup() { + lastLocations.clear(); + } + + @Override + public String getName() { + return "EntityLocation"; + } + + private record CachedLocation(double x, double y, double z, float yaw, float pitch) {} +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/ReplayDispatcher.java b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/ReplayDispatcher.java new file mode 100644 index 000000000..ae53d46f8 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/dispatcher/ReplayDispatcher.java @@ -0,0 +1,14 @@ +package net.swofty.type.game.replay.dispatcher; + +import net.swofty.type.game.replay.ReplayRecorder; + +public interface ReplayDispatcher { + void initialize(ReplayRecorder recorder); + + default void tick() { + } + + void cleanup(); + + String getName(); +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/entity/EntityStateTracker.java b/type.game/src/main/java/net/swofty/type/game/replay/entity/EntityStateTracker.java new file mode 100644 index 000000000..73fadfe7f --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/entity/EntityStateTracker.java @@ -0,0 +1,181 @@ +package net.swofty.type.game.replay.entity; + +import net.swofty.type.game.replay.recordable.Recordable; +import net.swofty.type.game.replay.recordable.RecordableType; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +public class EntityStateTracker { + private final Map>> states = new HashMap<>(); + private final Map defaultStates = new EnumMap<>(StateType.class); + + public enum StateType { + LOCATION(RecordableType.ENTITY_LOCATIONS), + EQUIPMENT_HELMET(RecordableType.ENTITY_EQUIPMENT), + EQUIPMENT_CHESTPLATE(RecordableType.ENTITY_EQUIPMENT), + EQUIPMENT_LEGGINGS(RecordableType.ENTITY_EQUIPMENT), + EQUIPMENT_BOOTS(RecordableType.ENTITY_EQUIPMENT), + EQUIPMENT_MAIN_HAND(RecordableType.ENTITY_EQUIPMENT), + EQUIPMENT_OFF_HAND(RecordableType.ENTITY_EQUIPMENT), + SNEAKING(RecordableType.PLAYER_SNEAK), + SPRINTING(RecordableType.PLAYER_SPRINT), + GAMEMODE(RecordableType.PLAYER_GAMEMODE), + MOUNT(RecordableType.ENTITY_MOUNT), + METADATA(RecordableType.ENTITY_METADATA), + ; + + public final RecordableType recordableType; + + StateType(RecordableType recordableType) { + this.recordableType = recordableType; + } + } + + public void recordState(int entityId, StateType stateType, int tick, Recordable recordable) { + states.computeIfAbsent(entityId, k -> new EnumMap<>(StateType.class)) + .computeIfAbsent(stateType, k -> new TreeMap<>()) + .put(tick, recordable); + } + + /** + * Gets the state at a specific tick. + * Returns the most recent state at or before the given tick. + * + * @param entityId The entity ID + * @param stateType The state type + * @param tick The tick to query + * @return The state, or null if no state exists + */ + public Recordable getStateAt(int entityId, StateType stateType, int tick) { + Map> entityStates = states.get(entityId); + if (entityStates == null) { + return defaultStates.get(stateType); + } + + TreeMap stateHistory = entityStates.get(stateType); + if (stateHistory == null || stateHistory.isEmpty()) { + return defaultStates.get(stateType); + } + + Map.Entry entry = stateHistory.floorEntry(tick); + if (entry == null) { + return defaultStates.get(stateType); + } + + return entry.getValue(); + } + + /** + * Gets all state changes for an entity between two ticks. + */ + public List getStatesBetween(int entityId, StateType stateType, int startTick, int endTick) { + Map> entityStates = states.get(entityId); + if (entityStates == null) return Collections.emptyList(); + + TreeMap stateHistory = entityStates.get(stateType); + if (stateHistory == null) return Collections.emptyList(); + + return new ArrayList<>(stateHistory.subMap(startTick, true, endTick, true).values()); + } + + /** + * Gets the latest state for each type for an entity at a given tick. + * Used when seeking to a specific time. + */ + public Map getAllStatesAt(int entityId, int tick) { + Map result = new EnumMap<>(StateType.class); + + Map> entityStates = states.get(entityId); + if (entityStates == null) { + for (StateType type : StateType.values()) { + Recordable def = defaultStates.get(type); + if (def != null) result.put(type, def); + } + return result; + } + + for (StateType type : StateType.values()) { + Recordable state = getStateAt(entityId, type, tick); + if (state != null) { + result.put(type, state); + } + } + + return result; + } + + public void setDefaultState(StateType stateType, Recordable defaultState) { + defaultStates.put(stateType, defaultState); + } + + public void removeEntity(int entityId) { + states.remove(entityId); + skinData.remove(entityId); + healthData.remove(entityId); + } + + public void clear() { + states.clear(); + skinData.clear(); + healthData.clear(); + } + + public Set getTrackedEntities() { + return new HashSet<>(states.keySet()); + } + + private final Map skinData = new HashMap<>(); + + public void trackSkin(int entityId, String textureValue, String textureSignature) { + skinData.put(entityId, new SkinData(textureValue, textureSignature)); + } + + public SkinData getSkin(int entityId) { + return skinData.get(entityId); + } + + public record SkinData(String textureValue, String textureSignature) { + } + + private final Map healthData = new HashMap<>(); + + public void trackHealth(int entityId, float health, float maxHealth) { + healthData.put(entityId, new HealthData(health, maxHealth)); + } + + public HealthData getHealth(int entityId) { + return healthData.get(entityId); + } + + public record HealthData(float health, float maxHealth) { + } + + public void track(Recordable recordable) { + if (!recordable.isEntityState() || recordable.getEntityId() < 0) return; + + StateType stateType = mapRecordableToStateType(recordable); + if (stateType != null) { + recordState(recordable.getEntityId(), stateType, 0, recordable); + } + } + + private StateType mapRecordableToStateType(Recordable recordable) { + return switch (recordable.getType()) { + case ENTITY_LOCATIONS -> StateType.LOCATION; + case PLAYER_SNEAK -> StateType.SNEAKING; + case PLAYER_SPRINT -> StateType.SPRINTING; + case PLAYER_GAMEMODE -> StateType.GAMEMODE; + case ENTITY_MOUNT -> StateType.MOUNT; + case ENTITY_METADATA -> StateType.METADATA; + default -> null; + }; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/AbstractRecordable.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/AbstractRecordable.java new file mode 100644 index 000000000..5abcda512 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/AbstractRecordable.java @@ -0,0 +1,15 @@ +package net.swofty.type.game.replay.recordable; + +public abstract class AbstractRecordable implements Recordable { + protected int tick; + + @Override + public int getTick() { + return tick; + } + + @Override + public void setTick(int tick) { + this.tick = tick; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/Recordable.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/Recordable.java new file mode 100644 index 000000000..956b3b811 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/Recordable.java @@ -0,0 +1,26 @@ +package net.swofty.type.game.replay.recordable; + +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +public interface Recordable { + RecordableType getType(); + + void write(ReplayDataWriter writer) throws IOException; + + void read(ReplayDataReader reader) throws IOException; + + int getTick(); + + void setTick(int tick); + + default boolean isEntityState() { + return false; + } + + default int getEntityId() { + return -1; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBatch.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBatch.java new file mode 100644 index 000000000..c032da20a --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBatch.java @@ -0,0 +1,59 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableBatch extends AbstractRecordable { + private List recordables = new ArrayList<>(); + + public RecordableBatch(List recordables) { + this.recordables = recordables; + } + + public void add(Recordable recordable) { + recordables.add(recordable); + } + + @Override + public RecordableType getType() { + return RecordableType.BATCH; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(recordables.size()); + for (Recordable recordable : recordables) { + writer.writeVarInt(recordable.getTick()); + writer.writeByte(recordable.getType().getId()); + recordable.write(writer); + } + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + int count = reader.readVarInt(); + recordables = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + int tick = reader.readVarInt(); + int typeId = reader.readUnsignedByte(); + RecordableType type = RecordableType.byId(typeId); + if (type == null) { + throw new IOException("Unknown recordable type: " + typeId); + } + Recordable recordable = type.createAndRead(reader); + recordable.setTick(tick); + recordables.add(recordable); + } + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBlockBreakAnimation.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBlockBreakAnimation.java new file mode 100644 index 000000000..5ebfefb8b --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBlockBreakAnimation.java @@ -0,0 +1,55 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableBlockBreakAnimation extends AbstractRecordable { + private int entityId; + private int x; + private int y; + private int z; + private byte stage; // 0-9, or -1 to stop + + public RecordableBlockBreakAnimation(int entityId, int x, int y, int z, byte stage) { + this.entityId = entityId; + this.x = x; + this.y = y; + this.z = z; + this.stage = stage; + } + + @Override + public RecordableType getType() { + return RecordableType.BLOCK_BREAK_ANIMATION; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeBlockCoords(x, y, z); + writer.writeByte(stage); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + int[] coords = reader.readBlockCoords(); + x = coords[0]; + y = coords[1]; + z = coords[2]; + stage = (byte) reader.readByte(); + } + + @Override + public int getEntityId() { + return entityId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBlockChange.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBlockChange.java new file mode 100644 index 000000000..ab3923e83 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableBlockChange.java @@ -0,0 +1,51 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableBlockChange extends AbstractRecordable { + private int x; + private int y; + private int z; + private int blockStateId; + private int previousBlockStateId; + + public RecordableBlockChange(int x, int y, int z, int blockStateId, int previousBlockStateId) { + this.x = x; + this.y = y; + this.z = z; + this.blockStateId = blockStateId; + this.previousBlockStateId = previousBlockStateId; + } + + @Override + public RecordableType getType() { + return RecordableType.BLOCK_CHANGE; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeBlockCoords(x, y, z); + writer.writeVarInt(blockStateId); + writer.writeVarInt(previousBlockStateId); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + int[] coords = reader.readBlockCoords(); + x = coords[0]; + y = coords[1]; + z = coords[2]; + blockStateId = reader.readVarInt(); + previousBlockStateId = reader.readVarInt(); + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableDroppedItem.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableDroppedItem.java new file mode 100644 index 000000000..b4f3d5c66 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableDroppedItem.java @@ -0,0 +1,89 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableDroppedItem extends AbstractRecordable { + private int entityId; + private UUID entityUuid; + private double x; + private double y; + private double z; + private float velocityX; + private float velocityY; + private float velocityZ; + private byte[] itemNbt; // Serialized item data + private int pickupDelay; // Ticks until item can be picked up + private int despawnTick; // Tick when item should despawn (0 = no auto-despawn) + + public RecordableDroppedItem(int entityId, UUID entityUuid, + double x, double y, double z, + float velocityX, float velocityY, float velocityZ, + byte[] itemNbt, int pickupDelay, int despawnTick) { + this.entityId = entityId; + this.entityUuid = entityUuid; + this.x = x; + this.y = y; + this.z = z; + this.velocityX = velocityX; + this.velocityY = velocityY; + this.velocityZ = velocityZ; + this.itemNbt = itemNbt; + this.pickupDelay = pickupDelay; + this.despawnTick = despawnTick; + } + + @Override + public RecordableType getType() { + return RecordableType.DROPPED_ITEM; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeUUID(entityUuid); + writer.writeLocation(x, y, z, 0, 0); + writer.writeFloat(velocityX); + writer.writeFloat(velocityY); + writer.writeFloat(velocityZ); + writer.writeBytes(itemNbt); + writer.writeVarInt(pickupDelay); + writer.writeVarInt(despawnTick); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + entityUuid = reader.readUUID(); + double[] loc = reader.readLocation(); + x = loc[0]; + y = loc[1]; + z = loc[2]; + velocityX = reader.readFloat(); + velocityY = reader.readFloat(); + velocityZ = reader.readFloat(); + itemNbt = reader.readBytes(); + pickupDelay = reader.readVarInt(); + despawnTick = reader.readVarInt(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableDynamicTextDisplay.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableDynamicTextDisplay.java new file mode 100644 index 000000000..c2d431347 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableDynamicTextDisplay.java @@ -0,0 +1,86 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableDynamicTextDisplay extends AbstractRecordable { + private int entityId; + private UUID entityUuid; + private double x; + private double y; + private double z; + private List textLines; + private String displayType; // "generator", "hologram", "scoreboard_line" + private String displayIdentifier; + + public RecordableDynamicTextDisplay(int entityId, UUID entityUuid, + double x, double y, double z, + List textLines, + String displayType, String displayIdentifier) { + this.entityId = entityId; + this.entityUuid = entityUuid; + this.x = x; + this.y = y; + this.z = z; + this.textLines = textLines != null ? new ArrayList<>(textLines) : new ArrayList<>(); + this.displayType = displayType != null ? displayType : ""; + this.displayIdentifier = displayIdentifier != null ? displayIdentifier : ""; + } + + @Override + public RecordableType getType() { + return RecordableType.DYNAMIC_TEXT_DISPLAY; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeUUID(entityUuid); + writer.writeLocation(x, y, z, 0, 0); + writer.writeVarInt(textLines.size()); + for (String line : textLines) { + writer.writeString(line); + } + writer.writeString(displayType); + writer.writeString(displayIdentifier); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + entityUuid = reader.readUUID(); + double[] loc = reader.readLocation(); + x = loc[0]; + y = loc[1]; + z = loc[2]; + int lineCount = reader.readVarInt(); + textLines = new ArrayList<>(lineCount); + for (int i = 0; i < lineCount; i++) { + textLines.add(reader.readString()); + } + displayType = reader.readString(); + displayIdentifier = reader.readString(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityAnimation.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityAnimation.java new file mode 100644 index 000000000..b7f1d3ab6 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityAnimation.java @@ -0,0 +1,53 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityAnimation extends AbstractRecordable { + private int entityId; + private AnimationType animation; + + public RecordableEntityAnimation(int entityId, AnimationType animation) { + this.entityId = entityId; + this.animation = animation; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_ANIMATION; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeByte(animation.ordinal()); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + animation = AnimationType.values()[reader.readUnsignedByte()]; + } + + @Override + public int getEntityId() { + return entityId; + } + + public enum AnimationType { + SWING_MAIN_HAND, + TAKE_DAMAGE, + LEAVE_BED, + SWING_OFFHAND, + CRITICAL_EFFECT, + MAGIC_CRITICAL_EFFECT + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityDespawn.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityDespawn.java new file mode 100644 index 000000000..baf9b2d97 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityDespawn.java @@ -0,0 +1,41 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityDespawn extends AbstractRecordable { + private int entityId; + + public RecordableEntityDespawn(int entityId) { + this.entityId = entityId; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_DESPAWN; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + } + + @Override + public int getEntityId() { + return entityId; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEffect.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEffect.java new file mode 100644 index 000000000..40244bafd --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEffect.java @@ -0,0 +1,57 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityEffect extends AbstractRecordable { + private int entityId; + private int effectId; + private byte amplifier; + private int durationTicks; + private byte flags; // ambient, particles, icon visibility - bitmask + + public RecordableEntityEffect(int entityId, int effectId, byte amplifier, int durationTicks, byte flags) { + this.entityId = entityId; + this.effectId = effectId; + this.amplifier = amplifier; + this.durationTicks = durationTicks; + this.flags = flags; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_EFFECT; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeVarInt(effectId); + writer.writeByte(amplifier); + writer.writeVarInt(durationTicks); + writer.writeByte(flags); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + effectId = reader.readVarInt(); + amplifier = (byte) reader.readByte(); + durationTicks = reader.readVarInt(); + flags = (byte) reader.readByte(); + } + + @Override + public int getEntityId() { + return entityId; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEffectRemove.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEffectRemove.java new file mode 100644 index 000000000..811c06c81 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEffectRemove.java @@ -0,0 +1,45 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityEffectRemove extends AbstractRecordable { + private int entityId; + private int effectId; + + public RecordableEntityEffectRemove(int entityId, int effectId) { + this.entityId = entityId; + this.effectId = effectId; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_EFFECT_REMOVE; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeVarInt(effectId); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + effectId = reader.readVarInt(); + } + + @Override + public int getEntityId() { + return entityId; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEquipment.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEquipment.java new file mode 100644 index 000000000..7da797f97 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityEquipment.java @@ -0,0 +1,54 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityEquipment extends AbstractRecordable { + private int entityId; + private int slotId; + private byte[] itemBytes; // Serialized item + + public RecordableEntityEquipment(int entityId, int slotId, byte[] itemBytes) { + this.entityId = entityId; + this.slotId = slotId; + this.itemBytes = itemBytes; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_EQUIPMENT; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeByte(slotId); + writer.writeBytes(itemBytes != null ? itemBytes : new byte[0]); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + slotId = reader.readUnsignedByte(); + itemBytes = reader.readBytes(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityLocations.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityLocations.java new file mode 100644 index 000000000..5bfd54eb3 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityLocations.java @@ -0,0 +1,66 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityLocations extends AbstractRecordable { + private List entries = new ArrayList<>(); + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_LOCATIONS; + } + + public void addEntry(int entityId, double x, double y, double z, float yaw, float pitch, boolean onGround) { + entries.add(new EntityLocationEntry(entityId, x, y, z, yaw, pitch, onGround)); + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entries.size()); + for (EntityLocationEntry entry : entries) { + writer.writeVarInt(entry.entityId); + writer.writeLocation(entry.x, entry.y, entry.z, entry.yaw, entry.pitch); + writer.writeBoolean(entry.onGround); + } + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + int count = reader.readVarInt(); + entries = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + int entityId = reader.readVarInt(); + double[] loc = reader.readLocation(); + boolean onGround = reader.readBoolean(); + entries.add(new EntityLocationEntry( + entityId, loc[0], loc[1], loc[2], (float) loc[3], (float) loc[4], onGround + )); + } + } + + @Override + public boolean isEntityState() { + return true; // Location is an entity state - can skip to latest + } + + public record EntityLocationEntry( + int entityId, + double x, + double y, + double z, + float yaw, + float pitch, + boolean onGround + ) {} +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityMetadata.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityMetadata.java new file mode 100644 index 000000000..c2d7b28c5 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityMetadata.java @@ -0,0 +1,50 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityMetadata extends AbstractRecordable { + private int entityId; + private byte[] metadataBytes; + + public RecordableEntityMetadata(int entityId, byte[] metadataBytes) { + this.entityId = entityId; + this.metadataBytes = metadataBytes; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_METADATA; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeBytes(metadataBytes); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + metadataBytes = reader.readBytes(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityMount.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityMount.java new file mode 100644 index 000000000..eab021b28 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntityMount.java @@ -0,0 +1,58 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntityMount extends AbstractRecordable { + private int vehicleId; + private List passengerIds = new ArrayList<>(); + + public RecordableEntityMount(int vehicleId, List passengerIds) { + this.vehicleId = vehicleId; + this.passengerIds = passengerIds; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_MOUNT; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(vehicleId); + writer.writeVarInt(passengerIds.size()); + for (int passengerId : passengerIds) { + writer.writeVarInt(passengerId); + } + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + vehicleId = reader.readVarInt(); + int count = reader.readVarInt(); + passengerIds = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + passengerIds.add(reader.readVarInt()); + } + } + + @Override + public int getEntityId() { + return vehicleId; + } + + @Override + public boolean isEntityState() { + return true; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntitySpawn.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntitySpawn.java new file mode 100644 index 000000000..a6ac6d62f --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableEntitySpawn.java @@ -0,0 +1,80 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableEntitySpawn extends AbstractRecordable { + private int entityId; + private UUID entityUuid; + private int entityTypeId; + private double x; + private double y; + private double z; + private float yaw; + private float pitch; + private byte[] initialMetadata; // Optional metadata + + public RecordableEntitySpawn(int entityId, UUID entityUuid, int entityTypeId, + double x, double y, double z, float yaw, float pitch) { + this.entityId = entityId; + this.entityUuid = entityUuid; + this.entityTypeId = entityTypeId; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } + + @Override + public RecordableType getType() { + return RecordableType.ENTITY_SPAWN; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeUUID(entityUuid); + writer.writeVarInt(entityTypeId); + writer.writeLocation(x, y, z, yaw, pitch); + + boolean hasMetadata = initialMetadata != null && initialMetadata.length > 0; + writer.writeBoolean(hasMetadata); + if (hasMetadata) { + writer.writeBytes(initialMetadata); + } + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + entityUuid = reader.readUUID(); + entityTypeId = reader.readVarInt(); + + double[] loc = reader.readLocation(); + x = loc[0]; + y = loc[1]; + z = loc[2]; + yaw = (float) loc[3]; + pitch = (float) loc[4]; + + if (reader.readBoolean()) { + initialMetadata = reader.readBytes(); + } + } + + @Override + public int getEntityId() { + return entityId; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableExplosion.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableExplosion.java new file mode 100644 index 000000000..e3866c2be --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableExplosion.java @@ -0,0 +1,65 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableExplosion extends AbstractRecordable { + private double x, y, z; + private float strength; + private List affectedBlocks = new ArrayList<>(); + private float playerMotionX, playerMotionY, playerMotionZ; + + public RecordableExplosion(double x, double y, double z, float strength) { + this.x = x; + this.y = y; + this.z = z; + this.strength = strength; + } + + @Override + public RecordableType getType() { + return RecordableType.EXPLOSION; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeLocation(x, y, z, 0, 0); + writer.writeHalfFloat(strength); + writer.writeVarInt(affectedBlocks.size()); + for (int[] block : affectedBlocks) { + writer.writeByte(block[0]); // Relative offsets fit in bytes + writer.writeByte(block[1]); + writer.writeByte(block[2]); + } + writer.writeHalfFloat(playerMotionX); + writer.writeHalfFloat(playerMotionY); + writer.writeHalfFloat(playerMotionZ); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + double[] loc = reader.readLocation(); + x = loc[0]; + y = loc[1]; + z = loc[2]; + strength = reader.readHalfFloat(); + int count = reader.readVarInt(); + affectedBlocks = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + affectedBlocks.add(new int[]{reader.readByte(), reader.readByte(), reader.readByte()}); + } + playerMotionX = reader.readHalfFloat(); + playerMotionY = reader.readHalfFloat(); + playerMotionZ = reader.readHalfFloat(); + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableItemPickup.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableItemPickup.java new file mode 100644 index 000000000..5e3b8028b --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableItemPickup.java @@ -0,0 +1,45 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableItemPickup extends AbstractRecordable { + private int itemEntityId; + private int collectorEntityId; + + public RecordableItemPickup(int itemEntityId, int collectorEntityId) { + this.itemEntityId = itemEntityId; + this.collectorEntityId = collectorEntityId; + } + + @Override + public RecordableType getType() { + return RecordableType.ITEM_PICKUP; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(itemEntityId); + writer.writeVarInt(collectorEntityId); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + itemEntityId = reader.readVarInt(); + collectorEntityId = reader.readVarInt(); + } + + @Override + public int getEntityId() { + return itemEntityId; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableNpcDisplayName.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableNpcDisplayName.java new file mode 100644 index 000000000..22c0a08bd --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableNpcDisplayName.java @@ -0,0 +1,68 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableNpcDisplayName extends AbstractRecordable { + private int entityId; + private String displayName; + private String prefix; + private String suffix; + private int nameColor; + private boolean visible; // whether the name is visible above the NPC + + public RecordableNpcDisplayName(int entityId, String displayName, + String prefix, String suffix, + int nameColor, boolean visible) { + this.entityId = entityId; + this.displayName = displayName != null ? displayName : ""; + this.prefix = prefix != null ? prefix : ""; + this.suffix = suffix != null ? suffix : ""; + this.nameColor = nameColor; + this.visible = visible; + } + + @Override + public RecordableType getType() { + return RecordableType.NPC_DISPLAY_NAME; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeString(displayName); + writer.writeString(prefix); + writer.writeString(suffix); + writer.writeInt(nameColor); + writer.writeBoolean(visible); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + displayName = reader.readString(); + prefix = reader.readString(); + suffix = reader.readString(); + nameColor = reader.readInt(); + visible = reader.readBoolean(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableNpcTextLine.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableNpcTextLine.java new file mode 100644 index 000000000..fa760a1d5 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableNpcTextLine.java @@ -0,0 +1,75 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableNpcTextLine extends AbstractRecordable { + private int entityId; + private List textLines; + private double yOffset; // vertical offset from NPC position + private int displayDurationTicks; // how long to show (0 = indefinite) + + public RecordableNpcTextLine(int entityId, List textLines, + double yOffset, int displayDurationTicks) { + this.entityId = entityId; + this.textLines = textLines != null ? new ArrayList<>(textLines) : new ArrayList<>(); + this.yOffset = yOffset; + this.displayDurationTicks = displayDurationTicks; + } + + /** + * Convenience constructor for simple single-line text. + */ + public RecordableNpcTextLine(int entityId, String text, double yOffset) { + this(entityId, List.of(text), yOffset, 0); + } + + @Override + public RecordableType getType() { + return RecordableType.NPC_TEXT_LINE; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeVarInt(textLines.size()); + for (String line : textLines) { + writer.writeString(line); + } + writer.writeDouble(yOffset); + writer.writeVarInt(displayDurationTicks); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + int lineCount = reader.readVarInt(); + textLines = new ArrayList<>(lineCount); + for (int i = 0; i < lineCount; i++) { + textLines.add(reader.readString()); + } + yOffset = reader.readDouble(); + displayDurationTicks = reader.readVarInt(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableParticle.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableParticle.java new file mode 100644 index 000000000..5904756bc --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableParticle.java @@ -0,0 +1,35 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableParticle extends AbstractRecordable { + private byte[] data; + + public RecordableParticle(byte[] data) { + this.data = data; + } + + @Override + public RecordableType getType() { + return RecordableType.PARTICLE; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeBytes(data); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + this.data = reader.readBytes(); + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerArmSwing.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerArmSwing.java new file mode 100644 index 000000000..59fab06d4 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerArmSwing.java @@ -0,0 +1,45 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerArmSwing extends AbstractRecordable { + private int entityId; + private boolean mainHand; + + public RecordablePlayerArmSwing(int entityId, boolean mainHand) { + this.entityId = entityId; + this.mainHand = mainHand; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_ARM_SWING; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeBoolean(mainHand); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + mainHand = reader.readBoolean(); + } + + @Override + public int getEntityId() { + return entityId; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerChat.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerChat.java new file mode 100644 index 000000000..594cd33c4 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerChat.java @@ -0,0 +1,49 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerChat extends AbstractRecordable { + private int entityId; + private String message; + private boolean shout; + + public RecordablePlayerChat(int entityId, String message, boolean shout) { + this.entityId = entityId; + this.message = message; + this.shout = shout; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_CHAT; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeString(message); + writer.writeBoolean(shout); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + message = reader.readString(); + shout = reader.readBoolean(); + } + + @Override + public int getEntityId() { + return entityId; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerDeath.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerDeath.java new file mode 100644 index 000000000..06824729c --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerDeath.java @@ -0,0 +1,49 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerDeath extends AbstractRecordable { + private int entityId; + private int killerId; // -1 if no killer + private String deathMessage; + + public RecordablePlayerDeath(int entityId, int killerId, String deathMessage) { + this.entityId = entityId; + this.killerId = killerId; + this.deathMessage = deathMessage; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_DEATH; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeSignedVarInt(killerId); + writer.writeString(deathMessage != null ? deathMessage : ""); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + killerId = reader.readSignedVarInt(); + deathMessage = reader.readString(); + if (deathMessage.isEmpty()) deathMessage = null; + } + + @Override + public int getEntityId() { + return entityId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerDisplayName.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerDisplayName.java new file mode 100644 index 000000000..3ae3697a8 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerDisplayName.java @@ -0,0 +1,62 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerDisplayName extends AbstractRecordable { + private int entityId; + private String displayName; + private String prefix; + private String suffix; + private int nameColor; + + public RecordablePlayerDisplayName(int entityId, String displayName, String prefix, String suffix, int nameColor) { + this.entityId = entityId; + this.displayName = displayName; + this.prefix = prefix != null ? prefix : ""; + this.suffix = suffix != null ? suffix : ""; + this.nameColor = nameColor; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_DISPLAY_NAME; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeString(displayName); + writer.writeString(prefix); + writer.writeString(suffix); + writer.writeInt(nameColor); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + displayName = reader.readString(); + prefix = reader.readString(); + suffix = reader.readString(); + nameColor = reader.readInt(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerGamemode.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerGamemode.java new file mode 100644 index 000000000..2683c0fee --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerGamemode.java @@ -0,0 +1,49 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerGamemode extends AbstractRecordable { + private int entityId; + private byte gamemode; // 0=survival, 1=creative, 2=adventure, 3=spectator + + public RecordablePlayerGamemode(int entityId, byte gamemode) { + this.entityId = entityId; + this.gamemode = gamemode; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_GAMEMODE; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeByte(gamemode); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + gamemode = (byte) reader.readByte(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerHandItem.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerHandItem.java new file mode 100644 index 000000000..a34d038ba --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerHandItem.java @@ -0,0 +1,49 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerHandItem extends AbstractRecordable { + private int entityId; + private byte[] itemBytes; + + public RecordablePlayerHandItem(int entityId, byte[] itemBytes) { + this.entityId = entityId; + this.itemBytes = itemBytes; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_HAND_ITEM; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeBytes(itemBytes != null ? itemBytes : new byte[0]); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + itemBytes = reader.readBytes(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerHealth.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerHealth.java new file mode 100644 index 000000000..c8ef6c72b --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerHealth.java @@ -0,0 +1,54 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerHealth extends AbstractRecordable { + private int entityId; + private float health; + private float maxHealth; + + public RecordablePlayerHealth(int entityId, float health, float maxHealth) { + this.entityId = entityId; + this.health = health; + this.maxHealth = maxHealth; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_HEALTH; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeHalfFloat(health); + writer.writeHalfFloat(maxHealth); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + health = reader.readHalfFloat(); + maxHealth = reader.readHalfFloat(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerRespawn.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerRespawn.java new file mode 100644 index 000000000..872c4c3b3 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerRespawn.java @@ -0,0 +1,54 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerRespawn extends AbstractRecordable { + private int entityId; + private double x, y, z; + private float yaw, pitch; + + public RecordablePlayerRespawn(int entityId, double x, double y, double z, float yaw, float pitch) { + this.entityId = entityId; + this.x = x; + this.y = y; + this.z = z; + this.yaw = yaw; + this.pitch = pitch; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_RESPAWN; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeLocation(x, y, z, yaw, pitch); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + double[] loc = reader.readLocation(); + x = loc[0]; + y = loc[1]; + z = loc[2]; + yaw = (float) loc[3]; + pitch = (float) loc[4]; + } + + @Override + public int getEntityId() { + return entityId; + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSkin.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSkin.java new file mode 100644 index 000000000..9b331018d --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSkin.java @@ -0,0 +1,59 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerSkin extends AbstractRecordable { + private int entityId; + private UUID playerUuid; + private String textureValue; // Base64 encoded skin texture + private String textureSignature; // Mojang signature (can be empty) + + public RecordablePlayerSkin(int entityId, UUID playerUuid, String textureValue, String textureSignature) { + this.entityId = entityId; + this.playerUuid = playerUuid; + this.textureValue = textureValue; + this.textureSignature = textureSignature != null ? textureSignature : ""; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_SKIN; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeUUID(playerUuid); + writer.writeString(textureValue); + writer.writeString(textureSignature); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + playerUuid = reader.readUUID(); + textureValue = reader.readString(); + textureSignature = reader.readString(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSneak.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSneak.java new file mode 100644 index 000000000..5245fc2d9 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSneak.java @@ -0,0 +1,50 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerSneak extends AbstractRecordable { + private int entityId; + private boolean sneaking; + + public RecordablePlayerSneak(int entityId, boolean sneaking) { + this.entityId = entityId; + this.sneaking = sneaking; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_SNEAK; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeBoolean(sneaking); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + sneaking = reader.readBoolean(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSprint.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSprint.java new file mode 100644 index 000000000..98e668dfd --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordablePlayerSprint.java @@ -0,0 +1,50 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordablePlayerSprint extends AbstractRecordable { + private int entityId; + private boolean sprinting; + + public RecordablePlayerSprint(int entityId, boolean sprinting) { + this.entityId = entityId; + this.sprinting = sprinting; + } + + @Override + public RecordableType getType() { + return RecordableType.PLAYER_SPRINT; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeBoolean(sprinting); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + sprinting = reader.readBoolean(); + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableSound.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableSound.java new file mode 100644 index 000000000..f4bce2a08 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableSound.java @@ -0,0 +1,56 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableSound extends AbstractRecordable { + private String soundId; // namespace:sound + private byte category; // master + private double x, y, z; + private float volume; + private float pitch; + + public RecordableSound(String soundId, byte category, double x, double y, double z, float volume, float pitch) { + this.soundId = soundId; + this.category = category; + this.x = x; + this.y = y; + this.z = z; + this.volume = volume; + this.pitch = pitch; + } + + @Override + public RecordableType getType() { + return RecordableType.SOUND; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeString(soundId); + writer.writeByte(category); + writer.writeLocation(x, y, z, 0, 0); + writer.writeHalfFloat(volume); + writer.writeHalfFloat(pitch); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + soundId = reader.readString(); + category = (byte) reader.readByte(); + double[] loc = reader.readLocation(); + x = loc[0]; + y = loc[1]; + z = loc[2]; + volume = reader.readHalfFloat(); + pitch = reader.readHalfFloat(); + } +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableTextDisplayUpdate.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableTextDisplayUpdate.java new file mode 100644 index 000000000..1069807a9 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableTextDisplayUpdate.java @@ -0,0 +1,79 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableTextDisplayUpdate extends AbstractRecordable { + private int entityId; + private List newTextLines; + private boolean replaceAll; // true = replace all lines, false = update specific lines + private int startLineIndex; // if replaceAll is false, starting index for updates + + public RecordableTextDisplayUpdate(int entityId, List newTextLines, + boolean replaceAll, int startLineIndex) { + this.entityId = entityId; + this.newTextLines = newTextLines != null ? new ArrayList<>(newTextLines) : new ArrayList<>(); + this.replaceAll = replaceAll; + this.startLineIndex = startLineIndex; + } + + /** + * Convenience constructor for replacing all lines. + */ + public RecordableTextDisplayUpdate(int entityId, List newTextLines) { + this(entityId, newTextLines, true, 0); + } + + @Override + public RecordableType getType() { + return RecordableType.TEXT_DISPLAY_UPDATE; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(entityId); + writer.writeVarInt(newTextLines.size()); + for (String line : newTextLines) { + writer.writeString(line); + } + writer.writeBoolean(replaceAll); + if (!replaceAll) { + writer.writeVarInt(startLineIndex); + } + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + entityId = reader.readVarInt(); + int lineCount = reader.readVarInt(); + newTextLines = new ArrayList<>(lineCount); + for (int i = 0; i < lineCount; i++) { + newTextLines.add(reader.readString()); + } + replaceAll = reader.readBoolean(); + if (!replaceAll) { + startLineIndex = reader.readVarInt(); + } + } + + @Override + public int getEntityId() { + return entityId; + } + + @Override + public boolean isEntityState() { + return true; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableType.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableType.java new file mode 100644 index 000000000..403b82d8e --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/RecordableType.java @@ -0,0 +1,106 @@ +package net.swofty.type.game.replay.recordable; + +import lombok.Getter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.type.game.replay.recordable.bedwars.RecordableBedDestruction; +import net.swofty.type.game.replay.recordable.bedwars.RecordableGeneratorUpgrade; +import net.swofty.type.game.replay.recordable.bedwars.RecordableKill; +import net.swofty.type.game.replay.recordable.bedwars.RecordableTeamElimination; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Supplier; + +public enum RecordableType { + // Block events (0-19) + BLOCK_CHANGE(0, RecordableBlockChange::new), + BLOCK_BREAK_ANIMATION(1, RecordableBlockBreakAnimation::new), + + // Entity events (20-49), + ENTITY_SPAWN(20, RecordableEntitySpawn::new), + ENTITY_DESPAWN(21, RecordableEntityDespawn::new), + ENTITY_LOCATIONS(22, RecordableEntityLocations::new), + ENTITY_METADATA(24, RecordableEntityMetadata::new), + ENTITY_EQUIPMENT(25, RecordableEntityEquipment::new), + ENTITY_MOUNT(26, RecordableEntityMount::new), + ENTITY_ANIMATION(27, RecordableEntityAnimation::new), + ENTITY_EFFECT(30, RecordableEntityEffect::new), + ENTITY_EFFECT_REMOVE(31, RecordableEntityEffectRemove::new), + + // Player-specific events (50-79) + PLAYER_ARM_SWING(50, RecordablePlayerArmSwing::new), + PLAYER_SNEAK(51, RecordablePlayerSneak::new), + PLAYER_SPRINT(52, RecordablePlayerSprint::new), + PLAYER_CHAT(53, RecordablePlayerChat::new), + PLAYER_DEATH(54, RecordablePlayerDeath::new), + PLAYER_RESPAWN(55, RecordablePlayerRespawn::new), + PLAYER_GAMEMODE(56, RecordablePlayerGamemode::new), + PLAYER_HAND_ITEM(57, RecordablePlayerHandItem::new), + PLAYER_SKIN(58, RecordablePlayerSkin::new), + PLAYER_DISPLAY_NAME(59, RecordablePlayerDisplayName::new), + PLAYER_HEALTH(60, RecordablePlayerHealth::new), + + // World events (80-99) + PARTICLE(80, RecordableParticle::new), + SOUND(81, RecordableSound::new), + EXPLOSION(82, RecordableExplosion::new), + + // Item events (100-109) + DROPPED_ITEM(100, RecordableDroppedItem::new), + ITEM_PICKUP(101, RecordableItemPickup::new), + + // Display events (110-119) + DYNAMIC_TEXT_DISPLAY(110, RecordableDynamicTextDisplay::new), + TEXT_DISPLAY_UPDATE(111, RecordableTextDisplayUpdate::new), + + // BedWars + BEDWARS_BED_DESTRUCTION(120, RecordableBedDestruction::new), + BEDWARS_KILL(121, RecordableKill::new), + BEDWARS_TEAM_ELIMINATION(122, RecordableTeamElimination::new), + BEDWARS_EVENT_CONTINUE(123, RecordableGeneratorUpgrade::new), + + // NPC events (140-149) + NPC_DISPLAY_NAME(140, RecordableNpcDisplayName::new), + NPC_TEXT_LINE(141, RecordableNpcTextLine::new), + + // Composite events (150+) + BATCH(150, RecordableBatch::new) + ; + + private static final Map BY_ID = new HashMap<>(); + + static { + for (RecordableType type : values()) { + BY_ID.put(type.id, type); + } + } + + @Getter + private final int id; + private final Supplier factory; + + RecordableType(int id, Supplier factory) { + this.id = id; + this.factory = factory; + } + + public Recordable create() { + Recordable recordable = factory.get(); + if (recordable == null) { + throw new UnsupportedOperationException("Recordable type " + name() + " has no factory"); + } + return recordable; + } + + public Recordable createAndRead(ReplayDataReader reader) throws IOException { + Recordable recordable = create(); + recordable.read(reader); + return recordable; + } + + public static RecordableType byId(int id) { + return BY_ID.get(id); + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableBedDestruction.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableBedDestruction.java new file mode 100644 index 000000000..4c325f8da --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableBedDestruction.java @@ -0,0 +1,64 @@ +package net.swofty.type.game.replay.recordable.bedwars; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; +import net.swofty.type.game.replay.recordable.AbstractRecordable; +import net.swofty.type.game.replay.recordable.RecordableType; + +import java.io.IOException; +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableBedDestruction extends AbstractRecordable { + private byte teamId; + private int destroyerEntityId; // this is nullable? + private UUID destroyerUuid; + private int bedX; + private int bedY; + private int bedZ; + + public RecordableBedDestruction(byte teamId, int destroyerEntityId, UUID destroyerUuid, int bedX, int bedY, int bedZ) { + this.teamId = teamId; + this.destroyerEntityId = destroyerEntityId; + this.destroyerUuid = destroyerUuid; + this.bedX = bedX; + this.bedY = bedY; + this.bedZ = bedZ; + } + + @Override + public RecordableType getType() { + return RecordableType.BEDWARS_BED_DESTRUCTION; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeByte(teamId); + writer.writeVarInt(destroyerEntityId); + boolean hasDestroyer = destroyerUuid != null; + writer.writeBoolean(hasDestroyer); + if (hasDestroyer) { + writer.writeUUID(destroyerUuid); + } + writer.writeBlockCoords(bedX, bedY, bedZ); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + teamId = (byte) reader.readByte(); + destroyerEntityId = reader.readVarInt(); + if (reader.readBoolean()) { + destroyerUuid = reader.readUUID(); + } + int[] coords = reader.readBlockCoords(); + bedX = coords[0]; + bedY = coords[1]; + bedZ = coords[2]; + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableGeneratorUpgrade.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableGeneratorUpgrade.java new file mode 100644 index 000000000..4adf0a45e --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableGeneratorUpgrade.java @@ -0,0 +1,42 @@ +package net.swofty.type.game.replay.recordable.bedwars; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; +import net.swofty.type.game.replay.recordable.AbstractRecordable; +import net.swofty.type.game.replay.recordable.RecordableType; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableGeneratorUpgrade extends AbstractRecordable { + private byte generatorType; // 0=diamond, 1=emerald + private byte tier; // 1, 2, 3 + + public RecordableGeneratorUpgrade(byte generatorType, byte tier) { + this.generatorType = generatorType; + this.tier = tier; + } + + @Override + public RecordableType getType() { + return RecordableType.BEDWARS_EVENT_CONTINUE; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeByte(generatorType); + writer.writeByte(tier); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + generatorType = (byte) reader.readByte(); + tier = (byte) reader.readByte(); + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableKill.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableKill.java new file mode 100644 index 000000000..43bb0cfe2 --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableKill.java @@ -0,0 +1,69 @@ +package net.swofty.type.game.replay.recordable.bedwars; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; +import net.swofty.type.game.replay.recordable.AbstractRecordable; +import net.swofty.type.game.replay.recordable.RecordableType; + +import java.io.IOException; +import java.util.UUID; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableKill extends AbstractRecordable { + private int victimEntityId; + private UUID victimUuid; + private int killerEntityId; // nullable as -1 + private UUID killerUuid; // nullable + private byte victimTeamId; + private byte deathCause; // 0=generic, 1=generic_player, 2=void, 3=void_player, 4=shot, 5=entity + private byte finalKill; + + public RecordableKill(int victimEntityId, UUID victimUuid, int killerEntityId, UUID killerUuid, byte victimTeamId, byte deathCause, byte finalKill) { + this.victimEntityId = victimEntityId; + this.victimUuid = victimUuid; + this.killerEntityId = killerEntityId; + this.killerUuid = killerUuid; + this.victimTeamId = victimTeamId; + this.deathCause = deathCause; + this.finalKill = finalKill; + } + + @Override + public RecordableType getType() { + return RecordableType.BEDWARS_KILL; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeVarInt(victimEntityId); + writer.writeUUID(victimUuid); + writer.writeVarInt(killerEntityId); + boolean hasKiller = killerUuid != null; + writer.writeBoolean(hasKiller); + if (hasKiller) { + writer.writeUUID(killerUuid); + } + writer.writeByte(victimTeamId); + writer.writeByte(deathCause); + writer.writeByte(finalKill); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + victimEntityId = reader.readVarInt(); + victimUuid = reader.readUUID(); + killerEntityId = reader.readVarInt(); + if (reader.readBoolean()) { + killerUuid = reader.readUUID(); + } + victimTeamId = (byte) reader.readByte(); + deathCause = (byte) reader.readByte(); + finalKill = (byte) reader.readByte(); + } + +} diff --git a/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableTeamElimination.java b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableTeamElimination.java new file mode 100644 index 000000000..12db0c9bc --- /dev/null +++ b/type.game/src/main/java/net/swofty/type/game/replay/recordable/bedwars/RecordableTeamElimination.java @@ -0,0 +1,38 @@ +package net.swofty.type.game.replay.recordable.bedwars; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.replay.protocol.ReplayDataReader; +import net.swofty.commons.replay.protocol.ReplayDataWriter; +import net.swofty.type.game.replay.recordable.AbstractRecordable; +import net.swofty.type.game.replay.recordable.RecordableType; + +import java.io.IOException; + +@Getter +@Setter +@NoArgsConstructor +public class RecordableTeamElimination extends AbstractRecordable { + private byte teamId; + + public RecordableTeamElimination(byte teamId) { + this.teamId = teamId; + } + + @Override + public RecordableType getType() { + return RecordableType.BEDWARS_TEAM_ELIMINATION; + } + + @Override + public void write(ReplayDataWriter writer) throws IOException { + writer.writeByte(teamId); + } + + @Override + public void read(ReplayDataReader reader) throws IOException { + teamId = (byte) reader.readByte(); + } + +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/HypixelGenericLoader.java b/type.generic/src/main/java/net/swofty/type/generic/HypixelGenericLoader.java index ed8446fd9..9c8f48343 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/HypixelGenericLoader.java +++ b/type.generic/src/main/java/net/swofty/type/generic/HypixelGenericLoader.java @@ -29,9 +29,11 @@ import net.swofty.type.generic.command.HypixelCommand; import net.swofty.type.generic.data.GameDataHandlerRegistry; import net.swofty.type.generic.data.HypixelDataHandler; +import net.swofty.type.generic.data.handlers.ArcadeDataHandler; import net.swofty.type.generic.data.handlers.BedWarsDataHandler; import net.swofty.type.generic.data.handlers.MurderMysteryDataHandler; import net.swofty.type.generic.data.handlers.PrototypeLobbyDataHandler; +import net.swofty.type.generic.data.handlers.ReplayDataHandler; import net.swofty.type.generic.data.handlers.SkywarsDataHandler; import net.swofty.type.generic.data.mongodb.AttributeDatabase; import net.swofty.type.generic.data.mongodb.BedWarsStatsDatabase; @@ -55,6 +57,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicReference; @@ -207,6 +210,8 @@ public void initialize(MinecraftServer server) { GameDataHandlerRegistry.register(new PrototypeLobbyDataHandler()); GameDataHandlerRegistry.register(new MurderMysteryDataHandler()); GameDataHandlerRegistry.register(new SkywarsDataHandler()); + GameDataHandlerRegistry.register(new ReplayDataHandler()); + GameDataHandlerRegistry.register(new ArcadeDataHandler()); // Register Block Handlers MinecraftServer.getBlockManager().registerHandler(PlayerHeadBlockHandler.KEY, PlayerHeadBlockHandler::new); @@ -281,6 +286,6 @@ public static Stream loopThroughPackage(String packageName, Class claz return null; } }) - .filter(java.util.Objects::nonNull); + .filter(Objects::nonNull); } } diff --git a/type.generic/src/main/java/net/swofty/type/generic/HypixelTypeLoader.java b/type.generic/src/main/java/net/swofty/type/generic/HypixelTypeLoader.java index 4ef484fe6..ddb4dcb1e 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/HypixelTypeLoader.java +++ b/type.generic/src/main/java/net/swofty/type/generic/HypixelTypeLoader.java @@ -39,7 +39,11 @@ public interface HypixelTypeLoader { List> getTypedProxyHandlers(); - record LoaderValues(Function spawnPosition, boolean announceDeathMessages) {} + record LoaderValues(Function spawnPosition, boolean announceDeathMessages) { + public LoaderValues(Pos spawnPosition, boolean announceDeathMessages) { + this(_ -> spawnPosition, announceDeathMessages); + } + } @Nullable CustomWorlds getMainInstance(); diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCatalog.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCatalog.java new file mode 100644 index 000000000..8513abfaf --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCatalog.java @@ -0,0 +1,62 @@ +package net.swofty.type.generic.collectibles; + +import java.util.*; + +public abstract class CollectibleCatalog { + + private final Map byId = new LinkedHashMap<>(); + private final Map> byCategory = new EnumMap<>(CollectibleCategory.class); + private final Set knownCategories = EnumSet.noneOf(CollectibleCategory.class); + + protected void clear() { + byId.clear(); + byCategory.clear(); + knownCategories.clear(); + } + + protected void registerCategory(CollectibleCategory category) { + knownCategories.add(category); + byCategory.computeIfAbsent(category, ignored -> new ArrayList<>()); + } + + protected void register(CollectibleDefinition definition) { + registerCategory(definition.category()); + byId.put(scopedId(definition.category(), definition.id()), definition); + byId.putIfAbsent(definition.id(), definition); + byCategory.get(definition.category()).add(definition); + } + + protected void sortAll() { + Comparator comparator = Comparator + .comparingInt(CollectibleDefinition::sortIndex) + .thenComparing(CollectibleDefinition::id); + + for (List definitions : byCategory.values()) { + definitions.sort(comparator); + } + } + + public Optional findById(String id) { + return Optional.ofNullable(byId.get(id)); + } + + public Optional findById(CollectibleCategory category, String id) { + return Optional.ofNullable(byId.get(scopedId(category, id))).or(() -> findById(id)); + } + + public List getByCategory(CollectibleCategory category) { + return List.copyOf(byCategory.getOrDefault(category, List.of())); + } + + public Collection getAll() { + return byCategory.values().stream().flatMap(List::stream).toList(); + } + + public Set getKnownCategories() { + return EnumSet.copyOf(knownCategories); + } + + private String scopedId(CollectibleCategory category, String id) { + return category.name() + ":" + id; + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCategory.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCategory.java new file mode 100644 index 000000000..af3362004 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCategory.java @@ -0,0 +1,66 @@ +package net.swofty.type.generic.collectibles; + +import lombok.Getter; + +import java.util.EnumSet; +import java.util.Locale; +import java.util.Optional; +import java.util.Set; + +@Getter +public enum CollectibleCategory { + PROJECTILE_TRAILS("Projectile Trails"), + VICTORY_DANCES("Victory Dances"), + FINAL_KILL_EFFECTS("Final Kill Effects"), + SPRAYS("Sprays"), + ISLAND_TOPPERS("Island Toppers"), + DEATH_CRIES("Death Cries"), + SHOPKEEPER_SKINS("Shopkeeper Skins"), + KILL_MESSAGES("Kill Messages"), + GLYPHS("Glyphs"), + BED_DESTROYS("Bed Destroys"), + WOOD_SKINS("Wood Skins"), + FIGURINES("Figurines"), + PRESTIGE_SCHEMES("Prestige Schemes"), + PRESTIGE_STARS("Prestige Stars"), + PRESTIGE_BRACKETS("Prestige Brackets"); + + private static final EnumSet BEDWARS_CATEGORIES = EnumSet.of( + PROJECTILE_TRAILS, + VICTORY_DANCES, + FINAL_KILL_EFFECTS, + SPRAYS, + ISLAND_TOPPERS, + DEATH_CRIES, + SHOPKEEPER_SKINS, + KILL_MESSAGES, + GLYPHS, + BED_DESTROYS, + WOOD_SKINS, + FIGURINES, + PRESTIGE_SCHEMES, + PRESTIGE_STARS, + PRESTIGE_BRACKETS + ); + + private final String displayName; + + CollectibleCategory(String displayName) { + this.displayName = displayName; + } + + public static Optional fromKey(String key) { + if (key == null || key.isBlank()) { + return Optional.empty(); + } + try { + return Optional.of(CollectibleCategory.valueOf(key.trim().toUpperCase(Locale.ROOT))); + } catch (IllegalArgumentException exception) { + return Optional.empty(); + } + } + + public static Set bedWarsCategories() { + return EnumSet.copyOf(BEDWARS_CATEGORIES); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCurrency.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCurrency.java new file mode 100644 index 000000000..c6eee8bc4 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleCurrency.java @@ -0,0 +1,31 @@ +package net.swofty.type.generic.collectibles; + +import lombok.Getter; + +import java.util.Locale; + +@Getter +public enum CollectibleCurrency { + BEDWARS_TOKENS("Tokens", "§2"), + SKYWARS_COINS("Tokens", "§2"), + MURDER_MYSTERY_COINS("Tokens", "§2"); + + private final String displayName; + private final String color; + + CollectibleCurrency(String displayName, String color) { + this.displayName = displayName; + this.color = color; + } + + public static CollectibleCurrency fromString(String value, CollectibleCurrency fallback) { + if (value == null || value.isBlank()) { + return fallback; + } + try { + return CollectibleCurrency.valueOf(value.trim().toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException exception) { + return fallback; + } + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleDefinition.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleDefinition.java new file mode 100644 index 000000000..f6b3f0e54 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleDefinition.java @@ -0,0 +1,36 @@ +package net.swofty.type.generic.collectibles; + +import net.minestom.server.item.Material; + +import java.util.List; +import java.util.Map; + +public record CollectibleDefinition( + String id, + CollectibleGamemode gamemode, + CollectibleCategory category, + String name, + Material iconMaterial, + String iconTexture, + List description, + String categoryDescriptionKey, + Map customData, + CollectibleRarity rarity, + int sortIndex, + String selectionValue, + CollectibleUnlockRequirement unlockRequirement +) { + public CollectibleDefinition { + description = description == null ? List.of() : List.copyOf(description); + customData = customData == null ? Map.of() : Map.copyOf(customData); + rarity = rarity == null ? CollectibleRarity.COMMON : rarity; + unlockRequirement = unlockRequirement == null ? CollectibleUnlockRequirement.free() : unlockRequirement; + } + + public String effectiveSelectionValue() { + if (selectionValue == null || selectionValue.isBlank()) { + return id; + } + return selectionValue; + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleDescriptionService.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleDescriptionService.java new file mode 100644 index 000000000..41a6422ce --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleDescriptionService.java @@ -0,0 +1,50 @@ +package net.swofty.type.generic.collectibles; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.minimessage.translation.Argument; +import net.swofty.type.generic.i18n.I18n; + +import java.util.Arrays; +import java.util.List; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class CollectibleDescriptionService { + + public static List resolveLore(CollectibleDefinition definition) { + String categoryDescriptionKey = definition.categoryDescriptionKey(); + if (categoryDescriptionKey != null && !categoryDescriptionKey.isBlank()) { + Component nameComponent = Component.text(definition.name()); + try { + Component[] lines = I18n.iterable(categoryDescriptionKey, Argument.component("name", nameComponent)); + return Arrays.stream(lines) + .map(line -> line.colorIfAbsent(NamedTextColor.GRAY)) + .toList(); + } catch (IllegalStateException exception) { + if (!isMissingIterableKey(exception)) { + throw exception; + } + + return List.of( + I18n.t(categoryDescriptionKey, Argument.component("name", nameComponent)) + .colorIfAbsent(NamedTextColor.GRAY) + ); + } + } + + if (definition.description().isEmpty()) { + return List.of(); + } + + return definition.description().stream() + .map(line -> (Component) Component.text(line, NamedTextColor.GRAY)) + .toList(); + } + + private static boolean isMissingIterableKey(IllegalStateException exception) { + String message = exception.getMessage(); + return message != null && message.startsWith("Missing dialogue translation key in en_US:"); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleEvaluator.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleEvaluator.java new file mode 100644 index 000000000..25871b898 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleEvaluator.java @@ -0,0 +1,108 @@ +package net.swofty.type.generic.collectibles; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.swofty.commons.bedwars.BedwarsLevelUtil; +import net.swofty.type.generic.data.datapoints.DatapointLeaderboardLong; +import net.swofty.type.generic.data.handlers.BedWarsDataHandler; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.generic.user.categories.Rank; + +import java.text.NumberFormat; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class CollectibleEvaluator { + + private static final DateTimeFormatter WINDOW_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneOffset.UTC); + private static final NumberFormat NUMBER_FORMAT = NumberFormat.getIntegerInstance(Locale.US); + + public static CollectibleSelectionCheck checkSelectable( + HypixelPlayer player, + CollectibleDefinition definition, + boolean manuallyUnlocked + ) { + CollectibleUnlockRequirement requirement = definition.unlockRequirement(); + CollectibleEvent event = requirement.event(); + if (event != null && !event.isAvailableNow()) { + return CollectibleSelectionCheck.blocked(unavailableReason(requirement, event)); + } + + Rank requiredRank = requirement.requiredRank(); + if (requiredRank != null && !player.getRank().isEqualOrHigherThan(requiredRank)) { + return CollectibleSelectionCheck.blocked("§cRequires " + requiredRank.getPrefix() + "§c."); + } + + return switch (requirement.method()) { + case FREE, RANK -> CollectibleSelectionCheck.allowed(); + case MANUAL, CURRENCY -> manuallyUnlocked + ? CollectibleSelectionCheck.allowed() + : CollectibleSelectionCheck.blocked(defaultReason(requirement, "Locked.")); + case CUSTOM -> { + if (manuallyUnlocked) { + yield CollectibleSelectionCheck.allowed(); + } + String resolverKey = requirement.customResolverKey(); + boolean unlocked = CollectibleUnlockResolverRegistry.get(resolverKey) + .map(resolver -> resolver.isUnlocked(player, definition)) + .orElse(false); + if (unlocked) { + yield CollectibleSelectionCheck.allowed(); + } + yield CollectibleSelectionCheck.blocked(defaultReason(requirement, "Locked.")); + } + case BEDWARS_LEVEL -> { + int requiredLevel = requirement.cost() == null ? 0 : requirement.cost().intValue(); + if (bedWarsLevel(player) >= requiredLevel) { + yield CollectibleSelectionCheck.allowed(); + } + yield CollectibleSelectionCheck.blocked(defaultReason(requirement, "§c§l!! §r§cYou must be level " + + NUMBER_FORMAT.format(requiredLevel) + " to use this\n§cprestige!")); + } + }; + } + + private static int bedWarsLevel(HypixelPlayer player) { + BedWarsDataHandler handler = BedWarsDataHandler.getUser(player); + if (handler == null) { + return 0; + } + long experience = handler.get(BedWarsDataHandler.Data.EXPERIENCE, DatapointLeaderboardLong.class).getValue(); + return BedwarsLevelUtil.calculateLevel(experience); + } + + private static String defaultReason(CollectibleUnlockRequirement requirement, String fallback) { + if (requirement.customDisplayText() != null && !requirement.customDisplayText().isBlank()) { + return "§c" + requirement.customDisplayText(); + } + if (requirement.method() == CollectibleUnlockMethod.CURRENCY + && requirement.cost() != null + && requirement.cost() > 0) { + return "§7Cost: " + requirement.currency().getColor() + NUMBER_FORMAT.format(requirement.cost()) + " " + requirement.currency().getDisplayName() + "§7."; + } + return fallback; + } + + private static String unavailableReason(CollectibleUnlockRequirement requirement, CollectibleEvent event) { + String customText = requirement.customDisplayText(); + if (event != null) { + return "§cAvailable during the " + event.displayName() + " Event."; + } + + if (customText != null && !customText.isBlank()) { + return "§c" + customText; + } + + return "§cUnavailable right now."; + } + + private static String formatTimestamp(Long timestampMs) { + if (timestampMs == null) { + return null; + } + return WINDOW_FORMATTER.format(Instant.ofEpochMilli(timestampMs)); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleEvent.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleEvent.java new file mode 100644 index 000000000..f7ebe4e9d --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleEvent.java @@ -0,0 +1,59 @@ +package net.swofty.type.generic.collectibles; + +import java.time.LocalDate; +import java.util.Locale; +import java.util.Optional; + +public enum CollectibleEvent { + EASTER("Easter", + LocalDate.of(2026, 1, 1), + LocalDate.of(2026, 4, 12) + ), + HOLIDAY("Holiday", + LocalDate.of(2025, 12, 31), + LocalDate.of(2026, 2, 1) + ), + HALLOWEEN("Halloween", + LocalDate.of(2026, 10, 31), + LocalDate.of(2026, 11, 10) + ); + + private final String displayName; + private final LocalDate start; + private final LocalDate end; + + CollectibleEvent(String displayName, LocalDate startDate, LocalDate endDate) { + this.displayName = displayName; + this.start = startDate; + this.end = endDate; + } + + public String displayName() { + return displayName; + } + + public boolean isAvailableNow() { + return isAvailableAt(LocalDate.now()); + } + + public boolean isAvailableAt(LocalDate date) { + if (date == null || start == null || end == null) { + return false; + } + + // inclusive range: start <= date <= end + return (!date.isBefore(start)) && (!date.isAfter(end)); + } + + public static Optional fromString(String value) { + if (value == null || value.isBlank()) { + return Optional.empty(); + } + + try { + return Optional.of(CollectibleEvent.valueOf(value.trim().toUpperCase(Locale.ROOT))); + } catch (IllegalArgumentException exception) { + return Optional.empty(); + } + } +} \ No newline at end of file diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleGamemode.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleGamemode.java new file mode 100644 index 000000000..7d6c917e5 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleGamemode.java @@ -0,0 +1,18 @@ +package net.swofty.type.generic.collectibles; + +public enum CollectibleGamemode { + BEDWARS("BedWars"), + SKYWARS("SkyWars"), + MURDER_MYSTERY("Murder Mystery"), + PROTOTYPE("Prototype"); + + private final String displayName; + + CollectibleGamemode(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleRarity.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleRarity.java new file mode 100644 index 000000000..6b939d502 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleRarity.java @@ -0,0 +1,39 @@ +package net.swofty.type.generic.collectibles; + +import lombok.Getter; + +import java.util.Locale; + +@Getter +public enum CollectibleRarity { + COMMON("COMMON", "§a", 1), + RARE("RARE", "§9", 2), + EPIC("EPIC", "§5", 3), + LEGENDARY("LEGENDARY", "§6", 4), + MYTHIC("MYTHIC", "§d", 5); + + private final String displayName; + private final String colorCode; + private final int weight; + + CollectibleRarity(String displayName, String colorCode, int weight) { + this.displayName = displayName; + this.colorCode = colorCode; + this.weight = weight; + } + + public String formattedName() { + return colorCode + displayName; + } + + public static CollectibleRarity fromString(String value, CollectibleRarity fallback) { + if (value == null || value.isBlank()) { + return fallback; + } + try { + return CollectibleRarity.valueOf(value.trim().toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException exception) { + return fallback; + } + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleSelectionCheck.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleSelectionCheck.java new file mode 100644 index 000000000..35e09b5f2 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleSelectionCheck.java @@ -0,0 +1,12 @@ +package net.swofty.type.generic.collectibles; + +public record CollectibleSelectionCheck(boolean selectable, String reason) { + + public static CollectibleSelectionCheck allowed() { + return new CollectibleSelectionCheck(true, null); + } + + public static CollectibleSelectionCheck blocked(String reason) { + return new CollectibleSelectionCheck(false, reason); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockMethod.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockMethod.java new file mode 100644 index 000000000..b9f0a5303 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockMethod.java @@ -0,0 +1,23 @@ +package net.swofty.type.generic.collectibles; + +import java.util.Locale; + +public enum CollectibleUnlockMethod { + FREE, + RANK, + MANUAL, + CURRENCY, + CUSTOM, + BEDWARS_LEVEL; + + public static CollectibleUnlockMethod fromString(String value, CollectibleUnlockMethod fallback) { + if (value == null || value.isBlank()) { + return fallback; + } + try { + return CollectibleUnlockMethod.valueOf(value.trim().toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException exception) { + return fallback; + } + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockRequirement.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockRequirement.java new file mode 100644 index 000000000..3fe2dc566 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockRequirement.java @@ -0,0 +1,35 @@ +package net.swofty.type.generic.collectibles; + +import net.swofty.type.generic.user.categories.Rank; + +public record CollectibleUnlockRequirement( + CollectibleUnlockMethod method, + Rank requiredRank, + CollectibleCurrency currency, + Long cost, + String customResolverKey, + String customDisplayText, + CollectibleEvent event +) { + public CollectibleUnlockRequirement { + if (method == null) { + method = CollectibleUnlockMethod.FREE; + } + if (currency == null) { + currency = CollectibleCurrency.BEDWARS_TOKENS; + } + } + + public static CollectibleUnlockRequirement free() { + return new CollectibleUnlockRequirement( + CollectibleUnlockMethod.FREE, + null, + CollectibleCurrency.BEDWARS_TOKENS, + null, + null, + null, + null + ); + } + +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockResolver.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockResolver.java new file mode 100644 index 000000000..f6460e063 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockResolver.java @@ -0,0 +1,8 @@ +package net.swofty.type.generic.collectibles; + +import net.swofty.type.generic.user.HypixelPlayer; + +@FunctionalInterface +public interface CollectibleUnlockResolver { + boolean isUnlocked(HypixelPlayer player, CollectibleDefinition definition); +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockResolverRegistry.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockResolverRegistry.java new file mode 100644 index 000000000..690c4722c --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/CollectibleUnlockResolverRegistry.java @@ -0,0 +1,31 @@ +package net.swofty.type.generic.collectibles; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public final class CollectibleUnlockResolverRegistry { + + private static final Map RESOLVERS = new ConcurrentHashMap<>(); + + private CollectibleUnlockResolverRegistry() { + } + + public static void register(String key, CollectibleUnlockResolver resolver) { + if (key == null || key.isBlank() || resolver == null) { + return; + } + RESOLVERS.put(key.trim().toLowerCase(), resolver); + } + + public static Optional get(String key) { + if (key == null || key.isBlank()) { + return Optional.empty(); + } + return Optional.ofNullable(RESOLVERS.get(key.trim().toLowerCase())); + } + + public static void clear() { + RESOLVERS.clear(); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsCollectibleCatalog.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsCollectibleCatalog.java new file mode 100644 index 000000000..140326a1b --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsCollectibleCatalog.java @@ -0,0 +1,376 @@ +package net.swofty.type.generic.collectibles.bedwars; + +import lombok.Getter; +import net.minestom.server.item.Material; +import net.swofty.commons.YamlFileUtils; +import net.swofty.type.generic.collectibles.CollectibleCatalog; +import net.swofty.type.generic.collectibles.CollectibleCategory; +import net.swofty.type.generic.collectibles.CollectibleCurrency; +import net.swofty.type.generic.collectibles.CollectibleDefinition; +import net.swofty.type.generic.collectibles.CollectibleEvent; +import net.swofty.type.generic.collectibles.CollectibleGamemode; +import net.swofty.type.generic.collectibles.CollectibleRarity; +import net.swofty.type.generic.collectibles.CollectibleUnlockMethod; +import net.swofty.type.generic.collectibles.CollectibleUnlockRequirement; +import net.swofty.type.generic.collectibles.bedwars.prestige.BedWarsPrestigeDefinitions; +import net.swofty.type.generic.collectibles.bedwars.prestige.PrestigeCollectibleFactory; +import net.swofty.type.generic.user.categories.Rank; +import org.tinylog.Logger; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public final class BedWarsCollectibleCatalog extends CollectibleCatalog { + + private static final File CATALOG_FILE = new File("./configuration/bedwars/cosmetics.yml"); + private static final BedWarsCollectibleCatalog INSTANCE = new BedWarsCollectibleCatalog(); + + @Getter + private static boolean initialized = false; + + private final Map categorySettings = new EnumMap<>(CollectibleCategory.class); + + private static final String DEFAULT_WOOD_ID = "oak_plank"; + private static final String DEFAULT_SHOPKEEPER_ID = "blacksmith"; + + private BedWarsCollectibleCatalog() { + } + + public static synchronized void initialize() { + if (initialized) { + return; + } + INSTANCE.loadInternal(); + initialized = true; + } + + public static synchronized void reload() { + INSTANCE.loadInternal(); + initialized = true; + } + + public static List getCategoryItems(CollectibleCategory category) { + initialize(); + return INSTANCE.getByCategory(category); + } + + public static Optional findItemById(String id) { + initialize(); + return INSTANCE.findById(id); + } + + public static Set knownCategories() { + initialize(); + return INSTANCE.getKnownCategories(); + } + + public static boolean categorySupportsFavorites(CollectibleCategory category) { + initialize(); + return INSTANCE.categorySettings.getOrDefault(category, CategorySettings.DEFAULT).favoriteable(); + } + + public static boolean categorySupportsRandom(CollectibleCategory category) { + initialize(); + return INSTANCE.categorySettings.getOrDefault(category, CategorySettings.DEFAULT).random(); + } + + public static String pinnedDefaultId(CollectibleCategory category) { + initialize(); + return INSTANCE.categorySettings.getOrDefault(category, CategorySettings.DEFAULT).defaultSelectionId(); + } + + public static String categoryDescriptionKey(CollectibleCategory category) { + initialize(); + return INSTANCE.categorySettings.getOrDefault(category, CategorySettings.DEFAULT).descriptionKey(); + } + + private void loadInternal() { + clear(); + categorySettings.clear(); + for (CollectibleCategory category : CollectibleCategory.bedWarsCategories()) { + registerCategory(category); + categorySettings.put(category, CategorySettings.DEFAULT); + } + categorySettings.put(CollectibleCategory.PRESTIGE_SCHEMES, new CategorySettings( + true, true, BedWarsPrestigeDefinitions.DEFAULT_SCHEME_ID, null)); + categorySettings.put(CollectibleCategory.PRESTIGE_STARS, new CategorySettings( + true, true, BedWarsPrestigeDefinitions.DEFAULT_STAR_ID, null)); + categorySettings.put(CollectibleCategory.PRESTIGE_BRACKETS, new CategorySettings( + true, true, BedWarsPrestigeDefinitions.DEFAULT_BRACKET_ID, null)); + + if (!CATALOG_FILE.exists()) { + Logger.warn("BedWars collectibles configuration not found: {}", CATALOG_FILE.getAbsolutePath()); + sortAll(); + return; + } + + try { + Map yaml = YamlFileUtils.loadYaml(CATALOG_FILE); + if (yaml != null) { + parseCategories(yaml.get("categories")); + } + } catch (IOException exception) { + Logger.error(exception, "Failed loading BedWars collectibles from {}", CATALOG_FILE.getAbsolutePath()); + } catch (Exception exception) { + Logger.error(exception, "Failed parsing BedWars collectibles from {}", CATALOG_FILE.getAbsolutePath()); + } + + registerPrestigeDefinitions(); + sortAll(); + Logger.info("Loaded {} BedWars collectibles from {}", getAll().size(), CATALOG_FILE.getAbsolutePath()); + } + + private void registerPrestigeDefinitions() { + for (CollectibleDefinition definition : PrestigeCollectibleFactory.definitions()) { + try { + register(definition); + } catch (IllegalArgumentException exception) { + Logger.warn(exception, "Skipping duplicate BedWars prestige collectible '{}'", definition.id()); + } + } + } + + private void parseCategories(Object categoriesRaw) { + if (!(categoriesRaw instanceof Map categories)) { + return; + } + + for (Map.Entry categoryEntry : categories.entrySet()) { + String categoryKey = String.valueOf(categoryEntry.getKey()); + Optional parsedCategory = CollectibleCategory.fromKey(categoryKey); + if (parsedCategory.isEmpty()) { + Logger.warn("Unknown BedWars collectible category '{}' in {}", categoryKey, CATALOG_FILE.getName()); + continue; + } + + CollectibleCategory category = parsedCategory.get(); + registerCategory(category); + + if (!(categoryEntry.getValue() instanceof Map categoryData)) { + continue; + } + + categorySettings.put(category, parseCategorySettings(category, categoryData)); + + Object itemsRaw = categoryData.get("items"); + if (!(itemsRaw instanceof List items)) { + continue; + } + + int autoSortIndex = 0; + for (Object itemRaw : items) { + if (!(itemRaw instanceof Map itemDataRaw)) { + continue; + } + CollectibleDefinition definition = parseDefinition(category, itemDataRaw, autoSortIndex++); + if (definition == null) { + continue; + } + try { + register(definition); + } catch (IllegalArgumentException exception) { + Logger.warn(exception, "Skipping duplicate BedWars collectible '{}'", definition.id()); + } + } + } + } + + private CollectibleDefinition parseDefinition(CollectibleCategory category, Map rawData, int autoSortIndex) { + String id = stringValue(rawData.get("id")); + if (id == null || id.isBlank()) { + return null; + } + + String name = stringValue(rawData.get("name")); + if (name == null || name.isBlank()) { + name = id; + } + + Material iconMaterial = parseMaterial(stringValue(rawData.get("iconMaterial"))); + String iconTexture = stringValue(rawData.get("iconTexture")); + + List description = stringList(rawData.get("description")); + String categoryDescriptionKey = categorySettings.getOrDefault(category, CategorySettings.DEFAULT).descriptionKey(); + Map customData = stringMap(rawData.get("custom")); + CollectibleRarity rarity = CollectibleRarity.fromString(stringValue(rawData.get("rarity")), CollectibleRarity.COMMON); + int sortIndex = intValue(rawData.get("sortIndex"), autoSortIndex); + String selectionValue = stringValue(rawData.get("selectionValue")); + + CollectibleUnlockRequirement unlockRequirement = parseUnlockRequirement(rawData.get("unlock")); + + return new CollectibleDefinition( + id, + CollectibleGamemode.BEDWARS, + category, + name, + iconMaterial, + iconTexture, + description, + categoryDescriptionKey, + customData, + rarity, + sortIndex, + selectionValue, + unlockRequirement + ); + } + + private CategorySettings parseCategorySettings(CollectibleCategory category, Map categoryData) { + boolean favoriteable = booleanValue(categoryData.get("favoriteable"), false); + boolean random = booleanValue(categoryData.get("random"), false); + String defaultSelectionId = stringValue(categoryData.get("defaultSelectionId")); + String descriptionKey = stringValue(categoryData.get("descriptionKey")); + + if (defaultSelectionId == null) { + if (category == CollectibleCategory.WOOD_SKINS) { + defaultSelectionId = DEFAULT_WOOD_ID; + } else if (category == CollectibleCategory.SHOPKEEPER_SKINS) { + defaultSelectionId = DEFAULT_SHOPKEEPER_ID; + } + } + + return new CategorySettings(favoriteable, random, defaultSelectionId, descriptionKey); + } + + private CollectibleUnlockRequirement parseUnlockRequirement(Object raw) { + if (!(raw instanceof Map unlockMap)) { + return CollectibleUnlockRequirement.free(); + } + + CollectibleUnlockMethod method = CollectibleUnlockMethod.fromString( + stringValue(unlockMap.get("method")), + CollectibleUnlockMethod.FREE + ); + Rank requiredRank = parseRank(stringValue(unlockMap.get("requiredRank"))); + CollectibleCurrency currency = CollectibleCurrency.fromString( + stringValue(unlockMap.get("currency")), + CollectibleCurrency.BEDWARS_TOKENS + ); + Long cost = longValue(unlockMap.get("cost")); + String customResolverKey = stringValue(unlockMap.get("customResolverKey")); + String customDisplayText = stringValue(unlockMap.get("customDisplayText")); + CollectibleEvent event = CollectibleEvent.fromString(stringValue(unlockMap.get("event"))).orElse(null); + + return new CollectibleUnlockRequirement( + method, + requiredRank, + currency, + cost, + customResolverKey, + customDisplayText, + event + ); + } + + private Rank parseRank(String value) { + if (value == null || value.isBlank()) { + return null; + } + try { + return Rank.valueOf(value.trim().toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException exception) { + return null; + } + } + + public static Material parseMaterial(String rawMaterial) { + if (rawMaterial == null || rawMaterial.isBlank()) { + return null; + } + + String normalized = rawMaterial.trim().toLowerCase(Locale.ROOT); + Material material = Material.fromKey(normalized); + if (material != null) { + return material; + } + + if (!normalized.contains(":")) { + material = Material.fromKey("minecraft:" + normalized); + if (material != null) { + return material; + } + } + + Logger.warn("Unknown material '{}' in {}", rawMaterial, CATALOG_FILE.getName()); + return null; + } + + private String stringValue(Object value) { + if (value == null) { + return null; + } + String string = String.valueOf(value); + return string.isBlank() ? null : string; + } + + private List stringList(Object value) { + if (!(value instanceof List list)) { + return List.of(); + } + + List values = new ArrayList<>(); + for (Object entry : list) { + if (entry == null) { + continue; + } + values.add(String.valueOf(entry)); + } + return values; + } + + private Map stringMap(Object value) { + if (!(value instanceof Map map) || map.isEmpty()) { + return Map.of(); + } + + Map values = new HashMap<>(); + for (Map.Entry entry : map.entrySet()) { + if (entry.getKey() == null) { + continue; + } + + String key = String.valueOf(entry.getKey()); + if (key.isBlank()) { + continue; + } + + Object rawValue = entry.getValue(); + values.put(key, rawValue == null ? "" : String.valueOf(rawValue)); + } + return values; + } + + private int intValue(Object value, int fallback) { + if (!(value instanceof Number number)) { + return fallback; + } + return number.intValue(); + } + + private Long longValue(Object value) { + if (value instanceof Number number) { + return number.longValue(); + } + return null; + } + + private boolean booleanValue(Object value, boolean fallback) { + if (value instanceof Boolean bool) { + return bool; + } + return fallback; + } + + private record CategorySettings(boolean favoriteable, boolean random, String defaultSelectionId, + String descriptionKey) { + private static final CategorySettings DEFAULT = new CategorySettings(false, false, null, null); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsCollectibleStateService.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsCollectibleStateService.java new file mode 100644 index 000000000..6b8600796 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsCollectibleStateService.java @@ -0,0 +1,305 @@ +package net.swofty.type.generic.collectibles.bedwars; + +import net.swofty.type.generic.collectibles.CollectibleCategory; +import net.swofty.type.generic.collectibles.CollectibleCurrency; +import net.swofty.type.generic.collectibles.CollectibleDefinition; +import net.swofty.type.generic.collectibles.CollectibleEvaluator; +import net.swofty.type.generic.collectibles.CollectibleSelectionCheck; +import net.swofty.type.generic.collectibles.CollectibleUnlockMethod; +import net.swofty.type.generic.data.datapoints.DatapointCollectibles; +import net.swofty.type.generic.data.datapoints.DatapointLeaderboardLong; +import net.swofty.type.generic.data.handlers.BedWarsDataHandler; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ThreadLocalRandom; + +public final class BedWarsCollectibleStateService { + + public static final String RANDOM_SELECTION_ID = "random"; + public static final String RANDOM_FAVORITE_SELECTION_ID = "random_favorite"; + + private BedWarsCollectibleStateService() { + } + + public static SelectionResult select(HypixelPlayer player, CollectibleDefinition definition) { + DatapointCollectibles.CollectiblesState state = state(player); + CollectibleSelectionCheck check = checkSelectable(player, state, definition); + if (!check.selectable()) { + String reason = check.reason() != null ? check.reason() : "Locked."; + return new SelectionResult(false, "§c" + reason); + } + + state.setSelected(definition.category(), definition.id()); + persist(player, state); + return new SelectionResult(true, "§aSelected " + definition.name() + "§a."); + } + + public static SelectionResult selectSpecial(HypixelPlayer player, CollectibleCategory category, String selectionId) { + if (!BedWarsCollectibleCatalog.categorySupportsRandom(category)) { + return new SelectionResult(false, "§cRandom mode is not supported for this category."); + } + + if (!RANDOM_SELECTION_ID.equals(selectionId) && !RANDOM_FAVORITE_SELECTION_ID.equals(selectionId)) { + return new SelectionResult(false, "§cInvalid random selection mode."); + } + + DatapointCollectibles.CollectiblesState state = state(player); + state.setSelected(category, selectionId); + persist(player, state); + + if (RANDOM_FAVORITE_SELECTION_ID.equals(selectionId)) { + return new SelectionResult(true, "§aSelected Random Favorite mode."); + } + return new SelectionResult(true, "§aSelected Random mode."); + } + + public static SelectionResult purchaseAndSelect(HypixelPlayer player, CollectibleDefinition definition) { + DatapointCollectibles.CollectiblesState state = state(player); + PurchaseCheck purchaseCheck = checkPurchase(player, state, definition); + if (!purchaseCheck.purchasable()) { + return new SelectionResult(false, "§c" + purchaseCheck.reason()); + } + + BedWarsDataHandler dataHandler = BedWarsDataHandler.getUser(player); + DatapointLeaderboardLong tokensDp = dataHandler.get(BedWarsDataHandler.Data.TOKENS, DatapointLeaderboardLong.class); + long currentTokens = tokensDp.getValue(); + long cost = purchaseCheck.cost(); + if (currentTokens < cost) { + return new SelectionResult(false, "§cYou do not have enough BedWars Tokens."); + } + + tokensDp.setValue(currentTokens - cost); + state.unlock(definition.category(), definition.id()); + state.setSelected(definition.category(), definition.id()); + persist(player, state); + return new SelectionResult(true, "§6You purchased §a" + definition.name() + "§6!"); + } + + public static PurchaseCheck checkPurchase(HypixelPlayer player, CollectibleDefinition definition) { + return checkPurchase(player, state(player), definition); + } + + public static boolean isRandomModeSelected(HypixelPlayer player, CollectibleCategory category, String selectionId) { + return selectionId.equals(state(player).getSelected(category)); + } + + public static String getSelectedId(HypixelPlayer player, CollectibleCategory category) { + return state(player).getSelected(category); + } + + public static Optional resolveSelected(HypixelPlayer player, CollectibleCategory category) { + return reconcileSelected(player, category); + } + + public static CollectibleSelectionCheck checkSelectable(HypixelPlayer player, CollectibleDefinition definition) { + return checkSelectable(player, state(player), definition); + } + + public static Optional reconcileSelected(HypixelPlayer player, CollectibleCategory category) { + List definitions = BedWarsCollectibleCatalog.getCategoryItems(category); + if (definitions.isEmpty()) { + return Optional.empty(); + } + + DatapointCollectibles.CollectiblesState state = state(player); + String selectedId = state.getSelected(category); + + if ((RANDOM_SELECTION_ID.equals(selectedId) || RANDOM_FAVORITE_SELECTION_ID.equals(selectedId)) + && BedWarsCollectibleCatalog.categorySupportsRandom(category)) { + return resolveRandomSelection(player, state, category, definitions, selectedId); + } + + CollectibleDefinition selectedDefinition = null; + if (selectedId != null && !selectedId.isBlank()) { + for (CollectibleDefinition definition : definitions) { + if (definition.id().equals(selectedId)) { + selectedDefinition = definition; + break; + } + } + } + + if (selectedDefinition != null && checkSelectable(player, state, selectedDefinition).selectable()) { + return Optional.of(selectedDefinition); + } + + Optional fallback = nextSelectable(player, state, category, definitions); + if (fallback.isPresent()) { + state.setSelected(category, fallback.get().id()); + persist(player, state); + return fallback; + } + + CollectibleDefinition first = definitions.get(0); + state.setSelected(category, first.id()); + persist(player, state); + return Optional.of(first); + } + + public static boolean isSelected(HypixelPlayer player, CollectibleCategory category, String collectibleId) { + return collectibleId.equals(state(player).getSelected(category)); + } + + public static boolean isFavorite(HypixelPlayer player, String collectibleId) { + return state(player).isFavorite(collectibleId); + } + + public static boolean toggleFavorite(HypixelPlayer player, String collectibleId) { + Optional definition = BedWarsCollectibleCatalog.findItemById(collectibleId); + if (definition.isEmpty() || !BedWarsCollectibleCatalog.categorySupportsFavorites(definition.get().category())) { + return false; + } + + DatapointCollectibles.CollectiblesState state = state(player); + boolean favorite = state.toggleFavorite(collectibleId); + persist(player, state); + return favorite; + } + + public static void unlock(HypixelPlayer player, CollectibleCategory category, String collectibleId) { + DatapointCollectibles.CollectiblesState state = state(player); + state.unlock(category, collectibleId); + persist(player, state); + } + + private static Optional resolveRandomSelection( + HypixelPlayer player, + DatapointCollectibles.CollectiblesState state, + CollectibleCategory category, + List definitions, + String selectedId + ) { + List selectable = definitions.stream() + .filter(definition -> checkSelectable(player, state, definition).selectable()) + .toList(); + + if (selectable.isEmpty()) { + return Optional.empty(); + } + + if (RANDOM_FAVORITE_SELECTION_ID.equals(selectedId)) { + List favorites = selectable.stream() + .filter(definition -> state.isFavorite(definition.id())) + .toList(); + + if (!favorites.isEmpty()) { + return Optional.of(favorites.get(ThreadLocalRandom.current().nextInt(favorites.size()))); + } + return Optional.of(selectable.get(ThreadLocalRandom.current().nextInt(selectable.size()))); + } + + if (RANDOM_SELECTION_ID.equals(selectedId)) { + return Optional.of(selectable.get(ThreadLocalRandom.current().nextInt(selectable.size()))); + } + + return Optional.empty(); + } + + private static Optional nextSelectable( + HypixelPlayer player, + DatapointCollectibles.CollectiblesState state, + CollectibleCategory category, + List definitions + ) { + String pinnedDefault = BedWarsCollectibleCatalog.pinnedDefaultId(category); + if (pinnedDefault != null && !pinnedDefault.isBlank()) { + for (CollectibleDefinition definition : definitions) { + if (definition.id().equals(pinnedDefault) && checkSelectable(player, state, definition).selectable()) { + return Optional.of(definition); + } + } + } + + for (CollectibleDefinition candidate : definitions) { + if (checkSelectable(player, state, candidate).selectable()) { + return Optional.of(candidate); + } + } + + return Optional.empty(); + } + + private static CollectibleSelectionCheck checkSelectable( + HypixelPlayer player, + DatapointCollectibles.CollectiblesState state, + CollectibleDefinition definition + ) { + boolean manuallyUnlocked = state.isManuallyUnlocked(definition.category(), definition.id()); + return CollectibleEvaluator.checkSelectable(player, definition, manuallyUnlocked); + } + + private static PurchaseCheck checkPurchase( + HypixelPlayer player, + DatapointCollectibles.CollectiblesState state, + CollectibleDefinition definition + ) { + if (state.isManuallyUnlocked(definition.category(), definition.id())) { + return new PurchaseCheck(false, 0L, null, "This collectible is already unlocked."); + } + + if (definition.unlockRequirement().method() != CollectibleUnlockMethod.CURRENCY) { + return new PurchaseCheck(false, 0L, null, "This collectible cannot be purchased."); + } + + CollectibleCurrency currency = definition.unlockRequirement().currency(); + if (currency != CollectibleCurrency.BEDWARS_TOKENS) { + return new PurchaseCheck(false, 0L, currency, "This collectible cannot be purchased with BedWars Tokens."); + } + + Long configuredCost = definition.unlockRequirement().cost(); + long cost = configuredCost == null ? 0L : configuredCost; + if (cost <= 0) { + return new PurchaseCheck(false, 0L, currency, "This collectible has invalid pricing data."); + } + + CollectibleSelectionCheck selectableCheck = checkSelectable(player, state, definition); + if (selectableCheck.selectable()) { + return new PurchaseCheck(false, cost, currency, "This collectible is already selectable."); + } + + String reason = selectableCheck.reason() == null ? "This collectible is currently unavailable." : selectableCheck.reason(); + if (!isCostReason(reason)) { + return new PurchaseCheck(false, cost, currency, reason); + } + + BedWarsDataHandler dataHandler = BedWarsDataHandler.getUser(player); + DatapointLeaderboardLong tokensDp = dataHandler.get(BedWarsDataHandler.Data.TOKENS, DatapointLeaderboardLong.class); + long currentTokens = tokensDp.getValue(); + if (currentTokens < cost) { + return new PurchaseCheck(false, cost, currency, "You do not have enough BedWars Tokens."); + } + + return new PurchaseCheck(true, cost, currency, null); + } + + private static DatapointCollectibles.CollectiblesState state(HypixelPlayer player) { + BedWarsCollectibleCatalog.initialize(); + DatapointCollectibles.CollectiblesState state = datapoint(player).getValue(); + state.ensureCategoryKeys(BedWarsCollectibleCatalog.knownCategories()); + return state; + } + + private static boolean isCostReason(String reason) { + return reason != null && reason.contains("Cost:"); + } + + private static DatapointCollectibles datapoint(HypixelPlayer player) { + BedWarsDataHandler dataHandler = BedWarsDataHandler.getUser(player); + if (dataHandler == null) { + throw new IllegalStateException("BedWars data handler is not loaded for player " + player.getUuid()); + } + return dataHandler.get(BedWarsDataHandler.Data.COLLECTIBLES, DatapointCollectibles.class); + } + + private static void persist(HypixelPlayer player, DatapointCollectibles.CollectiblesState state) { + datapoint(player).setValue(state.copy()); + } + + public record SelectionResult(boolean success, String message) { + } + + public record PurchaseCheck(boolean purchasable, long cost, CollectibleCurrency currency, String reason) { + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsShopkeeperAppearanceService.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsShopkeeperAppearanceService.java new file mode 100644 index 000000000..105a88646 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsShopkeeperAppearanceService.java @@ -0,0 +1,167 @@ +package net.swofty.type.generic.collectibles.bedwars; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.VillagerProfession; +import net.swofty.type.generic.collectibles.CollectibleCategory; +import net.swofty.type.generic.collectibles.CollectibleDefinition; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.Locale; +import java.util.Map; +import java.util.Optional; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class BedWarsShopkeeperAppearanceService { + + private static final String DEFAULT_SHOPKEEPER_ID = "blacksmith"; + + public static ShopkeeperAppearance resolveSelected(HypixelPlayer player) { + Optional selected = BedWarsCollectibleStateService.resolveSelected( + player, + CollectibleCategory.SHOPKEEPER_SKINS + ); + + if (selected.isEmpty()) { + selected = BedWarsCollectibleCatalog.findItemById(DEFAULT_SHOPKEEPER_ID); + } + + return selected.map(BedWarsShopkeeperAppearanceService::resolve).orElse(defaultAppearance()); + } + + public static ShopkeeperAppearance resolve(CollectibleDefinition definition) { + Map customData = definition.customData(); + + String textureValue = clean(customData.get("textures")); + if (textureValue != null) { + return ShopkeeperAppearance.human(textureValue, clean(customData.get("signature"))); + } + + EntityType entityType = resolveEntityType(clean(customData.get("entity")), definition.id()); + if (entityType == EntityType.VILLAGER) { + VillagerProfession profession = resolveVillagerProfession(clean(customData.get("villager"))); + return ShopkeeperAppearance.villager(profession); + } + + return ShopkeeperAppearance.mob(entityType); + } + + public static ShopkeeperAppearance defaultAppearance() { + return ShopkeeperAppearance.villager(VillagerProfession.WEAPONSMITH); + } + + private static String clean(String value) { + if (value == null) { + return null; + } + + String cleaned = value.trim(); + if (cleaned.isEmpty() || cleaned.equalsIgnoreCase("null")) { + return null; + } + return cleaned; + } + + private static VillagerProfession resolveVillagerProfession(String rawProfession) { + if (rawProfession == null) { + return VillagerProfession.WEAPONSMITH; + } + + String normalized = normalizeKey(rawProfession); + return switch (normalized) { + case "BLACKSMITH", "WEAPONSMITH" -> VillagerProfession.WEAPONSMITH; + case "BUTCHER" -> VillagerProfession.BUTCHER; + case "LIBRARIAN" -> VillagerProfession.LIBRARIAN; + case "NITWIT" -> VillagerProfession.NITWIT; + case "NONE" -> VillagerProfession.NONE; + case "TOOLSMITH" -> VillagerProfession.TOOLSMITH; + default -> VillagerProfession.WEAPONSMITH; + }; + } + + private static EntityType resolveEntityType(String rawEntityType, String definitionId) { + if (rawEntityType != null) { + return switch (normalizeKey(rawEntityType)) { + case "VILLAGER" -> EntityType.VILLAGER; + case "SKELETON" -> EntityType.SKELETON; + case "WITHER_SKELETON" -> EntityType.WITHER_SKELETON; + case "BLAZE" -> EntityType.BLAZE; + case "ZOMBIE" -> EntityType.ZOMBIE; + case "ZOMBIE_VILLAGER", "VILLAGER_ZOMBIE" -> EntityType.ZOMBIE_VILLAGER; + case "WITCH" -> EntityType.WITCH; + case "CREEPER" -> EntityType.CREEPER; + case "ZOMBIFIED_PIGLIN", "ZOMBIE_PIGMAN", "PIG_ZOMBIE" -> EntityType.ZOMBIFIED_PIGLIN; + default -> inferFromDefinitionId(definitionId); + }; + } + + return inferFromDefinitionId(definitionId); + } + + private static EntityType inferFromDefinitionId(String definitionId) { + return switch (definitionId) { + case "skeleton" -> EntityType.SKELETON; + case "wither_skeleton" -> EntityType.WITHER_SKELETON; + case "blaze" -> EntityType.BLAZE; + case "zombie" -> EntityType.ZOMBIE; + case "witch" -> EntityType.WITCH; + case "creeper" -> EntityType.CREEPER; + case "zombie_pigman" -> EntityType.ZOMBIFIED_PIGLIN; + case "villager_zombie" -> EntityType.ZOMBIE_VILLAGER; + default -> EntityType.VILLAGER; + }; + } + + private static String normalizeKey(String value) { + return value.trim().toUpperCase(Locale.ROOT).replace('-', '_').replace(' ', '_'); + } + + public enum AppearanceKind { + VILLAGER, + MOB, + HUMAN + } + + public record ShopkeeperAppearance( + AppearanceKind kind, + EntityType entityType, + VillagerProfession villagerProfession, + String textureValue, + String textureSignature + ) { + public static ShopkeeperAppearance villager(VillagerProfession profession) { + VillagerProfession resolved = profession == null ? VillagerProfession.WEAPONSMITH : profession; + return new ShopkeeperAppearance(AppearanceKind.VILLAGER, EntityType.VILLAGER, resolved, null, null); + } + + public static ShopkeeperAppearance mob(EntityType entityType) { + EntityType resolved = entityType == null ? EntityType.VILLAGER : entityType; + if (resolved == EntityType.VILLAGER) { + return villager(VillagerProfession.WEAPONSMITH); + } + return new ShopkeeperAppearance(AppearanceKind.MOB, resolved, null, null, null); + } + + public static ShopkeeperAppearance human(String textureValue, String textureSignature) { + if (textureValue == null || textureValue.isBlank()) { + return villager(VillagerProfession.WEAPONSMITH); + } + return new ShopkeeperAppearance( + AppearanceKind.HUMAN, + EntityType.PLAYER, + null, + textureValue, + textureSignature == null ? "" : textureSignature + ); + } + + public boolean isHuman() { + return kind == AppearanceKind.HUMAN; + } + + public int replayEntityTypeId() { + return entityType.id(); + } + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsWoodSkinRuntimeService.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsWoodSkinRuntimeService.java new file mode 100644 index 000000000..9c668e723 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/BedWarsWoodSkinRuntimeService.java @@ -0,0 +1,32 @@ +package net.swofty.type.generic.collectibles.bedwars; + +import net.minestom.server.item.Material; +import net.swofty.type.generic.collectibles.CollectibleCategory; +import net.swofty.type.generic.collectibles.CollectibleDefinition; +import net.swofty.type.generic.user.HypixelPlayer; + +import java.util.Optional; + +public final class BedWarsWoodSkinRuntimeService { + + private BedWarsWoodSkinRuntimeService() { + } + + public static Material resolveSelectedMaterial(HypixelPlayer player) { + Optional selected = BedWarsCollectibleStateService.reconcileSelected( + player, + CollectibleCategory.WOOD_SKINS + ); + if (selected.isEmpty()) { + return Material.OAK_PLANKS; + } + + Material selectedMaterial = BedWarsCollectibleCatalog.parseMaterial(selected.get().effectiveSelectionValue()); + if (selectedMaterial != null) { + return selectedMaterial; + } + + Material iconMaterial = selected.get().iconMaterial(); + return iconMaterial != null ? iconMaterial : Material.OAK_PLANKS; + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeDefinitions.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeDefinitions.java new file mode 100644 index 000000000..1350fef97 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeDefinitions.java @@ -0,0 +1,189 @@ +package net.swofty.type.generic.collectibles.bedwars.prestige; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.minestom.server.item.Material; + +import java.util.List; +import java.util.Locale; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class BedWarsPrestigeDefinitions { + + public static final String DEFAULT_SCHEME_ID = "prestige_scheme_diamond"; + public static final String DEFAULT_STAR_ID = "prestige_star_default"; + public static final String DEFAULT_BRACKET_ID = "prestige_bracket_none"; + + public static final List SCHEMES = List.of( + new Scheme("none", "None", Material.NAME_TAG, 0, style("", List.of("", "", ""), "", "")), + new Scheme("iron", "Iron", Material.IRON_INGOT, 100, style("§f", List.of("§f", "§f", "§f"), "§f", "§f")), + new Scheme("gold", "Gold", Material.GOLD_INGOT, 200, style("§6", List.of("§6", "§6", "§6"), "§6", "§6")), + new Scheme("diamond", "Diamond", Material.DIAMOND, 300, style("§b", List.of("§b", "§b", "§b"), "§b", "§b")), + new Scheme("emerald", "Emerald", Material.EMERALD, 400, style("§2", List.of("§2", "§2", "§2"), "§2", "§2")), + new Scheme("sapphire", "Sapphire", Material.CYAN_DYE, 500, style("§3", List.of("§3", "§3", "§3"), "§3", "§3")), + new Scheme("ruby", "Ruby", Material.RED_DYE, 600, style("§4", List.of("§4", "§4", "§4"), "§4", "§4")), + new Scheme("crystal", "Crystal", Material.QUARTZ, 700, style("§d", List.of("§d", "§d", "§d"), "§d", "§d")), + new Scheme("opal", "Opal", Material.LAPIS_LAZULI, 800, style("§9", List.of("§9", "§9", "§9"), "§9", "§9")), + new Scheme("amethyst", "Amethyst", Material.PURPLE_DYE, 900, style("§5", List.of("§5", "§5", "§5"), "§5", "§5")), + new Scheme("rainbow", "Rainbow", Material.NETHER_STAR, 1000, style("§c", List.of("§6", "§e", "§a"), "§b", "§d")), + new Scheme("iron_prime", "Iron Prime", Material.IRON_BLOCK, 1100, style("", List.of("§f", "§f", "§f"), "§7", "§7")), + new Scheme("gold_prime", "Gold Prime", Material.GOLD_BLOCK, 1200, style("", List.of("§e", "§e", "§e"), "§6", "§7")), + new Scheme("diamond_prime", "Diamond Prime", Material.DIAMOND_BLOCK, 1300, style("", List.of("§b", "§b", "§b"), "§3", "§7")), + new Scheme("emerald_prime", "Emerald Prime", Material.EMERALD_BLOCK, 1400, style("", List.of("§a", "§a", "§a"), "§2", "§7")), + new Scheme("sapphire_prime", "Sapphire Prime", Material.CYAN_WOOL, 1500, style("", List.of("§3", "§3", "§3"), "§9", "§7")), + new Scheme("ruby_prime", "Ruby Prime", Material.RED_WOOL, 1600, style("", List.of("§c", "§c", "§c"), "§4", "§7")), + new Scheme("crystal_prime", "Crystal Prime", Material.QUARTZ_BLOCK, 1700, style("", List.of("§d", "§d", "§d"), "§5", "§7")), + new Scheme("opal_prime", "Opal Prime", Material.LAPIS_BLOCK, 1800, style("", List.of("§9", "§9", "§9"), "§1", "§7")), + new Scheme("amethyst_prime", "Amethyst Prime", Material.PURPLE_WOOL, 1900, style("", List.of("§5", "§5", "§5"), "§8", "§7")), + new Scheme("dawn", "Dawn", Material.SUNFLOWER, 2200, style("§6", List.of("§6", "§f", "§f"), "§b", "§3")), + new Scheme("dusk", "Dusk", Material.PEONY, 2300, style("§5", List.of("§5", "§d", "§d"), "§6", "§e")), + new Scheme("air", "Air", Material.GLASS_BOTTLE, 2400, style("§b", List.of("§b", "§f", "§f"), "§7", "§7")), + new Scheme("wind", "Wind", Material.SADDLE, 2500, style("§f", List.of("§f", "§a", "§a"), "§2", "§2")), + new Scheme("nebula", "Nebula", Material.FERMENTED_SPIDER_EYE, 2600, style("§4", List.of("§4", "§c", "§c"), "§d", "§d")), + new Scheme("thunder", "Thunder", Material.OAK_SAPLING, 2700, style("§e", List.of("§e", "§f", "§f"), "§8", "§8")), + new Scheme("earth", "Earth", Material.GRASS_BLOCK, 2800, style("§a", List.of("§a", "§2", "§2"), "§6", "§6")), + new Scheme("water", "Water", Material.WATER_BUCKET, 2900, style("§b", List.of("§b", "§3", "§3"), "§9", "§9")), + new Scheme("fire", "Fire", Material.BLAZE_POWDER, 3000, style("§e", List.of("§e", "§6", "§6"), "§c", "§c")), + new Scheme("sunrise", "Sunrise", Material.RED_BED, 3100, style("§9", List.of("§9", "§3", "§3"), "§6", "§6")), + new Scheme("eclipse", "Eclipse", Material.ENDER_PEARL, 3200, style("§c", List.of("§4", "§7", "§7"), "§4", "§c")), + new Scheme("gamma", "Gamma", Material.BREWING_STAND, 3300, style("§9", List.of("§9", "§9", "§d"), "§c", "§c")), + new Scheme("majestic", "Majestic", Material.DIAMOND_HORSE_ARMOR, 3400, style("§2", List.of("§a", "§d", "§d"), "§5", "§5")), + new Scheme("andesine", "Andesine", Material.BEEF, 3500, style("§c", List.of("§c", "§4", "§4"), "§2", "§a")), + new Scheme("marine", "Marine", Material.COD, 3600, style("§a", List.of("§a", "§a", "§b"), "§9", "§9")), + new Scheme("element", "Element", Material.ENCHANTING_TABLE, 3700, style("§4", List.of("§4", "§c", "§c"), "§b", "§3")), + new Scheme("galaxy", "Galaxy", Material.END_STONE, 3800, style("§1", List.of("§1", "§9", "§5"), "§5", "§d")), + new Scheme("atomic", "Atomic", Material.EGG, 3900, style("§c", List.of("§c", "§a", "§a"), "§3", "§9")), + new Scheme("sunset", "Sunset", Material.DAYLIGHT_DETECTOR, 4000, style("§5", List.of("§5", "§c", "§c"), "§6", "§6")), + new Scheme("obsidian", "Obsidian", Material.OBSIDIAN, 4300, style("§0", List.of("§5", "§8", "§8"), "§5", "§5")), + new Scheme("spring", "Spring", Material.LIME_TERRACOTTA, 4400, style("§2", List.of("§2", "§a", "§e"), "§6", "§5")), + new Scheme("ice", "Ice", Material.ICE, 4500, style("§f", List.of("§f", "§b", "§b"), "§3", "§3")), + new Scheme("summer", "Summer", Material.YELLOW_TERRACOTTA, 4600, style("§3", List.of("§b", "§e", "§6"), "§6", "§d")), + new Scheme("spinel", "Spinel", Material.FLOWER_POT, 4700, style("§f", List.of("§4", "§c", "§c"), "§9", "§1")), + new Scheme("autumn", "Autumn", Material.ORANGE_TERRACOTTA, 4800, style("§5", List.of("§5", "§c", "§6"), "§6", "§b")), + new Scheme("mystic", "Mystic", Material.BIRCH_SAPLING, 4900, style("§2", List.of("§a", "§f", "§f"), "§f", "§a")), + new Scheme("eternal", "Eternal", Material.INK_SAC, 5000, style("§4", List.of("§4", "§5", "§9"), "§9", "§1")), + new Scheme("burnout", "Burnout", Material.FLINT_AND_STEEL, 5100, style("§4", List.of("§c", "§c", "§6"), "§e", "§f")), + new Scheme("cooldown", "Cooldown", Material.PACKED_ICE, 5200, style("§1", List.of("§9", "§3", "§b"), "§f", "§e")), + new Scheme("obliteration", "Obliteration", Material.TNT_MINECART, 5300, style("§5", List.of("§d", "§e", "§f"), "§e", "§d")), + new Scheme("ender", "Ender", Material.ENDER_EYE, 5400, style("§3", List.of("§a", "§2", "§8"), "§2", "§a")), + new Scheme("brust", "Brust", Material.MAGMA_CREAM, 5500, style("§2", List.of("§a", "§e", "§f"), "§b", "§d")), + new Scheme("comical", "Comical", Material.TNT, 5600, style("§4", List.of("§c", "§e", "§f"), "§e", "§c")), + new Scheme("lusterlost", "Lusterlost", Material.GRAY_DYE, 5700, style("§4", List.of("§6", "§2", "§3"), "§9", "§5")), + new Scheme("maelstrom", "Maelstrom", Material.MUSIC_DISC_MELLOHI, 5800, style("§5", List.of("§c", "§6", "§f"), "§b", "§3")), + new Scheme("time_undone", "Time Undone", Material.SKELETON_SKULL, 5900, style("", List.of("§0", "§8", "§7"), "§f", "§f")), + new Scheme("umbrella", "Umbrella", Material.RED_MUSHROOM, 6000, style("§c", List.of("§f", "§f", "§f"), "§c", "§f")), + new Scheme("luminous", "Luminous", Material.GLOWSTONE, 6100, style("§6", List.of("§e", "§f", "§f"), "§f", "§b")), + new Scheme("bittersweet", "Bittersweet", Material.MELON_SLICE, 6400, style("§b", List.of("§b", "§c", "§c"), "§c", "§a")), + new Scheme("sweetsour", "Sweetsour", Material.GLISTERING_MELON_SLICE, 6500, style("§3", List.of("§3", "§a", "§a"), "§f", "§a")), + new Scheme("pop", "Pop", Material.PEONY, 6600, style("§9", List.of("§d", "§d", "§d"), "§b", "§9")), + new Scheme("bubblegum", "Bubblegum", Material.PINK_DYE, 6700, style("§5", List.of("§d", "§d", "§d"), "§f", "§5")), + new Scheme("contrast", "Contrast", Material.PUFFERFISH, 6800, style("§0", List.of("§6", "§6", "§e"), "§e", "§f")), + new Scheme("blended", "Blended", Material.SUGAR_CANE, 6900, style("§a", List.of("§a", "§a", "§a"), "§2", "§2")), + new Scheme("allay", "Allay", Material.NOTE_BLOCK, 7000, style("§3", List.of("§b", "§b", "§b"), "§f", "§3")), + new Scheme("blaze", "Blaze", Material.BLAZE_ROD, 7100, style("§4", List.of("§c", "§6", "§e"), "§c", "§6")), + new Scheme("creeper", "Creeper", Material.GUNPOWDER, 7200, style("§2", List.of("§a", "§f", "§2"), "§a", "§f")), + new Scheme("drowned", "Drowned", Material.SAND, 7300, style("§2", List.of("§3", "§3", "§b"), "§b", "§a")), + new Scheme("enderman", "Enderman", Material.END_STONE, 7400, style("§8", List.of("§8", "§8", "§8"), "§d", "§8")), + new Scheme("frog", "Frog", Material.LILY_PAD, 7500, style("§6", List.of("§6", "§2", "§2"), "§f", "§f")), + new Scheme("ghast", "Ghast", Material.GHAST_TEAR, 7600, style("§f", List.of("§f", "§f", "§7"), "§7", "§c")), + new Scheme("hoglin", "Hoglin", Material.PORKCHOP, 7700, style("§d", List.of("§c", "§c", "§c"), "§6", "§d")), + new Scheme("iron_golem", "Iron Golem", Material.POPPY, 7800, style("§8", List.of("§7", "§f", "§f"), "§f", "§e")), + new Scheme("jerry", "Jerry", Material.VILLAGER_SPAWN_EGG, 7900, style("§6", List.of("§f", "§2", "§6"), "§2", "§f")), + new Scheme("kringle", "Kringle", Material.COOKIE, 8000, style("§2", List.of("§a", "§a", "§a"), "§c", "§4")), + new Scheme("liquid", "Liquid", Material.MILK_BUCKET, 8100, style("§8", List.of("§7", "§f", "§b"), "§3", "§9")), + new Scheme("mint", "Mint", Material.LARGE_FERN, 8200, style("§f", List.of("§f", "§f", "§f"), "§a", "§f")), + new Scheme("poser", "Poser", Material.SLIME_BALL, 8500, style("§3", List.of("§6", "§6", "§6"), "§e", "§3")), + new Scheme("quartz", "Quartz", Material.QUARTZ, 8600, style("§d", List.of("§f", "§f", "§f"), "§e", "§d")), + new Scheme("rich", "Rich", Material.GOLD_NUGGET, 8700, style("§8", List.of("§6", "§6", "§6"), "§6", "§8")), + new Scheme("sanguine", "Sanguine", Material.FLOWER_POT, 8800, style("§4", List.of("§4", "§4", "§c"), "§c", "§f")), + new Scheme("titanic", "Titanic", Material.OAK_BOAT, 8900, style("§9", List.of("§b", "§b", "§b"), "§3", "§3")), + new Scheme("unorthodox", "Unorthodox", Material.ALLIUM, 9000, style("§d", List.of("§d", "§d", "§d"), "§5", "§8")), + new Scheme("volcanic", "Volcanic", Material.NETHERRACK, 9100, style("§0", List.of("§c", "§6", "§6"), "§c", "§c")), + new Scheme("weeping_cherry", "Weeping Cherry", Material.LILAC, 9200, style("§2", List.of("§d", "§d", "§d"), "§a", "§2")), + new Scheme("x_ray", "X-Ray", Material.SKELETON_SPAWN_EGG, 9300, style("§f", List.of("§8", "§8", "§8"), "§f", "§f")), + new Scheme("yearn", "Yearn", Material.FIRE_CHARGE, 9400, style("§e", List.of("§6", "§4", "§8"), "§8", "§8")), + new Scheme("zebra", "Zebra", Material.GHAST_SPAWN_EGG, 9500, style("§0", List.of("§0", "§8", "§8"), "§7", "§7")), + new Scheme("caution", "Caution", Material.YELLOW_DYE, 9600, style("§e", List.of("§e", "§e", "§0"), "§0", "§e")), + new Scheme("indescribable", "Indescribable", Material.END_PORTAL_FRAME, 9700, style("§d", List.of("§d", "§d", "§e"), "§e", "§b")), + new Scheme("forgotten", "Forgotten", Material.GRAY_STAINED_GLASS_PANE, 9800, style("§0", List.of("§8", "§8", "§8"), "§8", "§0")), + new Scheme("fuse", "Fuse", Material.REPEATER, 9900, style("§8", List.of("§7", "§f", "§f"), "§f", "§e")), + new Scheme("prestigious", "Prestigious", Material.FIREWORK_ROCKET, 10000, style("§9", List.of("§b", "§f", "§f"), "§f", "§c")) + ); + + public static final List STARS = List.of( + new Star("default", "Default", Material.GREEN_DYE, 0, "✫"), + new Star("1000", "1000+", Material.PINK_DYE, 1000, "✪"), + new Star("2000", "2000+", Material.PURPLE_DYE, 2000, "⚝"), + new Star("3000", "3000+", Material.RED_DYE, 3000, "✥"), + new Star("4000", "4000+", Material.LAPIS_LAZULI, 4000, "✭"), + new Star("four_pointed", "Four-Pointed", Material.PRISMARINE_SHARD, 0, "✦"), + new Star("pinwheel", "Pinwheel", Material.NETHER_QUARTZ_ORE, 0, "✵"), + new Star("hollow", "Hollow", Material.HOPPER, 0, "✰"), + new Star("nautical", "Nautical", Material.OAK_BOAT, 0, "✯") + ); + + public static final List BRACKETS = List.of( + new Bracket("none", "None", Material.NAME_TAG, 0, "[", "]"), + new Bracket("curly_brace", "Curly Brace", Material.OAK_FENCE, 0, "{", "}"), + new Bracket("parenthesis", "Parenthesis", Material.SPRUCE_FENCE, 0, "(", ")"), + new Bracket("angled", "Angled", Material.BIRCH_FENCE, 0, "<", ">"), + new Bracket("double_angle_quotation_mark", "Double Angle Quotation Mark", Material.ACACIA_FENCE, 0, "«", "»") + ); + + public static Scheme scheme(String id) { + return SCHEMES.stream().filter(s -> s.id().equals(normalizeScheme(id))).findFirst().orElse(SCHEMES.stream().filter(s -> s.id().equals("diamond")).findFirst().orElse(SCHEMES.getFirst())); + } + + public static Star star(String id) { + return STARS.stream().filter(s -> s.id().equals(normalizeStar(id))).findFirst().orElse(STARS.getFirst()); + } + + public static Bracket bracket(String id) { + return BRACKETS.stream().filter(b -> b.id().equals(normalizeBracket(id))).findFirst().orElse(BRACKETS.getFirst()); + } + + public static String schemeCollectibleId(String id) { + return "prestige_scheme_" + normalizeScheme(id); + } + + public static String starCollectibleId(String id) { + return "prestige_star_" + normalizeStar(id); + } + + public static String bracketCollectibleId(String id) { + return "prestige_bracket_" + normalizeBracket(id); + } + + private static String normalizeScheme(String id) { + return stripPrefix(normalize(id), "prestige_scheme_"); + } + + private static String normalizeStar(String id) { + return stripPrefix(normalize(id), "prestige_star_"); + } + + private static String normalizeBracket(String id) { + return stripPrefix(normalize(id), "prestige_bracket_"); + } + + private static String stripPrefix(String id, String prefix) { + return id.startsWith(prefix) ? id.substring(prefix.length()) : id; + } + + private static String normalize(String id) { + return id == null || id.isBlank() ? "" : id.trim().toLowerCase(Locale.ROOT); + } + + private static BedWarsPrestigeStyle style(String openColor, List digitColors, String starColor, String closeColor) { + return BedWarsPrestigeStyle.colors(openColor, digitColors, starColor, closeColor); + } + + public record Scheme(String id, String name, Material material, int requiredLevel, BedWarsPrestigeStyle style) { + } + + public record Star(String id, String name, Material material, int requiredLevel, String symbol) { + } + + public record Bracket(String id, String name, Material material, int requiredLevel, String open, String close) { + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeRenderer.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeRenderer.java new file mode 100644 index 000000000..5974cdf29 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeRenderer.java @@ -0,0 +1,77 @@ +package net.swofty.type.generic.collectibles.bedwars.prestige; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.swofty.commons.bedwars.BedwarsLevelUtil; +import net.swofty.type.generic.collectibles.CollectibleCategory; +import net.swofty.type.generic.collectibles.bedwars.BedWarsCollectibleStateService; +import net.swofty.type.generic.data.datapoints.DatapointCollectibles; +import net.swofty.type.generic.data.datapoints.DatapointLeaderboardLong; +import net.swofty.type.generic.data.handlers.BedWarsDataHandler; +import net.swofty.type.generic.user.HypixelPlayer; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class BedWarsPrestigeRenderer { + + public static String renderBrackets(HypixelPlayer player) { + return render(player, level(player), true); + } + + public static String renderString(HypixelPlayer player) { + return render(player, level(player), false); + } + + public static String renderBrackets(HypixelPlayer player, int level) { + return render(player, level, true); + } + + public static String renderString(HypixelPlayer player, int level) { + return render(player, level, false); + } + + public static String renderPreview(HypixelPlayer player, int level, String schemeId, String starId, String bracketId) { + return render(level, schemeId, starId, bracketId, true); + } + + public static String renderForData(BedWarsDataHandler dataHandler, int level, boolean brackets) { + DatapointCollectibles.CollectiblesState state = dataHandler + .get(BedWarsDataHandler.Data.COLLECTIBLES, DatapointCollectibles.class) + .getValue(); + + return render( + level, + state.getSelected(CollectibleCategory.PRESTIGE_SCHEMES), + state.getSelected(CollectibleCategory.PRESTIGE_STARS), + state.getSelected(CollectibleCategory.PRESTIGE_BRACKETS), + brackets + ); + } + + private static String render(HypixelPlayer player, int level, boolean brackets) { + BedWarsCollectibleStateService.reconcileSelected(player, CollectibleCategory.PRESTIGE_SCHEMES); + BedWarsCollectibleStateService.reconcileSelected(player, CollectibleCategory.PRESTIGE_STARS); + BedWarsCollectibleStateService.reconcileSelected(player, CollectibleCategory.PRESTIGE_BRACKETS); + + String schemeId = BedWarsCollectibleStateService.getSelectedId(player, CollectibleCategory.PRESTIGE_SCHEMES); + String starId = BedWarsCollectibleStateService.getSelectedId(player, CollectibleCategory.PRESTIGE_STARS); + String bracketId = BedWarsCollectibleStateService.getSelectedId(player, CollectibleCategory.PRESTIGE_BRACKETS); + return render(level, schemeId, starId, bracketId, brackets); + } + + private static String render(int level, String schemeId, String starId, String bracketId, boolean brackets) { + BedWarsPrestigeDefinitions.Scheme scheme = BedWarsPrestigeDefinitions.scheme(schemeId); + BedWarsPrestigeDefinitions.Star star = BedWarsPrestigeDefinitions.star(starId); + BedWarsPrestigeDefinitions.Bracket bracket = BedWarsPrestigeDefinitions.bracket(bracketId); + return scheme.style().render(String.valueOf(level), star.symbol(), bracket, brackets); + } + + private static int level(HypixelPlayer player) { + BedWarsDataHandler handler = BedWarsDataHandler.getUser(player); + if (handler == null) { + return 0; + } + long experience = handler.get(BedWarsDataHandler.Data.EXPERIENCE, DatapointLeaderboardLong.class).getValue(); + return BedwarsLevelUtil.calculateLevel(experience); + } + +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeStyle.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeStyle.java new file mode 100644 index 000000000..13ca1cb9c --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/BedWarsPrestigeStyle.java @@ -0,0 +1,141 @@ +package net.swofty.type.generic.collectibles.bedwars.prestige; + +import java.util.Arrays; +import java.util.List; + +public record BedWarsPrestigeStyle( + TextPaint openBracket, + DigitPaint digits, + TextPaint star, + TextPaint closeBracket +) { + public BedWarsPrestigeStyle { + openBracket = openBracket == null ? TextPaint.none() : openBracket; + digits = digits == null ? DigitPaint.none() : digits; + star = star == null ? TextPaint.none() : star; + closeBracket = closeBracket == null ? TextPaint.none() : closeBracket; + } + + public static Builder builder() { + return new Builder(); + } + + public static BedWarsPrestigeStyle solid(String color) { + return builder() + .openBracket(color) + .digits(color) + .star(color) + .closeBracket(color) + .build(); + } + + public static BedWarsPrestigeStyle colors(String openColor, List digitColors, String starColor, String closeColor) { + return BedWarsPrestigeStyle.builder() + .openBracket(openColor) + .digits(digitColors.toArray(String[]::new)) + .star(starColor) + .closeBracket(closeColor) + .build(); + } + + public String render(String level, String starSymbol, BedWarsPrestigeDefinitions.Bracket bracket, boolean includeBrackets) { + StringBuilder rendered = new StringBuilder(); + if (includeBrackets) { + rendered.append(openBracket.apply(bracket.open())); + } + for (int i = 0; i < level.length(); i++) { + rendered.append(digits.apply(String.valueOf(level.charAt(i)), i, level.length())); + } + rendered.append(star.apply(starSymbol)); + if (includeBrackets) { + rendered.append(closeBracket.apply(bracket.close())); + } + return rendered.toString(); + } + + public static final class Builder { + private TextPaint openBracket = TextPaint.none(); + private DigitPaint digits = DigitPaint.none(); + private TextPaint star = TextPaint.none(); + private TextPaint closeBracket = TextPaint.none(); + + public Builder openBracket(String color) { + this.openBracket = TextPaint.color(color); + return this; + } + + public Builder digits(String... colors) { + this.digits = DigitPaint.gradient(colors); + return this; + } + + public Builder star(String color) { + this.star = TextPaint.color(color); + return this; + } + + public Builder closeBracket(String color) { + this.closeBracket = TextPaint.color(color); + return this; + } + + public Builder all(String color) { + return openBracket(color).digits(color).star(color).closeBracket(color); + } + + public BedWarsPrestigeStyle build() { + return new BedWarsPrestigeStyle(openBracket, digits, star, closeBracket); + } + } + + public record TextPaint(String color) { + public TextPaint { + color = color == null ? "" : color; + } + + public static TextPaint none() { + return new TextPaint(""); + } + + public static TextPaint color(String color) { + return new TextPaint(color); + } + + public String apply(String text) { + return color + text; + } + } + + public record DigitPaint(List colors) { + public DigitPaint { + colors = colors == null ? List.of("") : List.copyOf(colors); + if (colors.isEmpty()) { + colors = List.of(""); + } + } + + public static DigitPaint none() { + return new DigitPaint(List.of("")); + } + + public static DigitPaint gradient(String... colors) { + if (colors == null || colors.length == 0) { + return none(); + } + return new DigitPaint(Arrays.asList(colors)); + } + + public String apply(String digit, int index, int totalDigits) { + return colorAt(index, totalDigits) + digit; + } + + private String colorAt(int index, int totalDigits) { + if (colors.size() == 1 || totalDigits <= 1) { + return colors.getFirst(); + } + int mappedIndex = Math.min(colors.size() - 1, Math.round(index * (colors.size() - 1) / (float) (totalDigits - 1))); + return colors.get(mappedIndex); + } + } + +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/PrestigeCollectibleFactory.java b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/PrestigeCollectibleFactory.java new file mode 100644 index 000000000..ee1ec2336 --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/collectibles/bedwars/prestige/PrestigeCollectibleFactory.java @@ -0,0 +1,107 @@ +package net.swofty.type.generic.collectibles.bedwars.prestige; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import net.swofty.type.generic.collectibles.CollectibleCategory; +import net.swofty.type.generic.collectibles.CollectibleCurrency; +import net.swofty.type.generic.collectibles.CollectibleDefinition; +import net.swofty.type.generic.collectibles.CollectibleGamemode; +import net.swofty.type.generic.collectibles.CollectibleRarity; +import net.swofty.type.generic.collectibles.CollectibleUnlockMethod; +import net.swofty.type.generic.collectibles.CollectibleUnlockRequirement; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class PrestigeCollectibleFactory { + + public static List definitions() { + List definitions = new ArrayList<>(); + int sortIndex = 0; + for (BedWarsPrestigeDefinitions.Scheme scheme : BedWarsPrestigeDefinitions.SCHEMES) { + definitions.add(definition( + CollectibleCategory.PRESTIGE_SCHEMES, + BedWarsPrestigeDefinitions.schemeCollectibleId(scheme.id()), + scheme.name(), + scheme.material(), + sortIndex++, + scheme.requiredLevel(), + Map.of("prestigeId", scheme.id()) + )); + } + + sortIndex = 0; + for (BedWarsPrestigeDefinitions.Star star : BedWarsPrestigeDefinitions.STARS) { + definitions.add(definition( + CollectibleCategory.PRESTIGE_STARS, + BedWarsPrestigeDefinitions.starCollectibleId(star.id()), + star.name(), + star.material(), + sortIndex++, + star.requiredLevel(), + Map.of("symbol", star.symbol(), "prestigeId", star.id()) + )); + } + + sortIndex = 0; + for (BedWarsPrestigeDefinitions.Bracket bracket : BedWarsPrestigeDefinitions.BRACKETS) { + definitions.add(definition( + CollectibleCategory.PRESTIGE_BRACKETS, + BedWarsPrestigeDefinitions.bracketCollectibleId(bracket.id()), + bracket.name(), + bracket.material(), + sortIndex++, + bracket.requiredLevel(), + Map.of("open", bracket.open(), "close", bracket.close(), "prestigeId", bracket.id()) + )); + } + return List.copyOf(definitions); + } + + private static CollectibleDefinition definition( + CollectibleCategory category, + String id, + String name, + net.minestom.server.item.Material material, + int sortIndex, + int requiredLevel, + Map customData + ) { + CollectibleUnlockRequirement requirement = requiredLevel <= 0 + ? CollectibleUnlockRequirement.free() + : new CollectibleUnlockRequirement( + CollectibleUnlockMethod.BEDWARS_LEVEL, + null, + CollectibleCurrency.BEDWARS_TOKENS, + (long) requiredLevel, + null, + null, + null + ); + + return new CollectibleDefinition( + id, + CollectibleGamemode.BEDWARS, + category, + name, + material, + null, + List.of(), + null, + customData, + rarity(requiredLevel), + sortIndex, + id, + requirement + ); + } + + private static CollectibleRarity rarity(int requiredLevel) { + if (requiredLevel >= 5000) return CollectibleRarity.MYTHIC; + if (requiredLevel >= 1000) return CollectibleRarity.LEGENDARY; + if (requiredLevel > 0) return CollectibleRarity.RARE; + return CollectibleRarity.COMMON; + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/command/HypixelCommand.java b/type.generic/src/main/java/net/swofty/type/generic/command/HypixelCommand.java index a0193e526..855d88255 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/command/HypixelCommand.java +++ b/type.generic/src/main/java/net/swofty/type/generic/command/HypixelCommand.java @@ -24,7 +24,7 @@ public abstract class HypixelCommand { protected HypixelCommand() { this.params = this.getClass().getAnnotation(CommandParameters.class); - this.name = this.getClass().getSimpleName().replace(COMMAND_SUFFIX, "").toLowerCase(); + this.name = this.getClass().getSimpleName().replace(COMMAND_SUFFIX, "").toLowerCase(); // why? - ARI List aliases = new ArrayList<>(); if (params.aliases() != null && !params.aliases().trim().isEmpty()) { diff --git a/type.generic/src/main/java/net/swofty/type/generic/command/commands/GuildCommand.java b/type.generic/src/main/java/net/swofty/type/generic/command/commands/GuildCommand.java new file mode 100644 index 000000000..8290fce6d --- /dev/null +++ b/type.generic/src/main/java/net/swofty/type/generic/command/commands/GuildCommand.java @@ -0,0 +1,346 @@ +package net.swofty.type.generic.command.commands; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.event.HoverEvent; +import net.minestom.server.command.builder.arguments.ArgumentStringArray; +import net.minestom.server.command.builder.arguments.ArgumentType; +import net.swofty.commons.ServiceType; +import net.swofty.commons.guild.GuildData; +import net.swofty.commons.guild.GuildMember; +import net.swofty.commons.guild.GuildRank; +import net.swofty.proxyapi.ProxyService; +import net.swofty.type.generic.command.CommandParameters; +import net.swofty.type.generic.command.HypixelCommand; +import net.swofty.type.generic.guild.GuildManager; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.generic.user.categories.Rank; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@CommandParameters(aliases = "g", + description = "Guild management commands", + usage = "/guild ", + permission = Rank.DEFAULT, + allowsConsole = false) +public class GuildCommand extends HypixelCommand { + private final List pendingCommands = new ArrayList<>(); + + @Override + public void registerUsage(MinestomCommand command) { + ArgumentStringArray arguments = ArgumentType.StringArray("arguments"); + ProxyService guildService = new ProxyService(ServiceType.GUILD); + + command.addSyntax((sender, context) -> { + showHelp((HypixelPlayer) sender); + }); + + command.addSyntax((sender, context) -> { + if (!permissionCheck(sender)) return; + HypixelPlayer player = (HypixelPlayer) sender; + if (pendingCommands.contains(player.getUuid())) return; + pendingCommands.add(player.getUuid()); + + Thread.startVirtualThread(() -> { + try { + if (!guildService.isOnline().join()) { + player.sendMessage("§cGuild service is currently offline!"); + return; + } + + String[] args = context.get(arguments); + String sub = args[0].toLowerCase(); + String argument = args.length > 1 ? args[1] : null; + String message = args.length > 1 + ? String.join(" ", java.util.Arrays.copyOfRange(args, 1, args.length)) + : ""; + + dispatch(player, sub, argument, message, args); + } finally { + pendingCommands.remove(player.getUuid()); + } + }); + }, arguments); + } + + private void dispatch(HypixelPlayer player, String sub, String argument, String message, String[] args) { + switch (sub) { + case "help" -> showHelp(player); + case "log", "history" -> showGuildLog(player); + case "leave" -> GuildManager.leaveGuild(player); + case "disband" -> GuildManager.disbandGuild(player); + case "list", "info" -> showGuildInfo(player); + case "online", "members" -> showOnlineMembers(player); + case "member" -> showMember(player, argument); + case "mypermissions", "permissions" -> showPermissions(player); + case "top" -> showTop(player); + case "discord" -> showDiscord(player, message); + case "join" -> player.sendMessage("§cGuild join requests are not currently accepted by this guild."); + case "menu" -> player.sendMessage("§eOpen your profile and select §aGuild §eto open the Guild Menu."); + case "party" -> player.sendMessage("§cNo online guild party could be formed."); + case "quest" -> player.sendMessage("§eYour guild does not currently have an active Guild Quest."); + case "notifications", "slow", "onlinemode", "toggle" -> GuildManager.changeSetting(player, sub, "toggle"); + case "create" -> + withArgument(player, argument, "/guild create ", value -> GuildManager.createGuild(player, value)); + case "invite" -> + withArgument(player, argument, "/guild invite ", value -> GuildManager.invitePlayer(player, value)); + case "accept" -> + withArgument(player, argument, "/guild accept ", value -> GuildManager.acceptInvite(player, value)); + case "promote" -> + withArgument(player, argument, "/guild promote ", value -> GuildManager.promotePlayer(player, value)); + case "demote" -> + withArgument(player, argument, "/guild demote ", value -> GuildManager.demotePlayer(player, value)); + case "transfer" -> + withArgument(player, argument, "/guild transfer ", value -> GuildManager.transferOwnership(player, value)); + case "tag", "tagcolor", "rename", "finder" -> + withArgument(player, argument, "/guild " + sub + " ", value -> GuildManager.changeSetting(player, sub, value)); + case "settings" -> { + if (args.length < 3) player.sendMessage("§cUsage: /guild settings "); + else + GuildManager.changeSetting(player, args[1], String.join(" ", java.util.Arrays.copyOfRange(args, 2, args.length))); + } + case "chat" -> + withArgument(player, argument, "/guild chat ", value -> GuildManager.sendChat(player, message, false)); + case "officerchat", "oc" -> + withArgument(player, argument, "/guild officerchat ", value -> GuildManager.sendChat(player, message, true)); + case "motd" -> handleMotd(player, args); + case "description" -> + withArgument(player, argument, "/guild " + sub + " ", value -> GuildManager.changeSetting(player, sub, message)); + case "mute" -> GuildManager.mutePlayer(player, argument == null ? "everyone" : argument, + args.length > 2 ? parseDuration(args[2]) : 3600000); + case "unmute" -> GuildManager.unmutePlayer(player, argument == null ? "everyone" : argument); + case "kick" -> withArgument(player, argument, "/guild kick [reason]", value -> { + String reason = args.length > 2 + ? String.join(" ", java.util.Arrays.copyOfRange(args, 2, args.length)) + : ""; + GuildManager.kickPlayer(player, value, reason); + }); + case "setrank" -> { + if (args.length < 3) player.sendMessage("§cUsage: /guild setrank "); + else GuildManager.setRank(player, args[1], args[2]); + } + default -> { + player.sendMessage("§cUnknown guild command. Use /guild for help."); + } + } + } + + private long parseDuration(String input) { + try { + long amount = Long.parseLong(input.substring(0, input.length() - 1)); + return amount * switch (input.charAt(input.length() - 1)) { + case 's' -> 1000; + case 'm' -> 60000; + case 'h' -> 3600000; + case 'd' -> 86400000; + default -> 60000; + }; + } catch (RuntimeException ignored) { + return 3600000; + } + } + + private void showMember(HypixelPlayer player, String name) { + GuildData guild = GuildManager.getGuildFromPlayer(player); + UUID uuid = name == null ? player.getUuid() : net.swofty.type.generic.data.HypixelDataHandler.getPotentialUUIDFromName(name); + GuildMember member = guild == null || uuid == null ? null : guild.getMember(uuid); + if (member == null) { + player.sendMessage("§cThat player is not in your guild!"); + return; + } + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("§a" + HypixelPlayer.getRawName(uuid)); + player.sendMessage("§7Rank: §e" + member.getRankName()); + player.sendMessage("§7Weekly GEXP: §e" + String.format("%,d", member.getWeeklyGexp())); + player.sendMessage("§7Total GEXP: §e" + String.format("%,d", member.getTotalGexp())); + player.sendMessage("§9§m-----------------------------------------------------"); + } + + private void showPermissions(HypixelPlayer player) { + GuildData guild = GuildManager.getGuildFromPlayer(player); + GuildRank rank = guild == null ? null : guild.getMemberRank(player.getUuid()); + if (rank == null) { + player.sendMessage("§cYou are not in a guild!"); + return; + } + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("§6Permissions for §e" + rank.getName()); + rank.getPermissions().forEach(permission -> player.sendMessage("§a✔ §7" + permission.name())); + player.sendMessage("§9§m-----------------------------------------------------"); + } + + private void showTop(HypixelPlayer player) { + GuildData guild = GuildManager.getGuildFromPlayer(player); + if (guild == null) { + player.sendMessage("§cYou are not in a guild!"); + return; + } + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("§6Guild Experience Top"); + guild.getMembers().stream().sorted(java.util.Comparator.comparingLong(GuildMember::getTotalGexp).reversed()).limit(10) + .forEach(member -> player.sendMessage("§e" + HypixelPlayer.getRawName(member.getUuid()) + " §7- §a" + + String.format("%,d", member.getTotalGexp()))); + player.sendMessage("§9§m-----------------------------------------------------"); + } + + private void showDiscord(HypixelPlayer player, String value) { + if (!value.isBlank()) { + GuildManager.changeSetting(player, "discord", value); + return; + } + GuildData guild = GuildManager.getGuildFromPlayer(player); + player.sendMessage(guild == null || guild.getDiscordLink().isBlank() + ? "§cYour guild has not set a Discord link!" : "§6Guild Discord: §b" + guild.getDiscordLink()); + } + + private void handleMotd(HypixelPlayer player, String[] args) { + if (args.length == 1 || args[1].equalsIgnoreCase("help")) { + showMotdHelp(player); + return; + } + GuildData guild = GuildManager.getGuildFromPlayer(player); + if (guild == null) { + player.sendMessage("§cYou are not in a guild!"); + return; + } + List lines = new ArrayList<>(guild.getMotd() == null || guild.getMotd().isBlank() + ? List.of() : List.of(guild.getMotd().split("\\n", -1))); + switch (args[1].toLowerCase()) { + case "list", "preview" -> { + player.sendMessage("§9§m-----------------------------------------------------"); + lines.forEach(line -> player.sendMessage("§f" + line)); + player.sendMessage("§9§m-----------------------------------------------------"); + } + case "clear" -> GuildManager.changeSetting(player, "motd", ""); + case "add" -> { + if (args.length < 3) player.sendMessage("§cUsage: /guild motd add "); + else { + lines.add(String.join(" ", java.util.Arrays.copyOfRange(args, 2, args.length))); + GuildManager.changeSetting(player, "motd", String.join("\n", lines)); + } + } + case "set" -> { + if (args.length < 4) { + player.sendMessage("§cUsage: /guild motd set "); + return; + } + try { + int line = Integer.parseInt(args[2]) - 1; + if (line < 0 || line >= lines.size()) throw new IndexOutOfBoundsException(); + lines.set(line, String.join(" ", java.util.Arrays.copyOfRange(args, 3, args.length))); + GuildManager.changeSetting(player, "motd", String.join("\n", lines)); + } catch (NumberFormatException | IndexOutOfBoundsException e) { + player.sendMessage("§cThat MOTD line does not exist!"); + } + } + default -> showMotdHelp(player); + } + } + + private void showGuildLog(HypixelPlayer player) { + GuildData guild = GuildManager.getGuildFromPlayer(player); + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage(" §6Guild Log (Page 1 of 1)"); + player.sendMessage(""); + if (guild == null || guild.getAuditLog().isEmpty()) player.sendMessage("§7There are no guild log entries."); + else guild.getAuditLog().stream().limit(10).forEach(player::sendMessage); + player.sendMessage("§9§m-----------------------------------------------------"); + } + + private void withArgument(HypixelPlayer player, String argument, String usage, java.util.function.Consumer action) { + if (argument == null) { + player.sendMessage("§cUsage: " + usage); + return; + } + action.accept(argument); + } + + private void showGuildInfo(HypixelPlayer player) { + GuildData guild = GuildManager.getGuildFromPlayer(player); + if (guild == null) { + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("§cYou are not in a guild!"); + player.sendMessage("§9§m-----------------------------------------------------"); + return; + } + + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("§6§l" + guild.getName() + (guild.getTag() != null ? " §7[" + guild.getTagColor() + guild.getTag() + "§7]" : "")); + player.sendMessage("§7Level: §a" + guild.getLevel()); + player.sendMessage("§7Members: §a" + guild.getMembers().size() + "/" + GuildData.MAX_MEMBERS); + player.sendMessage("§7GEXP: §a" + guild.getTotalGexp()); + if (guild.getMotd() != null && !guild.getMotd().isEmpty()) { + player.sendMessage("§7MOTD: §f" + guild.getMotd()); + } + if (guild.getDescription() != null && !guild.getDescription().isEmpty()) { + player.sendMessage("§7Description: §f" + guild.getDescription()); + } + player.sendMessage("§9§m-----------------------------------------------------"); + } + + private void showOnlineMembers(HypixelPlayer player) { + GuildData guild = GuildManager.getGuildFromPlayer(player); + if (guild == null) { + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("§cYou are not in a guild!"); + player.sendMessage("§9§m-----------------------------------------------------"); + return; + } + + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("§6Guild Members - §a" + guild.getMembers().size()); + String memberList = guild.getMembers().stream() + .map(m -> HypixelPlayer.getDisplayName(m.getUuid())) + .collect(Collectors.joining("§7, ")); + player.sendMessage(memberList); + player.sendMessage("§9§m-----------------------------------------------------"); + } + + private void showHelp(HypixelPlayer player) { + player.sendMessage("§9§m-----------------------------------------------------"); + player.sendMessage("Guild Commands:"); + String[][] commands = { + {"accept", "Accepts a guild invitation"}, {"chat ", "Send a chat message to your guild chat channel"}, + {"create ", "Creates a guild with the specified name"}, {"demote ", "Demotes the player to the previous rank"}, + {"disband", "Disbands the guild"}, {"discord", "Set or view the guild's discord link"}, {"help", "Prints this help message"}, + {"history", "View the last 24 hours of guild events"}, {"info", "Prints information about your guild"}, + {"invite ", "Invites the player to your guild"}, {"join ", "Request to join the specified guild"}, + {"kick ", "Kicks the player from your guild"}, {"leave", "Leaves your current guild"}, + {"log", "View the audit log"}, {"member", "Displays information about the Guild Member"}, {"members", "Lists players in your guild"}, + {"menu", "Opens the Guild Menu"}, {"motd", "Modifies the MOTD for the Guild"}, {"mute