rule management and extensibility

This commit is contained in:
gnembon committed 2019-07-04 01:54:13 -03:00
1 parent b56eb7403b
commit 95d556a978
6 files changed
+339 -275

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
package carpet;
import carpet.settings.SettingsManager;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
public abstract class CarpetExtension
{
/**
* When game started before world is loaded
*/
public void onGameStarted() {}
/**
* Runs once per loaded world once the World files / gamerules etc are fully loaded
* Can be loaded multiple times in SinglePlayer
*/
public void onServerLoaded(MinecraftServer server) {}
/**
* Runs once per game tick, as a first thing in the tick
*/
public void onTick(MinecraftServer server) {}
/**
* Register your own commands right after vanilla commands are added
* If that matters for you
*/
public void registerCommands(CommandDispatcher<ServerCommandSource> dispatcher) {}
/**
* Provide your own custom settings manager managed in the same way as base /carpet
* command, but separated to its own command as defined in SettingsManager.
*/
public SettingsManager customSettingsManager() {return null;}
/**
* todiddalidoo
*/
public void onPlayerLoggedIn(PlayerEntity player) {}
/**
* todiddalidoo
*/
public void onPlayerLoggedOut(PlayerEntity player) {}
}
+25 -12
View File
@@ -1,10 +1,11 @@
package carpet;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import carpet.commands.CameraModeCommand;
import carpet.commands.CarpetCommand;
import carpet.commands.CounterCommand;
import carpet.commands.DistanceCommand;
import carpet.commands.DrawCommand;
@@ -14,7 +15,6 @@ import carpet.commands.PerimeterInfoCommand;
import carpet.commands.PlayerCommand;
import carpet.commands.ScriptCommand;
import carpet.commands.SpawnCommand;
import carpet.commands.TestCommand;
import carpet.commands.TickCommand;
import carpet.helpers.TickSpeed;
import carpet.logging.LoggerRegistry;
@@ -32,25 +32,37 @@ public class CarpetServer // static for now - easier to handle all around the co
public static MinecraftServer minecraft_server;
public static CarpetScriptServer scriptServer;
public static SettingsManager settingsManager;
static
public static List<CarpetExtension> extensions = new ArrayList<>();
// Separate from onServerLoaded, because a server can be loaded multiple times in singleplayer
public static void manageExtension(CarpetExtension extension)
{
SettingsManager.parseSettingsClass(CarpetSettings.class);
//...
extensions.add(extension);
}
public static void onGameStarted()
{
LoggerRegistry.initLoggers();
settingsManager = new SettingsManager(CarpetSettings.carpetVersion, "carpet", "Carpet Mod");
settingsManager.parseSettingsClass(CarpetSettings.class);
extensions.forEach(CarpetExtension::onGameStarted);
}
public static void init(MinecraftServer server) //aka constructor of this static singleton class
{
// no sure we really need this here, needs testing and moving to onServerLoaded
CarpetServer.minecraft_server = server;
}
public static void onServerLoaded(MinecraftServer server)
{
settingsManager = new SettingsManager(server);
settingsManager.attachServer(server);
extensions.forEach(e -> {
if (e.customSettingsManager() != null)
e.customSettingsManager().attachServer(server);
e.onServerLoaded(server);
});
scriptServer = new CarpetScriptServer();
}
// Separate from onServerLoaded, because a server can be loaded multiple times in singleplayer
public static void onGameStarted()
{
LoggerRegistry.initLoggers();
}
public static void tick(MinecraftServer server)
{
@@ -59,6 +71,7 @@ public class CarpetServer // static for now - easier to handle all around the co
scriptServer.events.tick();
//in case something happens
CarpetSettings.impendingFillSkipUpdates = false;
extensions.forEach(e -> e.onTick(server));
}
public static void registerCarpetCommands(CommandDispatcher<ServerCommandSource> dispatcher)
@@ -74,7 +87,7 @@ public class CarpetServer // static for now - easier to handle all around the co
PerimeterInfoCommand.register(dispatcher);
DrawCommand.register(dispatcher);
ScriptCommand.register(dispatcher);
CarpetCommand.register(dispatcher);
extensions.forEach(e -> e.registerCommands(dispatcher));
//TestCommand.register(dispatcher);
}
}
@@ -1,213 +0,0 @@
package carpet.commands;
import carpet.CarpetServer;
import carpet.settings.CarpetSettings;
import carpet.settings.ParsedRule;
import carpet.settings.SettingsManager;
import carpet.utils.Messenger;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.text.BaseText;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
import static net.minecraft.server.command.CommandSource.suggestMatching;
public class CarpetCommand
{
private static ParsedRule<?> getRule(CommandContext<ServerCommandSource> ctx) throws CommandSyntaxException
{
String ruleName = StringArgumentType.getString(ctx, "rule");
ParsedRule<?> rule = SettingsManager.getRule(ruleName);
if (rule == null)
throw new SimpleCommandExceptionType(Messenger.c("rb Unknown rule: "+ruleName)).create();
return rule;
}
public static void register(CommandDispatcher<ServerCommandSource> dispatcher)
{
LiteralArgumentBuilder<ServerCommandSource> literalargumentbuilder = literal("carpet").requires((player) ->
player.hasPermissionLevel(2) && !CarpetServer.settingsManager.locked);
literalargumentbuilder.executes((context)->listAllSettings(context.getSource())).
then(literal("list").
executes( (c) -> listSettings(c.getSource(),
"All CarpetMod Settings",
SettingsManager.getRules())).
then(literal("defaults").
executes( (c)-> listSettings(c.getSource(),
"Current CarpetMod Startup Settings from carpet.conf",
CarpetServer.settingsManager.findStartupOverrides()))).
then(argument("tag",StringArgumentType.word()).
suggests( (c, b)->suggestMatching(SettingsManager.getCategories(), b)).
executes( (c) -> listSettings(c.getSource(),
String.format("CarpetMod Settings matching \"%s\"", StringArgumentType.getString(c, "tag")),
CarpetServer.settingsManager.getRulesMatching(StringArgumentType.getString(c, "tag")))))).
then(literal("removeDefault").
requires(s -> !CarpetServer.settingsManager.locked).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(SettingsManager.getRules().stream().map(r -> r.name), b)).
executes((c) -> removeDefault(c.getSource(), getRule(c))))).
then(literal("setDefault").
requires(s -> !CarpetServer.settingsManager.locked).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(SettingsManager.getRules().stream().map(r -> r.name), b)).
then(argument("value", StringArgumentType.word()).
suggests((c, b)-> suggestMatching(getRule(c).options, b)).
executes((c) -> setDefault(c.getSource(), getRule(c), StringArgumentType.getString(c, "value")))))).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(SettingsManager.getRules().stream().map(r -> r.name), b)).
requires(s -> !CarpetServer.settingsManager.locked ).
executes( (c) -> displayRuleMenu(c.getSource(),getRule(c))).
then(argument("value", StringArgumentType.word()).
suggests((c, b)-> suggestMatching(getRule(c).options,b)).
executes((c) -> setRule(c.getSource(), getRule(c), StringArgumentType.getString(c, "value")))));
dispatcher.register(literalargumentbuilder);
}
private static int displayRuleMenu(ServerCommandSource source, ParsedRule<?> rule)
{
PlayerEntity player;
try
{
player = source.getPlayer();
}
catch (CommandSyntaxException e)
{
Messenger.m(source, "w "+rule.name +" is set to: ","wb "+rule.getAsString());
return 1;
}
Messenger.m(player, "");
Messenger.m(player, "wb "+rule.name,"!/carpet "+rule.name,"^g refresh");
Messenger.m(player, "w "+rule.description);
rule.extraInfo.forEach(s -> Messenger.m(player, "g "+s));
List<BaseText> tags = new ArrayList<>();
tags.add(Messenger.c("w Tags: "));
for (String t: rule.categories)
{
tags.add(Messenger.c("c ["+t+"]", "^g list all "+t+" settings","!/carpet list "+t));
tags.add(Messenger.c("w , "));
}
tags.remove(tags.size()-1);
Messenger.m(player, tags.toArray(new Object[0]));
Messenger.m(player, "w Current value: ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified"));
List<BaseText> options = new ArrayList<>();
options.add(Messenger.c("w Options: ", "y [ "));
for (String o: rule.options)
{
options.add(makeSetRuleButton(rule, o, false));
options.add(Messenger.c("w "));
}
options.remove(options.size()-1);
options.add(Messenger.c("y ]"));
Messenger.m(player, options.toArray(new Object[0]));
return 1;
}
private static int setRule(ServerCommandSource source, ParsedRule<?> rule, String newValue)
{
if (rule.set(source, newValue) != null)
Messenger.m(source, "w "+rule.toString()+", ", "c [change permanently?]",
"^w Click to keep the settings in carpet.conf to save across restarts",
"?/carpet setDefault "+rule.name+" "+rule.getAsString());
return 1;
}
private static int setDefault(ServerCommandSource source, ParsedRule<?> rule, String defaultValue)
{
if (CarpetServer.settingsManager.setDefaultRule(source, rule.name, defaultValue))
Messenger.m(source ,"gi rule "+ rule.name+" will now default to "+ defaultValue);
return 1;
}
private static int removeDefault(ServerCommandSource source, ParsedRule<?> rule)
{
if (CarpetServer.settingsManager.removeDefaultRule(source, rule.name))
Messenger.m(source ,"gi rule "+ rule.name+" defaults to Vanilla");
return 1;
}
private static BaseText displayInteractiveSetting(ParsedRule<?> rule)
{
List<Object> args = new ArrayList<>();
args.add("w - "+rule.name+" ");
args.add("!/carpet "+rule.name);
args.add("^y "+rule.description);
for (String option: rule.options)
{
args.add(makeSetRuleButton(rule, option, true));
args.add("w ");
}
args.remove(args.size()-1);
return Messenger.c(args.toArray(new Object[0]));
}
private static BaseText makeSetRuleButton(ParsedRule<?> rule, String option, boolean brackets)
{
String style = rule.isDefault()?"g":(option.equalsIgnoreCase(rule.defaultAsString)?"y":"e");
if (option.equalsIgnoreCase(rule.defaultAsString))
style = style+"b";
else if (option.equalsIgnoreCase(rule.getAsString()))
style = style+"u";
String baseText = style + (brackets ? " [" : " ") + option + (brackets ? "]" : "");
if (CarpetServer.settingsManager.locked)
return Messenger.c(baseText, "^g Settings are locked");
if (option.equalsIgnoreCase(rule.getAsString()))
return Messenger.c(baseText);
return Messenger.c(baseText, "^g Switch to " + option, "?/carpet " + rule.name + " " + option);
}
private static int listSettings(ServerCommandSource source, String title, Collection<ParsedRule<?>> settings_list)
{
try
{
PlayerEntity player = source.getPlayer();
Messenger.m(player,String.format("wb %s:",title));
settings_list.forEach(e -> Messenger.m(player,displayInteractiveSetting(e)));
}
catch (CommandSyntaxException e)
{
Messenger.m(source, "w s:"+title);
settings_list.forEach(r -> Messenger.m(source, "w - "+ r.toString()));
}
return 1;
}
private static int listAllSettings(ServerCommandSource source)
{
listSettings(source, "Current CarpetMod Settings", CarpetServer.settingsManager.getNonDefault());
Messenger.m(source, "Carpet Mod version: "+ CarpetSettings.carpetVersion);
try
{
PlayerEntity player = source.getPlayer();
List<Object> tags = new ArrayList<>();
tags.add("w Browse Categories:\n");
for (String t : SettingsManager.getCategories())
{
tags.add("c [" + t+"]");
tags.add("^g list all " + t + " settings");
tags.add("!/carpet list " + t);
tags.add("w ");
}
tags.remove(tags.size() - 1);
Messenger.m(player, tags.toArray(new Object[0]));
}
catch (CommandSyntaxException ignored) { }
return 1;
}
}
@@ -25,7 +25,7 @@ import static carpet.settings.RuleCategory.SURVIVAL;
public class CarpetSettings
{
public static final String carpetVersion = "v190627";
public static final String carpetVersion = "v190704";
public static final Logger LOG = LogManager.getLogger();
public static boolean skipGenerationChecks = false;
public static boolean impendingFillSkipUpdates = false;
@@ -117,7 +117,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
if (!value.equals(get()))
{
this.field.set(null, value);
SettingsManager.notifyRuleChanged(source, this, stringValue);
CarpetServer.settingsManager.notifyRuleChanged(source, this, stringValue);
}
}
catch (IllegalAccessException e)
@@ -1,12 +1,21 @@
package carpet.settings;
import carpet.CarpetServer;
import carpet.utils.Messenger;
import com.google.common.collect.ImmutableList;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.tree.CommandNode;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.BaseText;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.util.TriConsumer;
import java.io.BufferedReader;
@@ -28,21 +37,44 @@ import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;
import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
import static net.minecraft.server.command.CommandSource.suggestMatching;
public class SettingsManager
{
private static final Logger LOG = LogManager.getLogger();
private static Map<String, ParsedRule<?>> rules = new HashMap<>();
private Map<String, ParsedRule<?>> rules = new HashMap<>();
public boolean locked;
private final String version;
private final String identifier;
private final String fancyName;
private MinecraftServer server;
private static List<TriConsumer<ServerCommandSource, ParsedRule<?>, String>> observers = new ArrayList<>();
private List<TriConsumer<ServerCommandSource, ParsedRule<?>, String>> observers = new ArrayList<>();
public SettingsManager(MinecraftServer server)
public SettingsManager(String version, String identifier)
{
this.version = version;
this.identifier = identifier;
this.fancyName = identifier;
}
public SettingsManager(String version, String identifier, String fancyName)
{
this.version = version;
this.identifier = identifier;
this.fancyName = fancyName;
}
public void attachServer(MinecraftServer server)
{
this.server = server;
loadConfigurationFromConf();
registerCommand(server.getCommandManager().getDispatcher());
notifyPlayersCommandsChanged();
}
public static void parseSettingsClass(Class settingsClass)
public SettingsManager parseSettingsClass(Class settingsClass)
{
for (Field f : settingsClass.getDeclaredFields())
{
@@ -51,19 +83,20 @@ public class SettingsManager
ParsedRule parsed = new ParsedRule(f, rule);
rules.put(parsed.name, parsed);
}
return this;
}
public static void addRuleObserver(TriConsumer<ServerCommandSource, ParsedRule<?>, String> observer)
public void addRuleObserver(TriConsumer<ServerCommandSource, ParsedRule<?>, String> observer)
{
observers.add(observer);
}
static void notifyRuleChanged(ServerCommandSource source, ParsedRule<?> rule, String userTypedValue)
void notifyRuleChanged(ServerCommandSource source, ParsedRule<?> rule, String userTypedValue)
{
observers.forEach(observer -> observer.accept(source, rule, userTypedValue));
}
public static Iterable<String> getCategories()
public Iterable<String> getCategories()
{
Set<String> categories = new HashSet<>();
getRules().stream().map(r -> r.categories).forEach(categories::addAll);
@@ -71,12 +104,12 @@ public class SettingsManager
}
public static ParsedRule<?> getRule(String name)
public ParsedRule<?> getRule(String name)
{
return rules.get(name);
}
public static Collection<ParsedRule<?>> getRules()
public Collection<ParsedRule<?>> getRules()
{
return rules.values().stream().sorted().collect(Collectors.toList());
}
@@ -96,7 +129,7 @@ public class SettingsManager
private File getFile()
{
return server.getLevelStorage().resolveFile(server.getLevelName(), "carpet.conf");
return server.getLevelStorage().resolveFile(server.getLevelName(), identifier+".conf");
}
public void disableBooleanFromCategory(String category)
@@ -126,7 +159,7 @@ public class SettingsManager
catch (IOException e)
{
e.printStackTrace();
LOG.error("[CM]: failed write the carpet.conf");
CarpetSettings.LOG.error("[CM]: failed write "+identifier+".conf config file");
}
///todo is it really needed? resendCommandTree();
}
@@ -150,13 +183,13 @@ public class SettingsManager
locked = false;
if (conf.getRight())
{
LOG.info("[CM]: Carpet Mod is locked by the administrator");
CarpetSettings.LOG.info("[CM]: "+fancyName+" features are locked by the administrator");
disableBooleanFromCategory(RuleCategory.COMMAND);
}
for (String key: conf.getLeft().keySet())
{
if (rules.get(key).set(server.getCommandSource(), conf.getLeft().get(key)) != null)
LOG.info("[CM]: loaded setting "+key+" as "+conf.getLeft().get(key)+" from carpet.conf");
CarpetSettings.LOG.info("[CM]: loaded setting "+key+" as "+conf.getLeft().get(key)+" from "+identifier+".conf");
}
locked = conf.getRight();
}
@@ -182,14 +215,14 @@ public class SettingsManager
{
if (!rules.containsKey(fields[0]))
{
LOG.error("[CM]: Setting " + fields[0] + " is not a valid - ignoring...");
CarpetSettings.LOG.error("[CM]: "+fancyName+" Setting " + fields[0] + " is not a valid - ignoring...");
continue;
}
ParsedRule rule = rules.get(fields[0]);
if (!(rule.options.contains(fields[1])) && rule.isStrict)
{
LOG.error("[CM]: The value of " + fields[1] + " for " + fields[0] + " is not valid - ignoring...");
CarpetSettings.LOG.error("[CM]: The value of " + fields[1] + " for " + fields[0] + "("+fancyName+") is not valid - ignoring...");
continue;
}
result.put(fields[0],fields[1]);
@@ -210,35 +243,7 @@ public class SettingsManager
}
}
// stores different defaults in the file
public boolean setDefaultRule(ServerCommandSource source, String settingName, String stringValue)
{
if (locked) return false;
if (rules.containsKey(settingName))
{
Pair<Map<String, String>,Boolean> conf = readSettingsFromConf();
conf.getLeft().put(settingName, stringValue);
writeSettingsToConf(conf.getLeft()); // this may feels weird, but if conf
// is locked, it will never reach this point.
rules.get(settingName).set(source,stringValue);
return true;
}
return false;
}
// removes overrides of the default values in the file
public boolean removeDefaultRule(ServerCommandSource source, String settingName)
{
if (locked) return false;
if (rules.containsKey(settingName))
{
Pair<Map<String, String>,Boolean> conf = readSettingsFromConf();
conf.getLeft().remove(settingName);
writeSettingsToConf(conf.getLeft());
rules.get(settingName).resetToDefault(source);
return true;
}
return false;
}
public Collection<ParsedRule<?>> getRulesMatching(String search) {
String lcSearch = search.toLowerCase(Locale.ROOT);
@@ -253,7 +258,7 @@ public class SettingsManager
public int printAllRulesToLog()
{
PrintStream ps = System.out;
ps.println("# Carpet Settings");
ps.println("# "+fancyName+" Settings");
for (Map.Entry<String, ParsedRule<?>> e : new TreeMap<>(rules).entrySet())
{
ParsedRule<?> rule = e.getValue();
@@ -284,4 +289,214 @@ public class SettingsManager
return 1;
}
private ParsedRule<?> contextRule(CommandContext<ServerCommandSource> ctx) throws CommandSyntaxException
{
String ruleName = StringArgumentType.getString(ctx, "rule");
ParsedRule<?> rule = getRule(ruleName);
if (rule == null)
throw new SimpleCommandExceptionType(Messenger.c("rb Unknown rule: "+ruleName)).create();
return rule;
}
private void registerCommand(CommandDispatcher<ServerCommandSource> dispatcher)
{
if (dispatcher.getRoot().getChildren().stream().anyMatch(node -> node.getName().equalsIgnoreCase(identifier)))
{
Messenger.print_server_message(CarpetServer.minecraft_server,
Messenger.c("rb Failed to add settings command for " + identifier + ". It is masking previous command."));
return;
}
CarpetSettings.LOG.error("\n\n\n\n REGISTERIN\n\n\n\n");
LiteralArgumentBuilder<ServerCommandSource> literalargumentbuilder = literal(identifier).requires((player) ->
player.hasPermissionLevel(2) && !locked);
literalargumentbuilder.executes((context)->listAllSettings(context.getSource())).
then(literal("list").
executes( (c) -> listSettings(c.getSource(), "All "+fancyName+" Settings",
getRules())).
then(literal("defaults").
executes( (c)-> listSettings(c.getSource(),
"Current "+fancyName+" Startup Settings from "+identifier+".conf",
findStartupOverrides()))).
then(argument("tag",StringArgumentType.word()).
suggests( (c, b)->suggestMatching(getCategories(), b)).
executes( (c) -> listSettings(c.getSource(),
String.format(fancyName+" Settings matching \"%s\"", StringArgumentType.getString(c, "tag")),
getRulesMatching(StringArgumentType.getString(c, "tag")))))).
then(literal("removeDefault").
requires(s -> !locked).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(getRules().stream().map(r -> r.name), b)).
executes((c) -> removeDefault(c.getSource(), contextRule(c))))).
then(literal("setDefault").
requires(s -> !locked).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(getRules().stream().map(r -> r.name), b)).
then(argument("value", StringArgumentType.word()).
suggests((c, b)-> suggestMatching(contextRule(c).options, b)).
executes((c) -> setDefault(c.getSource(), contextRule(c), StringArgumentType.getString(c, "value")))))).
then(argument("rule", StringArgumentType.word()).
suggests( (c, b) -> suggestMatching(getRules().stream().map(r -> r.name), b)).
requires(s -> !locked ).
executes( (c) -> displayRuleMenu(c.getSource(), contextRule(c))).
then(argument("value", StringArgumentType.word()).
suggests((c, b)-> suggestMatching(contextRule(c).options,b)).
executes((c) -> setRule(c.getSource(), contextRule(c), StringArgumentType.getString(c, "value")))));
dispatcher.register(literalargumentbuilder);
}
private int displayRuleMenu(ServerCommandSource source, ParsedRule<?> rule)
{
PlayerEntity player;
try
{
player = source.getPlayer();
}
catch (CommandSyntaxException e)
{
Messenger.m(source, "w "+rule.name +" is set to: ","wb "+rule.getAsString());
return 1;
}
Messenger.m(player, "");
Messenger.m(player, "wb "+rule.name,"!/"+identifier+" "+rule.name,"^g refresh");
Messenger.m(player, "w "+rule.description);
rule.extraInfo.forEach(s -> Messenger.m(player, "g "+s));
List<BaseText> tags = new ArrayList<>();
tags.add(Messenger.c("w Tags: "));
for (String t: rule.categories)
{
tags.add(Messenger.c("c ["+t+"]", "^g list all "+t+" settings","!/"+identifier+" list "+t));
tags.add(Messenger.c("w , "));
}
tags.remove(tags.size()-1);
Messenger.m(player, tags.toArray(new Object[0]));
Messenger.m(player, "w Current value: ",String.format("%s %s (%s value)",rule.getBoolValue()?"lb":"nb", rule.getAsString(),rule.isDefault()?"default":"modified"));
List<BaseText> options = new ArrayList<>();
options.add(Messenger.c("w Options: ", "y [ "));
for (String o: rule.options)
{
options.add(makeSetRuleButton(rule, o, false));
options.add(Messenger.c("w "));
}
options.remove(options.size()-1);
options.add(Messenger.c("y ]"));
Messenger.m(player, options.toArray(new Object[0]));
return 1;
}
private int setRule(ServerCommandSource source, ParsedRule<?> rule, String newValue)
{
if (rule.set(source, newValue) != null)
Messenger.m(source, "w "+rule.toString()+", ", "c [change permanently?]",
"^w Click to keep the settings in carpet.conf to save across restarts",
"?/carpet setDefault "+rule.name+" "+rule.getAsString());
return 1;
}
// stores different defaults in the file
private int setDefault(ServerCommandSource source, ParsedRule<?> rule, String stringValue)
{
if (locked) return 0;
if (!rules.containsKey(rule.name)) return 0;
Pair<Map<String, String>,Boolean> conf = readSettingsFromConf();
conf.getLeft().put(rule.name, stringValue);
writeSettingsToConf(conf.getLeft()); // this may feels weird, but if conf
// is locked, it will never reach this point.
rule.set(source,stringValue);
Messenger.m(source ,"gi rule "+ rule.name+" will now default to "+ stringValue);
return 1;
}
// removes overrides of the default values in the file
private int removeDefault(ServerCommandSource source, ParsedRule<?> rule)
{
if (locked) return 0;
if (!rules.containsKey(rule.name)) return 0;
Pair<Map<String, String>,Boolean> conf = readSettingsFromConf();
conf.getLeft().remove(rule.name);
writeSettingsToConf(conf.getLeft());
rules.get(rule.name).resetToDefault(source);
return 1;
}
private BaseText displayInteractiveSetting(ParsedRule<?> rule)
{
List<Object> args = new ArrayList<>();
args.add("w - "+rule.name+" ");
args.add("!/"+identifier+" "+rule.name);
args.add("^y "+rule.description);
for (String option: rule.options)
{
args.add(makeSetRuleButton(rule, option, true));
args.add("w ");
}
args.remove(args.size()-1);
return Messenger.c(args.toArray(new Object[0]));
}
private BaseText makeSetRuleButton(ParsedRule<?> rule, String option, boolean brackets)
{
String style = rule.isDefault()?"g":(option.equalsIgnoreCase(rule.defaultAsString)?"e":"y");
if (option.equalsIgnoreCase(rule.getAsString()))
{
style = style + "u";
if (option.equalsIgnoreCase(rule.defaultAsString))
style = style + "b";
}
String baseText = style + (brackets ? " [" : " ") + option + (brackets ? "]" : "");
if (locked)
return Messenger.c(baseText, "^g "+fancyName+" settings are locked");
if (option.equalsIgnoreCase(rule.getAsString()))
return Messenger.c(baseText);
return Messenger.c(baseText, "^g Switch to " + option+(option.equalsIgnoreCase(rule.defaultAsString)?" (default)":""), "?/"+identifier+" " + rule.name + " " + option);
}
private int listSettings(ServerCommandSource source, String title, Collection<ParsedRule<?>> settings_list)
{
try
{
PlayerEntity player = source.getPlayer();
Messenger.m(player,String.format("wb %s:",title));
settings_list.forEach(e -> Messenger.m(player,displayInteractiveSetting(e)));
}
catch (CommandSyntaxException e)
{
Messenger.m(source, "w s:"+title);
settings_list.forEach(r -> Messenger.m(source, "w - "+ r.toString()));
}
return 1;
}
private int listAllSettings(ServerCommandSource source)
{
listSettings(source, "Current "+fancyName+" Settings", getNonDefault());
if (version != null)
Messenger.m(source, fancyName+" version: "+ version);
try
{
PlayerEntity player = source.getPlayer();
List<Object> tags = new ArrayList<>();
tags.add("w Browse Categories:\n");
for (String t : getCategories())
{
tags.add("c [" + t+"]");
tags.add("^g list all " + t + " settings");
tags.add("!/"+identifier+" list " + t);
tags.add("w ");
}
tags.remove(tags.size() - 1);
Messenger.m(player, tags.toArray(new Object[0]));
}
catch (CommandSyntaxException ignored) { }
return 1;
}
}