Merge branch 'development'

This commit is contained in:
Brianna 2020-03-25 15:50:07 -04:00
commit 4680ef22e2
12 changed files with 300 additions and 166 deletions

View File

@ -1,21 +0,0 @@
stages:
- build
variables:
name: "EpicAnchors"
path: "/builds/$CI_PROJECT_PATH"
version: "1.4.6"
build:
stage: build
image: maven:3.5.3-jdk-8
script:
- find $path/ -type f -name "*.xml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g
- find $path/ -type f -name "*.yml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g
- mvn clean package
- find $path/ -depth -path '*original*' -delete
- mv $path/target/*.jar $path/
artifacts:
name: $name-$version
paths:
- "$path/*.jar"

32
pom.xml
View File

@ -2,7 +2,7 @@
<groupId>com.songoda</groupId>
<artifactId>EpicAnchors</artifactId>
<modelVersion>4.0.0</modelVersion>
<version>maven-version-number</version>
<version>1.4.7</version>
<build>
<defaultGoal>clean install</defaultGoal>
<finalName>EpicAnchors-${project.version}</finalName>
@ -16,6 +16,28 @@
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<file>${project.build.directory}/classes/plugin.yml</file>
<replacements>
<replacement>
<token>maven-version-number</token>
<value>${project.version}</value>
</replacement>
</replacements>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
@ -70,6 +92,10 @@
<id>private</id>
<url>http://repo.songoda.com/artifactory/private/</url>
</repository>
<repository>
<id>public</id>
<url>https://repo.songoda.com/artifactory/public/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
@ -78,8 +104,8 @@
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version>
<artifactId>spigot</artifactId>
<version>1.15</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -4,15 +4,18 @@ import com.songoda.core.SongodaCore;
import com.songoda.core.SongodaPlugin;
import com.songoda.core.commands.CommandManager;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.core.configuration.Config;
import com.songoda.core.gui.GuiManager;
import com.songoda.core.hooks.EconomyManager;
import com.songoda.core.hooks.HologramManager;
import com.songoda.core.utils.TextUtils;
import com.songoda.epicanchors.anchor.Anchor;
import com.songoda.epicanchors.anchor.AnchorManager;
import com.songoda.epicanchors.commands.*;
import com.songoda.epicanchors.listeners.BlockListeners;
import com.songoda.epicanchors.listeners.InteractListeners;
import com.songoda.epicanchors.listeners.PortalListeners;
import com.songoda.epicanchors.settings.Settings;
import com.songoda.epicanchors.tasks.AnchorTask;
import com.songoda.epicanchors.tasks.VisualizeTask;
@ -79,7 +82,7 @@ public class EpicAnchors extends SongodaPlugin {
);
anchorManager = new AnchorManager();
Bukkit.getScheduler().runTaskLater(this, () -> loadAnchorsFromFile(), 5L);
Bukkit.getScheduler().runTaskLater(this, this::loadAnchorsFromFile, 5L);
// Start tasks
new AnchorTask(this);
@ -90,6 +93,8 @@ public class EpicAnchors extends SongodaPlugin {
PluginManager pluginManager = Bukkit.getPluginManager();
pluginManager.registerEvents(new BlockListeners(this), this);
pluginManager.registerEvents(new InteractListeners(this), this);
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9))
pluginManager.registerEvents(new PortalListeners(this), this);
// Register Hologram Plugin
HologramManager.load(this);
@ -171,13 +176,13 @@ public class EpicAnchors extends SongodaPlugin {
}
public ItemStack makeAnchorItem(int ticks) {
ItemStack item = getCoreConfig().getMaterial("Main.Anchor Block Material", CompatibleMaterial.END_PORTAL_FRAME).getItem();
ItemStack item = Settings.MATERIAL.getMaterial().getItem();
ItemMeta meta = item.getItemMeta();
meta.setDisplayName(Methods.formatName(ticks, true));
ArrayList<String> lore = new ArrayList<>();
String[] parts = Settings.LORE.getString().split("\\|");
for (String line : parts) {
lore.add(Methods.formatText(line));
lore.add(TextUtils.formatText(line));
}
meta.setLore(lore);
item.setItemMeta(meta);

View File

@ -11,6 +11,7 @@ public class Anchor {
private Location location;
private int ticksLeft;
private boolean isInfinite;
private final int chunkX;
private final int chunkZ;
@ -20,6 +21,7 @@ public class Anchor {
this.chunkX = location.getBlockX() >> 4;
this.chunkZ = location.getBlockZ() >> 4;
this.ticksLeft = ticksLeft;
this.isInfinite = (ticksLeft == -99);
}
public void addTime(String type, Player player) {
@ -96,4 +98,12 @@ public class Anchor {
public void setTicksLeft(int ticksLeft) {
this.ticksLeft = ticksLeft;
}
public boolean isInfinite() {
return isInfinite;
}
public void setInfinite(boolean infinite) {
isInfinite = infinite;
}
}

View File

@ -2,6 +2,7 @@ package com.songoda.epicanchors.commands;
import com.songoda.core.commands.AbstractCommand;
import com.songoda.epicanchors.EpicAnchors;
import com.songoda.epicanchors.utils.Methods;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -31,16 +32,19 @@ public class CommandGive extends AbstractCommand {
return ReturnType.SYNTAX_ERROR;
}
try {
Integer.parseInt(args[1]);
} catch (Exception e) {
ItemStack itemStack;
if (Methods.isInt(args[1])) {
itemStack = (Integer.parseInt(args[1]) <= 0) ? instance.makeAnchorItem(-99) : instance.makeAnchorItem(Integer.parseInt(args[1]) * 20 * 60 * 60);
} else if (args[1].toLowerCase().equals("infinite")) {
itemStack = instance.makeAnchorItem(-99);
} else {
instance.getLocale().newMessage("&cYou can only use whole numbers...").sendPrefixedMessage(sender);
return ReturnType.FAILURE;
}
ItemStack itemStack = instance.makeAnchorItem(Integer.parseInt(args[1]) * 20 * 60 * 60);
if (target != null) {
target.getInventory().addItem(itemStack);
instance.getLocale().getMessage("command.give.success").sendPrefixedMessage(target);
@ -50,6 +54,7 @@ public class CommandGive extends AbstractCommand {
instance.getLocale().getMessage("command.give.success").sendPrefixedMessage(player);
}
}
return ReturnType.SUCCESS;
}
@ -75,7 +80,7 @@ public class CommandGive extends AbstractCommand {
@Override
public String getSyntax() {
return "/ea give <player/all> <amount in hours>";
return "/ea give <player/all> <amount in hours / infinite>";
}
@Override

View File

@ -4,6 +4,8 @@ import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.gui.Gui;
import com.songoda.core.gui.GuiUtils;
import com.songoda.core.hooks.EconomyManager;
import com.songoda.core.utils.TextUtils;
import com.songoda.core.utils.TimeUtils;
import com.songoda.epicanchors.EpicAnchors;
import com.songoda.epicanchors.anchor.Anchor;
import com.songoda.epicanchors.settings.Settings;
@ -27,7 +29,7 @@ public class GUIOverview extends Gui {
this.player = player;
this.setRows(3);
this.setTitle(Methods.formatText(plugin.getLocale().getMessage("interface.anchor.title").getMessage()));
this.setTitle(TextUtils.formatText(plugin.getLocale().getMessage("interface.anchor.title").getMessage()));
runTask();
constructGUI();
@ -49,14 +51,14 @@ public class GUIOverview extends Gui {
setItem(13, GuiUtils.createButtonItem(plugin.makeAnchorItem(anchor.getTicksLeft()),
plugin.getLocale().getMessage("interface.anchor.smalltitle").getMessage(),
ChatColor.GRAY + Methods.makeReadable((long) (anchor.getTicksLeft() / 20) * 1000) + " remaining."));
(anchor.isInfinite()) ? ChatColor.GRAY + "Infinite" : ChatColor.GRAY + TimeUtils.makeReadable((long) (anchor.getTicksLeft() / 20) * 1000) + " remaining."));
if (EconomyManager.isEnabled() && Settings.ADD_TIME_WITH_ECONOMY.getBoolean()) {
setButton(15, GuiUtils.createButtonItem(Settings.ECO_ICON.getMaterial(CompatibleMaterial.SUNFLOWER),
plugin.getLocale().getMessage("interface.button.addtimewitheconomy").getMessage(),
plugin.getLocale().getMessage("interface.button.addtimewitheconomylore")
.processPlaceholder("cost", Methods.formatEconomy(Settings.ECONOMY_COST.getDouble())).getMessage()), // EconomyManager.formatEconomy adds its own prefix/suffix
event -> anchor.addTime("ECO", event.player));
.processPlaceholder("cost", EconomyManager.formatEconomy(Settings.ECONOMY_COST.getDouble())).getMessage()), // EconomyManager.formatEconomy adds its own prefix/suffix
event -> checkInfiniteAndAlert(anchor, event.player, true));
}
if (Settings.ADD_TIME_WITH_XP.getBoolean()) {
@ -64,7 +66,7 @@ public class GUIOverview extends Gui {
plugin.getLocale().getMessage("interface.button.addtimewithxp").getMessage(),
plugin.getLocale().getMessage("interface.button.addtimewithxplore")
.processPlaceholder("cost", String.valueOf(Settings.XP_COST.getInt())).getMessage()),
event -> anchor.addTime("XP", event.player));
event -> checkInfiniteAndAlert(anchor, event.player, false));
}
}
@ -72,7 +74,19 @@ public class GUIOverview extends Gui {
private void runTask() {
task = Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, () -> {
updateItem(13, plugin.getLocale().getMessage("interface.anchor.smalltitle").getMessage(),
ChatColor.GRAY + Methods.makeReadable((long) (anchor.getTicksLeft() / 20) * 1000) + " remaining.");
(anchor.isInfinite()) ? ChatColor.GRAY + "Infinite" : ChatColor.GRAY + TimeUtils.makeReadable((long) (anchor.getTicksLeft() / 20) * 1000) + " remaining.");
}, 5L, 5L);
}
private void checkInfiniteAndAlert(Anchor anchor, Player p, boolean eco) {
if (anchor.isInfinite()) {
plugin.getLocale().getMessage("interface.button.infinite").sendPrefixedMessage(p);
} else {
if (eco) {
anchor.addTime("ECO", p);
} else {
anchor.addTime("XP", p);
}
}
}
}

View File

@ -7,7 +7,6 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.world.PortalCreateEvent;
import org.bukkit.inventory.ItemStack;
public class BlockListeners implements Listener {
@ -29,15 +28,13 @@ public class BlockListeners implements Listener {
|| plugin.getTicksFromItem(item) == 0) return;
Anchor anchor = new Anchor(event.getBlock().getLocation(), plugin.getTicksFromItem(item));
plugin.getAnchorManager().addAnchor(event.getBlock().getLocation(), anchor);
if (plugin.getTicksFromItem(item) == -99) {
anchor.setInfinite(true);
}
plugin.getAnchorManager().addAnchor(event.getBlock().getLocation(), anchor);
plugin.updateHologram(anchor);
}
@EventHandler
public void onPortalCreation(PortalCreateEvent e) {
if (e.getBlocks().size() < 1) return;
if (plugin.getAnchorManager().isAnchor(e.getBlocks().get(0).getLocation())) e.setCancelled(true);
}
}

View File

@ -1,5 +1,6 @@
package com.songoda.epicanchors.listeners;
import com.songoda.core.compatibility.CompatibleHand;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.core.compatibility.CompatibleParticleHandler;
import com.songoda.core.compatibility.CompatibleSound;
@ -55,7 +56,7 @@ public class InteractListeners implements Listener {
anchor.setTicksLeft(anchor.getTicksLeft() + instance.getTicksFromItem(item));
if (player.getGameMode() != GameMode.CREATIVE)
ItemUtils.takeActiveItem(player);
ItemUtils.takeActiveItem(player, CompatibleHand.getHand(event));
player.playSound(player.getLocation(), CompatibleSound.ENTITY_PLAYER_LEVELUP.getSound(), 0.6F, 15.0F);

View File

@ -0,0 +1,21 @@
package com.songoda.epicanchors.listeners;
import com.songoda.epicanchors.EpicAnchors;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.PortalCreateEvent;
public class PortalListeners implements Listener {
private EpicAnchors plugin;
public PortalListeners(EpicAnchors instance) {
this.plugin = instance;
}
@EventHandler
public void onPortalCreation(PortalCreateEvent e) {
if (e.getBlocks().size() < 1) return;
if (plugin.getAnchorManager().isAnchor(e.getBlocks().get(0).getLocation())) e.setCancelled(true);
}
}

View File

@ -0,0 +1,145 @@
package com.songoda.epicanchors.tasks;
import com.songoda.core.compatibility.CompatibleParticleHandler;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.epicanchors.EpicAnchors;
import com.songoda.epicanchors.anchor.Anchor;
import com.songoda.epicspawners.EpicSpawners;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class AnchorTask extends BukkitRunnable {
private static EpicAnchors plugin;
private Map<Location, Integer> delays = new HashMap<>();
private Class<?> clazzEntity, clazzCraftEntity, clazzMinecraftServer;
private Method methodTick, methodGetHandle;
private Field fieldCurrentTick, fieldActivatedTick;
private boolean epicSpawners;
public AnchorTask(EpicAnchors plug) {
plugin = plug;
epicSpawners = Bukkit.getPluginManager().getPlugin("EpicSpawners") != null;
try {
String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23);
clazzMinecraftServer = Class.forName("net.minecraft.server." + ver + ".MinecraftServer");
clazzEntity = Class.forName("net.minecraft.server." + ver + ".Entity");
clazzCraftEntity = Class.forName("org.bukkit.craftbukkit." + ver + ".entity.CraftEntity");
if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13))
methodTick = clazzEntity.getDeclaredMethod("tick");
else if (ServerVersion.isServerVersion(ServerVersion.V1_12))
methodTick = clazzEntity.getDeclaredMethod("B_");
else if (ServerVersion.isServerVersion(ServerVersion.V1_11))
methodTick = clazzEntity.getDeclaredMethod("A_");
else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9))
methodTick = clazzEntity.getDeclaredMethod("m");
else
methodTick = clazzEntity.getDeclaredMethod("t_");
methodGetHandle = clazzCraftEntity.getDeclaredMethod("getHandle");
fieldCurrentTick = clazzMinecraftServer.getDeclaredField("currentTick");
fieldActivatedTick = clazzEntity.getDeclaredField("activatedTick");
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
this.runTaskTimer(plugin, 0, 3);
}
private void doParticle() {
for (Anchor anchor : plugin.getAnchorManager().getAnchors().values()) {
Location location1 = anchor.getLocation().add(.5, .5, .5);
if (location1.getWorld() == null) continue;
CompatibleParticleHandler.redstoneParticles(location1, 255, 255, 255, 1.2F, 5, .75F);
}
}
@Override
public void run() {
doParticle();
for (Anchor anchor : new ArrayList<>(plugin.getAnchorManager().getAnchors().values())) {
if (anchor.getLocation() == null) continue;
plugin.updateHologram(anchor);
Location location = anchor.getLocation();
if (anchor.getLocation().getBlock().getType() != Material.valueOf(plugin.getConfig().getString("Main.Anchor Block Material")))
continue;
Chunk chunk = location.getChunk();
chunk.load();
// Load entities
for (Entity entity : chunk.getEntities()) {
if (!(entity instanceof LivingEntity) || entity instanceof Player) continue;
if (entity.getNearbyEntities(32, 32, 32).stream().anyMatch(entity1 -> entity1 instanceof Player)) {
continue;
}
try {
Object objCraftEntity = clazzCraftEntity.cast(entity);
Object objEntity = methodGetHandle.invoke(objCraftEntity);
fieldActivatedTick.set(objEntity, fieldCurrentTick.getLong(objEntity));
methodTick.invoke(objEntity);
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
}
int ticksLeft = anchor.getTicksLeft();
if (!anchor.isInfinite()) {
anchor.setTicksLeft(ticksLeft - 3);
}
if (ticksLeft <= 0 && !anchor.isInfinite()) {
anchor.bust();
chunk.unload();
return;
}
if (!epicSpawners || EpicSpawners.getInstance().getSpawnerManager() == null) continue;
EpicSpawners.getInstance().getSpawnerManager().getSpawners().stream()
.filter(spawner -> spawner.getWorld().isChunkLoaded(spawner.getX() >> 4, spawner.getZ() >> 4)
&& chunk == spawner.getLocation().getChunk()).forEach(spawner -> {
Block block = spawner.getLocation().getBlock();
if (!delays.containsKey(block.getLocation())) {
delays.put(block.getLocation(), spawner.updateDelay());
return;
}
int delay = delays.get(block.getLocation());
delay -= 1;
delays.put(block.getLocation(), delay);
if (delay <= 0) {
spawner.spawn();
delays.remove(block.getLocation());
}
});
}
}
}

View File

@ -1,5 +1,8 @@
package com.songoda.epicanchors.utils;
import com.songoda.core.utils.TextUtils;
import com.songoda.core.utils.TimeUtils;
import com.songoda.epicanchors.EpicAnchors;
import com.songoda.epicanchors.settings.Settings;
import org.bukkit.*;
import org.bukkit.block.Block;
@ -17,50 +20,17 @@ public class Methods {
public static String formatName(int ticks2, boolean full) {
String remaining = Methods.makeReadable((ticks2 / 20L) * 1000L);
String remaining = TimeUtils.makeReadable((ticks2 / 20L) * 1000L);
String name = Settings.NAMETAG.getString().replace("{REMAINING}", remaining);
String name = Settings.NAMETAG.getString().replace("{REMAINING}", (ticks2 <= 0)
? EpicAnchors.getInstance().getLocale().getMessage("infinite").getMessage() : remaining);
String info = "";
if (full) {
info += convertToInvisibleString(ticks2 + ":");
info += TextUtils.convertToInvisibleString(ticks2 + ":");
}
return info + formatText(name);
}
public static String formatText(String text) {
if (text == null || text.equals(""))
return "";
return formatText(text, false);
}
public static String formatText(String text, boolean cap) {
if (text == null || text.equals(""))
return "";
if (cap)
text = text.substring(0, 1).toUpperCase() + text.substring(1);
return ChatColor.translateAlternateColorCodes('&', text);
}
public static String convertToInvisibleString(String s) {
if (s == null || s.equals(""))
return "";
StringBuilder hidden = new StringBuilder();
for (char c : s.toCharArray()) hidden.append(ChatColor.COLOR_CHAR + "").append(c);
return hidden.toString();
}
/**
* Serializes the location of the block specified.
*
* @param b The block whose location is to be saved.
* @return The serialized data.
*/
public static String serializeLocation(Block b) {
if (b == null)
return "";
return serializeLocation(b.getLocation());
return info + TextUtils.formatText(name);
}
/**
@ -104,67 +74,16 @@ public class Methods {
return location;
}
public static String makeReadable(Long time) {
if (time == null)
return "";
StringBuilder sb = new StringBuilder();
long days = TimeUnit.MILLISECONDS.toDays(time);
long hours = TimeUnit.MILLISECONDS.toHours(time) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(time));
long minutes = TimeUnit.MILLISECONDS.toMinutes(time) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(time));
long seconds = TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time));
if (days != 0L)
sb.append(" ").append(days).append("d");
if (hours != 0L)
sb.append(" ").append(hours).append("h");
if (minutes != 0L)
sb.append(" ").append(minutes).append("m");
if (seconds != 0L)
sb.append(" ").append(seconds).append("s");
return sb.toString().trim();
public static boolean isInt(String number) {
if (number != null && !number.equals("")) {
try {
Integer.parseInt(number);
return true;
} catch (NumberFormatException var2) {
return false;
}
public static long parseTime(String input) {
long result = 0;
StringBuilder number = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (Character.isDigit(c)) {
number.append(c);
} else if (Character.isLetter(c) && (number.length() > 0)) {
result += convert(Integer.parseInt(number.toString()), c);
number = new StringBuilder();
} else {
return false;
}
}
return result;
}
private static long convert(long value, char unit) {
switch (unit) {
case 'd':
return value * 1000 * 60 * 60 * 24;
case 'h':
return value * 1000 * 60 * 60;
case 'm':
return value * 1000 * 60;
case 's':
return value * 1000;
}
return 0;
}
/**
* Formats the specified double into the Economy format specified in the Arconix config.
*
* @param amt The double to format.
* @return The economy formatted double.
*/
public static String formatEconomy(double amt) {
return formatter.format(amt);
}
static DecimalFormat formatter = new DecimalFormat("#,###.00");
}

View File

@ -1,25 +1,37 @@
# General Messages
general.nametag.prefix = "&8[&6EpicAnchors&8]"
general.nametag.next = "&9Next"
general.nametag.back = "&9Back"
general:
nametag:
prefix: '&8[&6EpicAnchors&8]'
word:
infinite: 'Infinite'
# Interface Messages
interface.button.addtimewithxp = "&aAdd 30 Minutes with XP"
interface.button.addtimewithxplore = "&7Cost: &a%cost% Levels"
interface.button.addtimewitheconomy = "&aAdd 30 Minutes with ECO"
interface.button.addtimewitheconomylore = "&7Cost: &a$%cost%"
interface.anchor.title = "ChunkAnchor"
interface.anchor.smalltitle = "&eChunkAnchor"
interface:
button:
addtimewithxp: '&aAdd 30 Minutes with XP'
addtimewithxplore: '&7Cost: &a%cost% Levels'
addtimewitheconomy: '&aAdd 30 Minutes with ECO'
addtimewitheconomylore: '&7Cost: &a$%cost%'
infinite: '&cCannot upgrade an infinite anchor!'
anchor:
title: ChunkAnchor
smalltitle: '&eChunkAnchor'
# Command Messages
command.give.success = "&7You have been given a ChunkAnchor."
command.show.start = "&7Anchor visualizer &2enabled."
command.show.stop = "&7Anchor visualizer &cdisabled."
command:
give:
success: '&7You have been given a ChunkAnchor.'
show:
start: '&7Anchor visualizer &2enabled.'
stop: '&7Anchor visualizer &cdisabled.'
# Event Messages
event.general.nopermission = "&cYou do not have permission to do that."
event.upgrade.cannotafford = "&cYou cant afford that."
event:
general:
nopermission: '&cYou do not have permission to do that.'
upgrade:
cannotafford: '&cYou cant afford that.'