forked from ChomeNS/chipmunkmod
refactor: use configurate for config
This commit is contained in:
parent
3c83eedd09
commit
1d09eab935
11 changed files with 252 additions and 209 deletions
build.gradle
src/main
12
build.gradle
12
build.gradle
|
@ -16,13 +16,21 @@ dependencies {
|
|||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
||||
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
|
||||
|
||||
// Fabric API. This is technically optional, but you probably want it anyway.
|
||||
// Fabric API
|
||||
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
||||
|
||||
// LuaJ
|
||||
include(implementation("org.luaj:luaj-jse:3.0.1"))
|
||||
|
||||
// Configurate
|
||||
include(implementation("org.spongepowered:configurate-core:4.1.2"))
|
||||
include(implementation("org.spongepowered:configurate-gson:4.1.2"))
|
||||
include(implementation("io.leangen.geantyref:geantyref:1.3.16"))
|
||||
|
||||
// Adventure
|
||||
include(modImplementation("net.kyori:adventure-platform-fabric:6.2.0"))
|
||||
include(implementation("net.kyori:adventure-text-serializer-gson:4.18.0"))
|
||||
include(implementation("net.kyori:adventure-text-serializer-legacy:4.18.0"))
|
||||
include(implementation("org.luaj:luaj-jse:3.0.1"))
|
||||
}
|
||||
|
||||
processResources {
|
||||
|
|
|
@ -1,85 +1,74 @@
|
|||
package land.chipmunk.chipmunkmod;
|
||||
|
||||
import com.google.gson.GsonBuilder;
|
||||
import land.chipmunk.chipmunkmod.modules.KaboomCheck;
|
||||
import land.chipmunk.chipmunkmod.modules.SelfCare;
|
||||
import land.chipmunk.chipmunkmod.util.gson.BlockBoxTypeAdapter;
|
||||
import land.chipmunk.chipmunkmod.util.gson.BlockPosTypeAdapter;
|
||||
import land.chipmunk.chipmunkmod.util.configurate.ConfigurateUtilities;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import java.io.InputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongepowered.configurate.BasicConfigurationNode;
|
||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||
import org.spongepowered.configurate.objectmapping.ObjectMapper;
|
||||
import org.spongepowered.configurate.util.NamingSchemes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
public class ChipmunkMod implements ModInitializer {
|
||||
// This logger is used to write text to the console and the log file.
|
||||
// It is considered best practice to use your mod id as the logger's name.
|
||||
// That way, it's clear which mod wrote info, warnings, and errors.
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
|
||||
public static Configuration CONFIG;
|
||||
private static File CONFIG_DIR = new File("config");
|
||||
private static File CONFIG_FILE = new File(CONFIG_DIR, "chipmunkmod.json");
|
||||
private static final Path CONFIG_PATH = FabricLoader.getInstance()
|
||||
.getConfigDir().resolve("chipmunkmod.json");
|
||||
|
||||
public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger("chipmunkmod");
|
||||
public static Configuration CONFIG;
|
||||
|
||||
@Override
|
||||
public void onInitialize () {
|
||||
// This code runs as soon as Minecraft is in a mod-load-ready state.
|
||||
// However, some things (like resources) may still be uninitialized.
|
||||
// Proceed with mild caution.
|
||||
public static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
|
||||
try {
|
||||
CONFIG = loadConfig();
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException("Could not load the config", exception);
|
||||
@Override
|
||||
public void onInitialize() {
|
||||
// This code runs as soon as Minecraft is in a mod-load-ready state.
|
||||
// However, some things (like resources) may still be uninitialized.
|
||||
// Proceed with mild caution.
|
||||
|
||||
try {
|
||||
CONFIG = loadConfig();
|
||||
} catch (IOException exception) {
|
||||
throw new RuntimeException("Could not load the config", exception);
|
||||
}
|
||||
|
||||
KaboomCheck.INSTANCE.init();
|
||||
SelfCare.INSTANCE.init();
|
||||
|
||||
LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
|
||||
}
|
||||
|
||||
KaboomCheck.INSTANCE.init();
|
||||
SelfCare.INSTANCE.init();
|
||||
public static Configuration loadConfig() throws IOException {
|
||||
final ObjectMapper.Factory customFactory = ObjectMapper.factoryBuilder()
|
||||
.defaultNamingScheme(NamingSchemes.CAMEL_CASE)
|
||||
.build();
|
||||
|
||||
LOGGER.info("Loaded ChipmunkMod (chayapak's fork)");
|
||||
}
|
||||
final GsonConfigurationLoader loader = GsonConfigurationLoader.builder()
|
||||
.defaultOptions(options -> options
|
||||
.serializers(build -> build
|
||||
.registerAnnotatedObjects(customFactory)
|
||||
.registerAll(ConfigurateUtilities.customSerializers()))
|
||||
.shouldCopyDefaults(true))
|
||||
.indent(4)
|
||||
.path(CONFIG_PATH)
|
||||
.build();
|
||||
|
||||
public static Configuration loadConfig () throws IOException {
|
||||
CONFIG_DIR.mkdirs();
|
||||
// Configurate will create parent directories for us, so we don't need to do it
|
||||
final BasicConfigurationNode node = loader.load();
|
||||
final boolean isBlank = node.empty();
|
||||
|
||||
final Gson gson = new GsonBuilder()
|
||||
.registerTypeAdapter(BlockPos.class, new BlockPosTypeAdapter())
|
||||
.registerTypeAdapter(BlockBox.class, new BlockBoxTypeAdapter())
|
||||
.create();
|
||||
final File file = CONFIG_FILE;
|
||||
final Configuration config = node.get(Configuration.class);
|
||||
if (isBlank) {
|
||||
node.set(Configuration.class, config);
|
||||
loader.save(node);
|
||||
}
|
||||
|
||||
if (!file.exists()) {
|
||||
InputStream is = ChipmunkMod.class.getClassLoader().getResourceAsStream("default_config.json");
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while (reader.ready()) sb.append((char) reader.read());
|
||||
final String defaultConfig = sb.toString();
|
||||
|
||||
// Write the default config
|
||||
BufferedWriter configWriter = new BufferedWriter(new FileWriter(file));
|
||||
configWriter.write(defaultConfig);
|
||||
configWriter.close();
|
||||
|
||||
return gson.fromJson(defaultConfig, Configuration.class);
|
||||
return config;
|
||||
}
|
||||
|
||||
InputStream is = new FileInputStream(file);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
return gson.fromJson(reader, Configuration.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,32 @@
|
|||
package land.chipmunk.chipmunkmod;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
|
||||
|
||||
|
||||
@ConfigSerializable
|
||||
public class Configuration {
|
||||
public CommandManager commands = new CommandManager();
|
||||
public CommandCore core = new CommandCore();
|
||||
public Bots bots = new Bots();
|
||||
public CustomChat customChat = new CustomChat();
|
||||
public boolean fullbright = true; // unused, but it is here for old configs
|
||||
public boolean fullbright = false; // unused, but it is here for old configs
|
||||
public String autoSkinUsername = "off";
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CommandManager {
|
||||
public String prefix = ".";
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CommandCore {
|
||||
public BlockBox relativeArea = BlockBox.create(new BlockPos(0, 0, 0), new BlockPos(15, 0, 15));
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class Bots {
|
||||
public BotInfo hbot = new BotInfo("#", null);
|
||||
public BotInfo sbot = new BotInfo(":", null);
|
||||
|
@ -32,13 +38,15 @@ public class Configuration {
|
|||
public TestBotInfo testbot = new TestBotInfo("-", null);
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class ChomeNSBotInfo {
|
||||
public String prefix;
|
||||
public String key;
|
||||
public String authKey;
|
||||
public String formatKey;
|
||||
public @Nullable String key;
|
||||
public @Nullable String authKey;
|
||||
public @Nullable String formatKey;
|
||||
|
||||
public ChomeNSBotInfo (String prefix, String key, String authKey, String formatKey) {
|
||||
public ChomeNSBotInfo() {}
|
||||
public ChomeNSBotInfo (String prefix, @Nullable String key, @Nullable String authKey, @Nullable String formatKey) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
this.authKey = authKey;
|
||||
|
@ -46,27 +54,35 @@ public class Configuration {
|
|||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class TestBotInfo {
|
||||
public String prefix;
|
||||
public String webhookUrl;
|
||||
public @Nullable String webhookUrl;
|
||||
|
||||
public TestBotInfo (String prefix, String webhookUrl) {
|
||||
public TestBotInfo() {}
|
||||
public TestBotInfo (String prefix, @Nullable String webhookUrl) {
|
||||
this.prefix = prefix;
|
||||
this.webhookUrl = webhookUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class BotInfo {
|
||||
public String prefix;
|
||||
public String key;
|
||||
public @Nullable String key;
|
||||
|
||||
public BotInfo (String prefix, String key) {
|
||||
public BotInfo() {}
|
||||
public BotInfo (String prefix, @Nullable String key) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigSerializable
|
||||
public static class CustomChat {
|
||||
public JsonObject format;
|
||||
public @NotNull Component format =
|
||||
Component.translatable("chat.type.text",
|
||||
Component.selector("UUID"),
|
||||
Component.text("MESSAGE"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package land.chipmunk.chipmunkmod.modules;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.gson.JsonElement;
|
||||
import land.chipmunk.chipmunkmod.ChipmunkMod;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
@ -17,6 +16,8 @@ import java.util.Timer;
|
|||
import java.util.TimerTask;
|
||||
|
||||
public class CustomChat {
|
||||
private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson();
|
||||
|
||||
private final MinecraftClient client;
|
||||
|
||||
public static final CustomChat INSTANCE = new CustomChat(MinecraftClient.getInstance());
|
||||
|
@ -69,10 +70,7 @@ public class CustomChat {
|
|||
}
|
||||
|
||||
public void reloadFormat () {
|
||||
final JsonElement formatString = ChipmunkMod.CONFIG.customChat.format;
|
||||
|
||||
if (formatString == null) format = "{\"translate\":\"chat.type.text\",\"with\":[\"USERNAME\",\"MESSAGE\"]}";
|
||||
else format = formatString.toString();
|
||||
this.format = GSON.serializeToTree(ChipmunkMod.CONFIG.customChat.format).toString();
|
||||
}
|
||||
|
||||
public void chat (String message) {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package land.chipmunk.chipmunkmod.util.configurate;
|
||||
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class BlockBoxTypeSerializer implements TypeSerializer<BlockBox> {
|
||||
private static final String START = "start";
|
||||
private static final String END = "end";
|
||||
|
||||
public static final BlockBoxTypeSerializer INSTANCE = new BlockBoxTypeSerializer();
|
||||
|
||||
private BlockBoxTypeSerializer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBox deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
final BlockPos start = ConfigurateUtilities.getNodeOrThrow(source, START).require(BlockPos.class);
|
||||
final BlockPos end = ConfigurateUtilities.getNodeOrThrow(source, END).require(BlockPos.class);
|
||||
|
||||
return BlockBox.create(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, final @Nullable BlockBox box,
|
||||
final ConfigurationNode target) throws SerializationException {
|
||||
if (box == null) {
|
||||
target.raw(null);
|
||||
return;
|
||||
}
|
||||
|
||||
target.node(START).set(BlockPos.class, new BlockPos(box.getMinX(), box.getMinY(), box.getMinZ()));
|
||||
target.node(END).set(BlockPos.class, new BlockPos(box.getMaxX(), box.getMaxY(), box.getMaxZ()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package land.chipmunk.chipmunkmod.util.configurate;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class BlockPosTypeSerializer implements TypeSerializer<BlockPos> {
|
||||
private static final String X = "x";
|
||||
private static final String Y = "y";
|
||||
private static final String Z = "z";
|
||||
|
||||
public static final BlockPosTypeSerializer INSTANCE = new BlockPosTypeSerializer();
|
||||
|
||||
private BlockPosTypeSerializer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
final int x = ConfigurateUtilities.getNodeOrThrow(source, X).getInt();
|
||||
final int y = ConfigurateUtilities.getNodeOrThrow(source, Y).getInt();
|
||||
final int z = ConfigurateUtilities.getNodeOrThrow(source, Z).getInt();
|
||||
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, final @Nullable BlockPos pos,
|
||||
final ConfigurationNode target) throws SerializationException {
|
||||
if (pos == null) {
|
||||
target.raw(null);
|
||||
return;
|
||||
}
|
||||
|
||||
target.node(X).set(pos.getX());
|
||||
target.node(Y).set(pos.getY());
|
||||
target.node(Z).set(pos.getZ());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package land.chipmunk.chipmunkmod.util.configurate;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class ComponentTypeSerializer implements TypeSerializer<Component> {
|
||||
private static final GsonComponentSerializer GSON = GsonComponentSerializer.gson();
|
||||
public static final ComponentTypeSerializer INSTANCE = new ComponentTypeSerializer();
|
||||
|
||||
private ComponentTypeSerializer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component deserialize(final Type type, final ConfigurationNode source) throws SerializationException {
|
||||
final JsonElement elem = source.get(JsonElement.class);
|
||||
if (elem == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return GSON.deserializeFromTree(elem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(final Type type, final @Nullable Component component,
|
||||
final ConfigurationNode target) throws SerializationException {
|
||||
if (component == null) {
|
||||
target.raw(null);
|
||||
return;
|
||||
}
|
||||
|
||||
final JsonElement elem = GSON.serializeToTree(component);
|
||||
target.set(JsonElement.class, elem);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package land.chipmunk.chipmunkmod.util.configurate;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.spongepowered.configurate.ConfigurationNode;
|
||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
import org.spongepowered.configurate.serialize.TypeSerializerCollection;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class ConfigurateUtilities {
|
||||
private static final TypeSerializerCollection CUSTOM_SERIALIZER_COLLECTION = TypeSerializerCollection.builder()
|
||||
.registerAll(GsonConfigurationLoader.gsonSerializers())
|
||||
.register(BlockPos.class, BlockPosTypeSerializer.INSTANCE)
|
||||
.register(BlockBox.class, BlockBoxTypeSerializer.INSTANCE)
|
||||
.register(Component.class, ComponentTypeSerializer.INSTANCE)
|
||||
.build();
|
||||
|
||||
private ConfigurateUtilities() {
|
||||
}
|
||||
|
||||
public static TypeSerializerCollection customSerializers() {
|
||||
return CUSTOM_SERIALIZER_COLLECTION;
|
||||
}
|
||||
|
||||
public static ConfigurationNode getNodeOrThrow(final ConfigurationNode source, final Object... path) throws SerializationException {
|
||||
if (!source.hasChild(path)) {
|
||||
throw new SerializationException("Required field " + Arrays.toString(path) + " was not present in node");
|
||||
}
|
||||
|
||||
return source.node(path);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package land.chipmunk.chipmunkmod.util.gson;
|
||||
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import net.minecraft.util.math.BlockBox;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BlockBoxTypeAdapter extends TypeAdapter<BlockBox> {
|
||||
private final BlockPosTypeAdapter blockPosAdapter = new BlockPosTypeAdapter();
|
||||
|
||||
@Override
|
||||
public BlockBox read(JsonReader reader) throws IOException {
|
||||
BlockPos start = null;
|
||||
BlockPos end = null;
|
||||
|
||||
reader.beginObject();
|
||||
|
||||
|
||||
while (!reader.peek().equals(JsonToken.END_OBJECT)) {
|
||||
if (reader.peek().equals(JsonToken.NAME)) {
|
||||
String name = reader.nextName();
|
||||
|
||||
switch (name) {
|
||||
case "start" -> start = blockPosAdapter.read(reader);
|
||||
case "end" -> end = blockPosAdapter.read(reader);
|
||||
default -> reader.skipValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
|
||||
if (start == null || end == null) return null;
|
||||
return BlockBox.create(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter writer, BlockBox box) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package land.chipmunk.chipmunkmod.util.gson;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
public class BlockPosTypeAdapter extends TypeAdapter<BlockPos> {
|
||||
@Override
|
||||
public BlockPos read (JsonReader reader) throws IOException {
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
|
||||
reader.beginObject();
|
||||
|
||||
while (!reader.peek().equals(JsonToken.END_OBJECT)) {
|
||||
if (reader.peek().equals(JsonToken.NAME)) {
|
||||
String name = reader.nextName();
|
||||
|
||||
switch (name) {
|
||||
case "x" -> x = reader.nextInt();
|
||||
case "y" -> y = reader.nextInt();
|
||||
case "z" -> z = reader.nextInt();
|
||||
default -> reader.skipValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reader.endObject();
|
||||
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write (JsonWriter out, BlockPos vec) throws IOException {
|
||||
// TODO: make this do something lmfaooo
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"commands": {
|
||||
"prefix": "."
|
||||
},
|
||||
|
||||
"core": {
|
||||
"relativeArea": {
|
||||
"start": { "x": 0, "y": 0, "z": 0 },
|
||||
"end": { "x": 15, "y": 0, "z": 15 }
|
||||
}
|
||||
},
|
||||
|
||||
"bots": {
|
||||
"hbot": { "prefix": "#", "key": null },
|
||||
"sbot": { "prefix": ":", "key": null },
|
||||
"chipmunk": { "prefix": "'", "key": null },
|
||||
"chomens": { "prefix": "*", "key": null, "authKey": null, "formatKey": null },
|
||||
"fnfboyfriend": { "prefix": "~", "key": null },
|
||||
"nbot": { "prefix": "?", "key": null },
|
||||
"kittycorp": { "prefix": "^", "key": null },
|
||||
"testbot": { "prefix": "-", "webhookUrl": null }
|
||||
},
|
||||
|
||||
"customChat": {
|
||||
"format": {
|
||||
"translate": "chat.type.text",
|
||||
"with": [
|
||||
{
|
||||
"selector": "UUID"
|
||||
},
|
||||
{
|
||||
"text": "MESSAGE"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
"autoSkinUsername": "off"
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue