7 Commits

Author SHA1 Message Date
7ad7ce6ed4 Added the Shared Ender Chest 2025-03-26 00:43:43 +01:00
78a56b6f28 Added config version "control" 2025-03-25 23:15:10 +01:00
6e15c54b80 Fixed INSTANCE not being assigned 2025-03-25 23:02:19 +01:00
22de60988f Removed unnecessary imports 2025-03-25 23:00:50 +01:00
c8f907dc57 Added customizable config messages & feature toggles 2025-03-25 22:59:05 +01:00
8377f36114 Updated README 2025-03-25 21:47:23 +01:00
f3a1156fd4 Changed mod icon 2025-03-25 21:36:53 +01:00
13 changed files with 425 additions and 52 deletions

View File

@ -8,17 +8,33 @@ As a challenge I'm trying to make it as user-friendly as possible. (It ain't the
- Custom join message - Custom join message
- Custom quit message - Custom quit message
- Custom chat message - Custom chat message
- Tablist dimension indicator - Tab list dimension indicator
### Commands ### Commands
- /spectator | Essentially server-side freecam, you get put in spectator and are able to fly around, once you use the command again you get put back to where you were. - /spectator | Essentially server-side free-cam, you get put in spectator and are able to fly around, once you use the command again you get put back to where you were.
## Currently working on v1.3.0
### Features
- [x] Config
- [x] Configurable messages
- [x] Feature toggle
- [x] Version "control"
- [x] Shared Ender Chest
- [x] Shared EC Access control (via config)
- [ ] Vein miner
- [ ] Telekinesis
### Commands
- [ ] /slimechunk (/sc) | See if you're currently in a slimechunk
### Misc
- [x] Updated icon
## Features to come ## Features to come
### Features ### Features
- Vein miner
- Telekinesis
- Shared Enderchest
- [ ] Shared for all
- [ ] Shared per team

View File

@ -9,7 +9,7 @@ yarn_mappings=1.21.4+build.8
loader_version=0.16.10 loader_version=0.16.10
# Mod Properties # Mod Properties
mod_version=1.2.0 mod_version=1.3.0
maven_group=wtf.hak.survivalfabric maven_group=wtf.hak.survivalfabric
archives_base_name=survivalfabric archives_base_name=survivalfabric

View File

@ -3,11 +3,13 @@ package wtf.hak.survivalfabric;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
import net.minecraft.scoreboard.Team;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import wtf.hak.survivalfabric.commands.ReloadConfigCommand;
import wtf.hak.survivalfabric.commands.SpectatorCommand; import wtf.hak.survivalfabric.commands.SpectatorCommand;
import wtf.hak.survivalfabric.sharedenderchest.SharedEnderChest;
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
public class SurvivalFabric implements ModInitializer { public class SurvivalFabric implements ModInitializer {
@ -18,6 +20,9 @@ public class SurvivalFabric implements ModInitializer {
@Override @Override
public void onInitialize() { public void onInitialize() {
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, new String[] { "spectator", "s", "S", "camera", "c", "C", })); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, new String[] { "spectator", "s", "S", "camera", "c", "C", }));
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ReloadConfigCommand.register(dispatcher, new String[] { "reloadsurvivalconfig" }));
if(getConfig().sharedEnderChestEnabled)
new SharedEnderChest().onInitialize();
} }
} }

View File

@ -0,0 +1,22 @@
package wtf.hak.survivalfabric.commands;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import wtf.hak.survivalfabric.config.ConfigManager;
public class ReloadConfigCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, String... aliases) {
for (String str : aliases)
dispatcher.register(CommandManager.literal(str)
.requires(source -> source.hasPermissionLevel(2))
.executes(ReloadConfigCommand::execute));
}
private static int execute(CommandContext<ServerCommandSource> context) {
ConfigManager.load();
return 1;
}
}

View File

@ -0,0 +1,46 @@
package wtf.hak.survivalfabric.config;
import com.google.common.collect.Lists;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import java.util.List;
public class Config {
public String configVersion = "1.0";
public boolean joinMessageEnabled = true;
public String joinMessage = "§8[§a+§8] §7%s";
public boolean quitMessageEnabled = true;
public String quitMessage = "§8[§c-§8] §7%s";
public boolean chatMessageEnabled = true;
public String chatMessage = "§7%s§8:§f %s";
public boolean dimensionIndicatorEnabled = true;
public String overworldPrefix = "§8[§aOverworld§8] ";
public String netherPrefix = "§8[§cNether§8] ";
public String endPrefix = "§8[§dEnd§8] ";
public String spectatorPrefix = "§8[§eSpectator§8] ";
public String unknownPrefix = "§8[§7Unknown§8] ";
public boolean sharedEnderChestEnabled = true;
public String sharedEnderChestName = "Ender Chest";
public int sharedEnderChestRows = 6;
public boolean sharedEnderChestLimitedAccess = true;
public List<String> sharedEnderChestNames = Lists.newArrayList("AlwaysHAK", "LunaticFox");
public ScreenHandlerType<GenericContainerScreenHandler> screenHandlerType() {
return switch (sharedEnderChestRows) {
case 1 -> ScreenHandlerType.GENERIC_9X1;
case 2 -> ScreenHandlerType.GENERIC_9X2;
case 3 -> ScreenHandlerType.GENERIC_9X3;
case 4 -> ScreenHandlerType.GENERIC_9X4;
case 5 -> ScreenHandlerType.GENERIC_9X5;
case 6 -> ScreenHandlerType.GENERIC_9X6;
default -> ScreenHandlerType.GENERIC_9X3;
};
}
}

View File

@ -0,0 +1,50 @@
package wtf.hak.survivalfabric.config;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.fabricmc.loader.api.FabricLoader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class ConfigManager {
private static final File CONFIG_FILE = FabricLoader.getInstance().getConfigDir().resolve("survivalfabric.json").toFile();
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private static Config INSTANCE;
public static Config getConfig() {
if (INSTANCE == null) {
return load();
} else
return INSTANCE;
}
public static Config load() {
try(FileReader reader = new FileReader(CONFIG_FILE)) {
INSTANCE = GSON.fromJson(reader, Config.class);
if (INSTANCE.configVersion.equalsIgnoreCase(new Config().configVersion)) {
return INSTANCE;
}
INSTANCE.configVersion = new Config().configVersion;
save(INSTANCE);
return INSTANCE;
} catch (IOException e) {
Config config = new Config();
INSTANCE = config;
save(config);
return config;
}
}
public static void save(Config config) {
try(FileWriter writer = new FileWriter(CONFIG_FILE)) {
GSON.toJson(config, writer);
} catch (IOException e) {
System.out.println("Error saving config: " + e.getMessage());
}
}
}

View File

@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import wtf.hak.survivalfabric.commands.SpectatorCommand; import wtf.hak.survivalfabric.commands.SpectatorCommand;
import wtf.hak.survivalfabric.utils.Messages; import wtf.hak.survivalfabric.config.ConfigManager;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
@ -24,14 +24,19 @@ public abstract class PlayerManagerMixin {
@Inject(method = {"onPlayerConnect"}, at = {@At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")}) @Inject(method = {"onPlayerConnect"}, at = {@At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")})
public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) { public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) {
Text text = Text.literal(String.format(Messages.JOIN_MESSAGE, player.getName().getString())); if(ConfigManager.getConfig().joinMessageEnabled) {
player.sendMessage(text, false); Text text = Text.literal(String.format(ConfigManager.getConfig().joinMessage, player.getName().getString()));
player.sendMessage(text, false);
}
} }
@ModifyArg(method = {"onPlayerConnect"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) @ModifyArg(method = {"onPlayerConnect"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V"))
private Text onPlayerConnect(Text text) { private Text onPlayerConnect(Text text) {
String name = text.getString().split(" ")[0]; if(ConfigManager.getConfig().joinMessageEnabled) {
return Text.literal(String.format(Messages.JOIN_MESSAGE, name)); String name = text.getString().split(" ")[0];
return Text.literal(String.format(ConfigManager.getConfig().joinMessage, name));
} else
return text;
} }
@Inject(method = {"remove"}, at = {@At("HEAD")}) @Inject(method = {"remove"}, at = {@At("HEAD")})
@ -45,8 +50,8 @@ public abstract class PlayerManagerMixin {
@Inject(method = {"broadcast(Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V"}, at = {@At("HEAD")}, cancellable = true) @Inject(method = {"broadcast(Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V"}, at = {@At("HEAD")}, cancellable = true)
private void onBroadcast(SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters parameters, CallbackInfo ci) { private void onBroadcast(SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters parameters, CallbackInfo ci) {
if(sender != null) { if(sender != null && ConfigManager.getConfig().chatMessageEnabled) {
Text text = Text.literal(String.format(Messages.CHAT_FORMAT, sender.getName().getString(), message.getContent().getString())); Text text = Text.literal(String.format(ConfigManager.getConfig().chatMessage, sender.getName().getString(), message.getContent().getString()));
Objects.requireNonNull(sender.getServer()).getPlayerManager().broadcast(text, false); Objects.requireNonNull(sender.getServer()).getPlayerManager().broadcast(text, false);
ci.cancel(); ci.cancel();
} }

View File

@ -5,15 +5,18 @@ import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
import wtf.hak.survivalfabric.utils.Messages; import wtf.hak.survivalfabric.config.ConfigManager;
@Mixin(ServerPlayNetworkHandler.class) @Mixin(ServerPlayNetworkHandler.class)
public abstract class ServerPlayNetworkHandlerMixin { public abstract class ServerPlayNetworkHandlerMixin {
@ModifyArg(method = {"cleanUp"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) @ModifyArg(method = {"cleanUp"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V"))
private Text quitMessage(Text text) { private Text quitMessage(Text text) {
String name = text.getString().split(" ")[0]; if(ConfigManager.getConfig().quitMessageEnabled) {
return Text.literal(String.format(Messages.QUIT_MESSAGE, name)); String name = text.getString().split(" ")[0];
return Text.literal(String.format(ConfigManager.getConfig().quitMessage, name));
}
return text;
} }
} }

View File

@ -7,28 +7,30 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import wtf.hak.survivalfabric.commands.SpectatorCommand; import wtf.hak.survivalfabric.commands.SpectatorCommand;
import wtf.hak.survivalfabric.utils.Messages; import wtf.hak.survivalfabric.config.ConfigManager;
@Mixin(ServerPlayerEntity.class) @Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin { public abstract class ServerPlayerEntityMixin {
@Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true) @Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true)
private void changePlayerListName(CallbackInfoReturnable<Text> cir) { private void changePlayerListName(CallbackInfoReturnable<Text> cir) {
ServerPlayerEntity p = (ServerPlayerEntity) (Object) this; if(ConfigManager.getConfig().dimensionIndicatorEnabled) {
String world = p.getServerWorld().getRegistryKey().getValue().toTranslationKey(); ServerPlayerEntity p = (ServerPlayerEntity) (Object) this;
String finalName; String world = p.getServerWorld().getRegistryKey().getValue().toTranslationKey();
if(!SpectatorCommand.spectating.containsKey(p)) { String finalName;
finalName = switch (world) { if (!SpectatorCommand.spectating.containsKey(p)) {
case "minecraft.overworld" -> Messages.OVERWORLD_PREFIX; finalName = switch (world) {
case "minecraft.the_nether" -> Messages.NETHER_PREFIX; case "minecraft.overworld" -> ConfigManager.getConfig().overworldPrefix;
case "minecraft.the_end" -> Messages.END_PREFIX; case "minecraft.the_nether" -> ConfigManager.getConfig().netherPrefix;
default -> Messages.UNKNOWN_PREFIX; case "minecraft.the_end" -> ConfigManager.getConfig().endPrefix;
}; default -> ConfigManager.getConfig().unknownPrefix;
} else };
finalName = Messages.SPECTATOR_PREFIX; } else
finalName = ConfigManager.getConfig().spectatorPrefix;
finalName += "§7" + p.getName().getString(); finalName += "§7" + p.getName().getString();
cir.setReturnValue(Text.of(finalName)); cir.setReturnValue(Text.of(finalName));
}
} }
} }

View File

@ -0,0 +1,129 @@
package wtf.hak.survivalfabric.sharedenderchest;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.block.EnderChestBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtSizeTracker;
import net.minecraft.screen.GenericContainerScreenHandler;
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
import net.minecraft.server.MinecraftServer;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.*;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, ServerLifecycleEvents.ServerStarted, ServerTickEvents.EndTick {
private static SharedInventory sharedInventory;
private long ticksUntilSave = -20;
public void onServerStarted(MinecraftServer server) {
File inventoryFile = getFile(server);
if (inventoryFile.exists()) {
try (FileInputStream inventoryFileInputStream = new FileInputStream(inventoryFile);
DataInputStream inventoryFileDataInput = new DataInputStream(inventoryFileInputStream)) {
NbtCompound nbt = NbtIo.readCompressed(inventoryFileDataInput, NbtSizeTracker.ofUnlimitedBytes());
DefaultedList<ItemStack> inventoryItemStacks = DefaultedList.ofSize(getConfig().sharedEnderChestRows * 9, ItemStack.EMPTY);
Inventories.readNbt(nbt, inventoryItemStacks, server.getRegistryManager());
sharedInventory = new SharedInventory(inventoryItemStacks);
} catch (Exception e) {
System.out.println("[ShareEnderChest] Error while loading inventory: " + e);
sharedInventory = new SharedInventory(getConfig().sharedEnderChestRows);
}
} else {
sharedInventory = new SharedInventory(getConfig().sharedEnderChestRows);
}
}
public static void saveInventory(MinecraftServer server) {
File inventoryFile = getFile(server);
NbtCompound nbt = new NbtCompound();
DefaultedList<ItemStack> inventoryItemStacks = DefaultedList.ofSize(getConfig().sharedEnderChestRows * 9, ItemStack.EMPTY);
Inventories.writeNbt(nbt, sharedInventory.getList(inventoryItemStacks), server.getRegistryManager());
try (FileOutputStream inventoryFileOutputStream = new FileOutputStream(inventoryFile);
DataOutputStream inventoryFileDataOutput = new DataOutputStream(inventoryFileOutputStream)) {
inventoryFile.createNewFile();
NbtIo.writeCompressed(nbt, inventoryFileDataOutput);
} catch (Exception e) {
System.out.println("[ShareEnderChest] Error while saving inventory: " + e);
}
}
public void onServerStopping(MinecraftServer server) {
saveInventory(server);
}
public void onEndTick(MinecraftServer server) {
if (ticksUntilSave != -20 && --ticksUntilSave <= 0L) {
saveInventory(server);
ticksUntilSave = 20L;
}
}
public void onInitialize() {
ticksUntilSave = 20L;
UseBlockCallback listenerUseBlock = (player, world, hand, hitResult) -> {
if (world.getBlockState(hitResult.getBlockPos()).getBlock() instanceof EnderChestBlock) {
if (!player.isSpectator()) {
if(!getConfig().sharedEnderChestLimitedAccess) {
if (world.isClient()) return ActionResult.SUCCESS;
playEnderChestOpenSound(world, hitResult.getBlockPos());
openSharedEnderChest(player);
return ActionResult.SUCCESS;
} else {
for(String name : getConfig().sharedEnderChestNames) {
if(name.toLowerCase().strip().equalsIgnoreCase(player.getNameForScoreboard().toLowerCase())) {
if (world.isClient()) return ActionResult.SUCCESS;
playEnderChestOpenSound(world, hitResult.getBlockPos());
openSharedEnderChest(player);
return ActionResult.SUCCESS;
}
}
}
}
}
return ActionResult.PASS;
};
UseBlockCallback.EVENT.register(listenerUseBlock);
ServerLifecycleEvents.SERVER_STARTED.register(this);
ServerLifecycleEvents.SERVER_STOPPING.register(this);
ServerTickEvents.END_SERVER_TICK.register(this);
}
public static void openSharedEnderChest(PlayerEntity player) {
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((int_1, playerInventory, playerEntity) ->
new GenericContainerScreenHandler(getConfig().screenHandlerType(), int_1, playerInventory, sharedInventory, getConfig().sharedEnderChestRows), Text.of(getConfig().sharedEnderChestName)));
}
public static void playEnderChestOpenSound(World world, BlockPos pos) {
world.playSound(null, pos, SoundEvents.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F);
}
private static File getFile(MinecraftServer server) {
return server.getSavePath(WorldSavePath.ROOT).resolve("sharedenderchest.sav").toFile();
}
}

View File

@ -0,0 +1,111 @@
package wtf.hak.survivalfabric.sharedenderchest;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DefaultedList;
import java.util.Iterator;
public class SharedInventory implements Inventory {
private final DefaultedList<ItemStack> stacks;
public SharedInventory(int inventoryRows) {
this.stacks = DefaultedList.ofSize(inventoryRows * 9, ItemStack.EMPTY);
}
public SharedInventory(DefaultedList<ItemStack> dl) {
this.stacks = dl;
}
/*
@Override
public void onClose(PlayerEntity player) {
Inventory.super.onClose(player);
EnderChestBlockEntity blockEntity = enderChests.remove(player);
if (blockEntity != null)
blockEntity.onClose(player);
}
@Override
public void onOpen(PlayerEntity player) {
Inventory.super.onOpen(player);
EnderChestBlockEntity blockEntity = enderChests.get(player);
if (blockEntity != null)
blockEntity.onOpen(player);
}
public void setBlockEntity(PlayerEntity player, EnderChestBlockEntity be) {
enderChests.put(player, be);
}
*/
public DefaultedList<ItemStack> getList(DefaultedList<ItemStack> dl) {
dl = stacks;
return dl;
}
@Override
public int size() {
return stacks.size();
}
@Override
public boolean isEmpty() {
Iterator<ItemStack> var1 = this.stacks.iterator();
ItemStack itemStack_1;
do {
if (!var1.hasNext()) {
return true;
}
itemStack_1 = (ItemStack)var1.next();
} while(itemStack_1.isEmpty());
return false;
}
@Override
public ItemStack getStack(int i) {
return i >= stacks.size() ? ItemStack.EMPTY : stacks.get(i);
}
@Override
public ItemStack removeStack(int int_1, int int_2) {
ItemStack itemStack_1 = Inventories.splitStack(this.stacks, int_1, int_2);
if (!itemStack_1.isEmpty()) {
//this.container.onContentChanged(this);
}
return itemStack_1;
}
@Override
public ItemStack removeStack(int i) {
return Inventories.removeStack(this.stacks, i);
}
@Override
public void setStack(int i, ItemStack itemStack) {
this.stacks.set(i, itemStack);
//this.container.onContentChanged(this);
}
@Override
public void markDirty() {
}
@Override
public boolean canPlayerUse(PlayerEntity playerEntity) {
return true;
}
@Override
public void clear() {
stacks.clear();
}
}

View File

@ -1,16 +0,0 @@
package wtf.hak.survivalfabric.utils;
public class Messages {
public static final String JOIN_MESSAGE = "§8[§a+§8] §7%s";
public static final String QUIT_MESSAGE = "§8[§c-§8] §7%s";
public static final String CHAT_FORMAT = "§7%s§8:§f %s";
public static final String OVERWORLD_PREFIX = "§8[§aOverworld§8] ";
public static final String NETHER_PREFIX = "§8[§cNether§8] ";
public static final String END_PREFIX = "§8[§dEnd§8] ";
public static final String SPECTATOR_PREFIX = "§8[§eSpectator§8] ";
public static final String UNKNOWN_PREFIX = "§8[§7Unknown§8] ";
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB