Allow rules to manage Scarpet apps (Scarpet Rules) (#519)

by altrisi
This commit is contained in:
altrisi authored and GitHub committed 2020-11-02 21:52:21 -04:00
1 parent 5c76723091
commit b9eee6e58b
12 files changed
+165 -25

No files matched your search

+1
View File
@@ -469,6 +469,7 @@ Available options in the scarpet app space:
* `world_seed` - a numeric seed of the world * `world_seed` - a numeric seed of the world
* `world_path` - full path to the world saves folder * `world_path` - full path to the world saves folder
* `world_folder` - name of the direct folder in the saves that holds world files * `world_folder` - name of the direct folder in the saves that holds world files
* `world_carpet_rules` - returns all Carpet rules in a map form (`rule`->`value`). Includes rules from extensions with their namespace (`namespace:rule`->`value`). You can later listen to rule changes with the `on_carpet_rule_change(rule, newValue)` event.
Relevant gameplay related properties Relevant gameplay related properties
* `game_difficulty` - current difficulty of the game: `'peacefu'`, `'easy'`, `'normal'`, or `'hard'` * `game_difficulty` - current difficulty of the game: `'peacefu'`, `'easy'`, `'normal'`, or `'hard'`
+3
View File
@@ -44,6 +44,9 @@ at the same time.
Triggered right after a lightning strikes. Lightning entity as well as potential horseman trap would Triggered right after a lightning strikes. Lightning entity as well as potential horseman trap would
already be spawned at that point. `mode` is `true` if the lightning did cause a trap to spawn. already be spawned at that point. `mode` is `true` if the lightning did cause a trap to spawn.
### `__on_carpet_rule_changes(rule, new_value)`
Triggered when a Carpet rule is changed. It includes extension rules, which will be namespaced as `namespace:rule`.
## Player events ## Player events
These are triggered with a player context. For apps with a 'player' scope, they trigger once for the appropriate These are triggered with a player context. For apps with a 'player' scope, they trigger once for the appropriate
+1 -1
View File
@@ -84,7 +84,7 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit
public static void onServerLoadedWorlds(MinecraftServer minecraftServer) public static void onServerLoadedWorlds(MinecraftServer minecraftServer)
{ {
extensions.forEach(e -> e.onServerLoadedWorlds(minecraftServer)); extensions.forEach(e -> e.onServerLoadedWorlds(minecraftServer));
scriptServer.loadAllWorldScripts(); scriptServer.initializeForWorld();
} }
public static void tick(MinecraftServer server) public static void tick(MinecraftServer server)
@@ -244,13 +244,13 @@ public class ScriptCommand
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.listAvailableModules(true),bb)). suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.listAvailableModules(true),bb)).
executes((cc) -> executes((cc) ->
{ {
boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), true, false); boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), true, false, false);
return success?1:0; return success?1:0;
}). }).
then(literal("global"). then(literal("global").
executes((cc) -> executes((cc) ->
{ {
boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), false, false); boolean success = CarpetServer.scriptServer.addScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), false, false, false);
return success?1:0; return success?1:0;
} }
) )
@@ -258,10 +258,10 @@ public class ScriptCommand
); );
LiteralArgumentBuilder<ServerCommandSource> f = literal("unload").requires( (player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandScriptACE) ). LiteralArgumentBuilder<ServerCommandSource> f = literal("unload").requires( (player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandScriptACE) ).
then(argument("app", StringArgumentType.word()). then(argument("app", StringArgumentType.word()).
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.modules.keySet(),bb)). suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.unloadableModules,bb)).
executes((cc) -> executes((cc) ->
{ {
boolean success =CarpetServer.scriptServer.removeScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), true); boolean success =CarpetServer.scriptServer.removeScriptHost(cc.getSource(), StringArgumentType.getString(cc, "app"), true, false);
return success?1:0; return success?1:0;
})); }));
@@ -30,7 +30,7 @@ public abstract class ArmorStandEntity_scarpetMarkerMixin extends LivingEntity
@Inject(method = "readCustomDataFromTag", at = @At("HEAD")) @Inject(method = "readCustomDataFromTag", at = @At("HEAD"))
private void checkScarpetMarkerUnloaded(CallbackInfo ci) private void checkScarpetMarkerUnloaded(CallbackInfo ci)
{ {
if ((CarpetSettings.scriptsAutoload || !CarpetSettings.commandScript.equals("false")) && !world.isClient) if (!world.isClient)
{ {
if (getScoreboardTags().contains(Auxiliary.MARKER_STRING)) if (getScoreboardTags().contains(Auxiliary.MARKER_STRING))
{ {
@@ -11,6 +11,7 @@ import carpet.script.value.NBTSerializableValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.settings.ParsedRule;
import carpet.utils.Messenger; import carpet.utils.Messenger;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
@@ -653,6 +654,25 @@ public class CarpetEventServer
); );
} }
}; };
public static final Event CARPET_RULE_CHANGES = new Event("carpet_rule_changes", 2, true)
{
@Override
public void onCarpetRuleChanges(ParsedRule<?> rule, ServerCommandSource source)
{
String identifier = rule.settingsManager.getIdentifier();
final String namespace;
if (!identifier.equals("carpet"))
{
namespace = identifier+":";
} else { namespace = "";}
handler.call(
() -> Arrays.asList(
new StringValue(namespace+rule.name),
new StringValue(rule.getAsString())
), () -> source
);
}
};
public static String getLoadEvent(EntityType<? extends Entity> et) public static String getLoadEvent(EntityType<? extends Entity> et)
{ {
@@ -721,6 +741,7 @@ public class CarpetEventServer
public void onWorldEvent(ServerWorld world, BlockPos pos) { } public void onWorldEvent(ServerWorld world, BlockPos pos) { }
public void onWorldEventFlag(ServerWorld world, BlockPos pos, int flag) { } public void onWorldEventFlag(ServerWorld world, BlockPos pos, int flag) { }
public void onCarpetRuleChanges(ParsedRule<?> rule, ServerCommandSource source) { }
} }
@@ -26,6 +26,7 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@@ -41,18 +42,31 @@ public class CarpetScriptServer
public final MinecraftServer server; public final MinecraftServer server;
public CarpetScriptHost globalHost; public CarpetScriptHost globalHost;
public Map<String, CarpetScriptHost> modules; public Map<String, CarpetScriptHost> modules;
public Set<String> unloadableModules;
public long tickStart; public long tickStart;
public boolean stopAll; public boolean stopAll;
private Set<String> holyMoly; private Set<String> holyMoly;
public CarpetEventServer events; public CarpetEventServer events;
private static final List<Module> bundledModuleData = new ArrayList<>(); private static final List<Module> bundledModuleData = new ArrayList<>();
private static final List<Module> ruleModuleData = new ArrayList<>();
public static void registerBuiltInScript(BundledModule app) public static void registerBuiltInScript(BundledModule app)
{ {
bundledModuleData.add(app); bundledModuleData.add(app);
} }
/**
* Registers a Scarpet App to be used as a Rule App
* (to be controlled with the value of a Carpet rule)
*
* @param app is the BundledModule of an app. Libraries
* should be registered as builtInScripts instead
*/
public static void registerRuleScript(BundledModule app) {
ruleModuleData.add(app);
}
static static
{ {
registerBuiltInScript(BundledModule.carpetNative("camera", false)); registerBuiltInScript(BundledModule.carpetNative("camera", false));
@@ -75,20 +89,27 @@ public class CarpetScriptServer
ScriptHost.systemGlobals.clear(); ScriptHost.systemGlobals.clear();
events = new CarpetEventServer(server); events = new CarpetEventServer(server);
modules = new HashMap<>(); modules = new HashMap<>();
unloadableModules = new HashSet<String>();
tickStart = 0L; tickStart = 0L;
stopAll = false; stopAll = false;
holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet()); holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet());
globalHost = CarpetScriptHost.create(this, null, false, null); globalHost = CarpetScriptHost.create(this, null, false, null);
} }
public void loadAllWorldScripts() public void initializeForWorld()
{ {
CarpetServer.settingsManager.initializeScarpetRules();
CarpetServer.extensions.forEach(e -> {
if (e.customSettingsManager() != null) {
e.customSettingsManager().initializeScarpetRules();
}
});
if (CarpetSettings.scriptsAutoload) if (CarpetSettings.scriptsAutoload)
{ {
Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps"); Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps");
for (String moduleName: listAvailableModules(false)) for (String moduleName: listAvailableModules(false))
{ {
addScriptHost(server.getCommandSource(), moduleName, true, true); addScriptHost(server.getCommandSource(), moduleName, true, true, false);
} }
} }
@@ -120,6 +141,18 @@ public class CarpetScriptServer
return null; return null;
} }
public Module getRuleModule(String name)
{
for (Module moduleData : ruleModuleData)
{
if (moduleData.getName().equalsIgnoreCase(name))
{
return moduleData;
}
}
return null;
}
public List<String> listAvailableModules(boolean includeBuiltIns) public List<String> listAvailableModules(boolean includeBuiltIns)
{ {
List<String> moduleNames = new ArrayList<>(); List<String> moduleNames = new ArrayList<>();
@@ -152,17 +185,18 @@ public class CarpetScriptServer
return modules.get(name); return modules.get(name);
} }
public boolean addScriptHost(ServerCommandSource source, String name, boolean perPlayer, boolean autoload) public boolean addScriptHost(ServerCommandSource source, String name, boolean perPlayer, boolean autoload, boolean isRuleApp)
{ {
//TODO add per player modules to support player actions better on a server //TODO add per player modules to support player actions better on a server
name = name.toLowerCase(Locale.ROOT); name = name.toLowerCase(Locale.ROOT);
boolean reload = false; boolean reload = false;
if (modules.containsKey(name)) if (modules.containsKey(name))
{ {
removeScriptHost(source, name, false); if (isRuleApp) return false;
removeScriptHost(source, name, false, isRuleApp);
reload = true; reload = true;
} }
Module module = getModule(name, false); Module module = isRuleApp ? getRuleModule(name) : getModule(name, false);
if (module == null) if (module == null)
{ {
Messenger.m(source, "r Failed to add "+name+" app"); Messenger.m(source, "r Failed to add "+name+" app");
@@ -194,18 +228,19 @@ public class CarpetScriptServer
} }
modules.put(name, newHost); modules.put(name, newHost);
if (!isRuleApp) unloadableModules.add(name);
if (autoload && !newHost.persistenceRequired) if (autoload && !newHost.persistenceRequired)
{ {
removeScriptHost(source, name, false); removeScriptHost(source, name, false, false);
return false; return false;
} }
//addEvents(source, name); //addEvents(source, name);
addLegacyCommand(source, name, reload); // this needs to be moved to config reader, only supporting legacy command here addLegacyCommand(source, name, reload, !isRuleApp); // this needs to be moved to config reader, only supporting legacy command here
return true; return true;
} }
private void addLegacyCommand(ServerCommandSource source, String hostName, boolean isReload) private void addLegacyCommand(ServerCommandSource source, String hostName, boolean isReload, boolean notifySource)
{ {
CarpetScriptHost host = modules.get(hostName); CarpetScriptHost host = modules.get(hostName);
String loaded = isReload?"reloaded":"loaded"; String loaded = isReload?"reloaded":"loaded";
@@ -215,7 +250,7 @@ public class CarpetScriptServer
} }
if (host.getFunction("__command") == null) if (host.getFunction("__command") == null)
{ {
Messenger.m(source, "gi "+hostName+" app "+loaded+"."); if (notifySource) Messenger.m(source, "gi "+hostName+" app "+loaded+".");
return; return;
} }
if (holyMoly.contains(hostName)) if (holyMoly.contains(hostName))
@@ -261,7 +296,7 @@ public class CarpetScriptServer
}))); })));
} }
} }
Messenger.m(source, "gi "+hostName+" app "+loaded+" with /"+hostName+" command"); if (notifySource) Messenger.m(source, "gi "+hostName+" app "+loaded+" with /"+hostName+" command");
server.getCommandManager().getDispatcher().register(command); server.getCommandManager().getDispatcher().register(command);
CarpetServer.settingsManager.notifyPlayersCommandsChanged(); CarpetServer.settingsManager.notifyPlayersCommandsChanged();
} }
@@ -308,10 +343,10 @@ public class CarpetScriptServer
public boolean removeScriptHost(ServerCommandSource source, String name, boolean notifySource) public boolean removeScriptHost(ServerCommandSource source, String name, boolean notifySource, boolean isRuleApp)
{ {
name = name.toLowerCase(Locale.ROOT); name = name.toLowerCase(Locale.ROOT);
if (!modules.containsKey(name)) if (!modules.containsKey(name) || (!isRuleApp && !unloadableModules.contains(name)))
{ {
if (notifySource) Messenger.m(source, "r No such app found: ", "wb " + name); if (notifySource) Messenger.m(source, "r No such app found: ", "wb " + name);
return false; return false;
@@ -320,6 +355,7 @@ public class CarpetScriptServer
events.removeAllHostEvents(name); events.removeAllHostEvents(name);
modules.get(name).onClose(); modules.get(name).onClose();
modules.remove(name); modules.remove(name);
if (!isRuleApp) unloadableModules.remove(name);
CarpetServer.settingsManager.notifyPlayersCommandsChanged(); CarpetServer.settingsManager.notifyPlayersCommandsChanged();
if (notifySource) Messenger.m(source, "gi Removed "+name+" app"); if (notifySource) Messenger.m(source, "gi Removed "+name+" app");
return true; return true;
@@ -367,9 +403,9 @@ public class CarpetScriptServer
{ {
Map<String, Boolean> apps = new HashMap<>(); Map<String, Boolean> apps = new HashMap<>();
modules.forEach((s, h) -> apps.put(s, h.perUser)); modules.forEach((s, h) -> apps.put(s, h.perUser));
apps.keySet().forEach(s -> removeScriptHost(server.getCommandSource(), s, false)); apps.keySet().forEach(s -> removeScriptHost(server.getCommandSource(), s, false, false));
events.clearAll(); events.clearAll();
init(); init();
apps.forEach((s, pp) -> addScriptHost(server.getCommandSource(), s, pp, false)); apps.forEach((s, pp) -> addScriptHost(server.getCommandSource(), s, pp, false, false));
} }
} }
@@ -1,5 +1,6 @@
package carpet.script.utils; package carpet.script.utils;
import carpet.CarpetServer;
import carpet.script.CarpetContext; import carpet.script.CarpetContext;
import carpet.script.CarpetScriptHost; import carpet.script.CarpetScriptHost;
import carpet.script.value.ListValue; import carpet.script.value.ListValue;
@@ -7,11 +8,14 @@ import carpet.script.value.MapValue;
import carpet.script.value.NumericValue; import carpet.script.value.NumericValue;
import carpet.script.value.StringValue; import carpet.script.value.StringValue;
import carpet.script.value.Value; import carpet.script.value.Value;
import carpet.settings.ParsedRule;
import carpet.settings.SettingsManager;
import com.sun.management.OperatingSystemMXBean; import com.sun.management.OperatingSystemMXBean;
import net.minecraft.util.WorldSavePath; import net.minecraft.util.WorldSavePath;
import java.lang.management.ManagementFactory; import java.lang.management.ManagementFactory;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -102,6 +106,23 @@ public class SystemInfo {
OperatingSystemMXBean.class); OperatingSystemMXBean.class);
return new NumericValue(osBean.getProcessCpuLoad()); return new NumericValue(osBean.getProcessCpuLoad());
}); });
put("world_carpet_rules", c -> {
Collection<ParsedRule<?>> rules = CarpetServer.settingsManager.getRules();
MapValue carpetRules = new MapValue(Collections.emptyList());
rules.forEach(rule -> {
carpetRules.put(new StringValue(rule.name), new StringValue(rule.getAsString()));
});
CarpetServer.extensions.forEach(e -> {
SettingsManager manager = e.customSettingsManager();
if (manager == null) return;
Collection<ParsedRule<?>> extensionRules = manager.getRules();
extensionRules.forEach(rule -> {
carpetRules.put(new StringValue(manager.getIdentifier()+":"+rule.name), new StringValue(rule.getAsString()));
});
});
return carpetRules;
});
+15 -4
View File
@@ -4,6 +4,7 @@ import carpet.CarpetServer;
import carpet.utils.Translations; import carpet.utils.Translations;
import carpet.utils.Messenger; import carpet.utils.Messenger;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
@@ -12,6 +13,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set;
import static carpet.utils.Translations.tr; import static carpet.utils.Translations.tr;
@@ -19,6 +21,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
public final Field field; public final Field field;
public final String name; public final String name;
public final String description; public final String description;
public final String scarpetApp;
public final ImmutableList<String> extraInfo; public final ImmutableList<String> extraInfo;
public final ImmutableList<String> categories; public final ImmutableList<String> categories;
public final ImmutableList<String> options; public final ImmutableList<String> options;
@@ -28,8 +31,10 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
public final List<Validator<T>> validators; public final List<Validator<T>> validators;
public final T defaultValue; public final T defaultValue;
public final String defaultAsString; public final String defaultAsString;
public final SettingsManager settingsManager;
private static final Set<Class<?>> NUMBER_CLASSES = Sets.newHashSet(byte.class, short.class, int.class, long.class, float.class, double.class);
ParsedRule(Field field, Rule rule) ParsedRule(Field field, Rule rule, SettingsManager settingsManager)
{ {
this.field = field; this.field = field;
this.name = rule.name().isEmpty() ? field.getName() : rule.name(); this.name = rule.name().isEmpty() ? field.getName() : rule.name();
@@ -38,6 +43,8 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
this.isStrict = rule.strict(); this.isStrict = rule.strict();
this.extraInfo = ImmutableList.copyOf(rule.extra()); this.extraInfo = ImmutableList.copyOf(rule.extra());
this.categories = ImmutableList.copyOf(rule.category()); this.categories = ImmutableList.copyOf(rule.category());
this.scarpetApp = rule.scarpetApp();
this.settingsManager = settingsManager;
this.validators = new ArrayList<>(); this.validators = new ArrayList<>();
for (Class v : rule.validate()) for (Class v : rule.validate())
this.validators.add((Validator<T>) callConstructor(v)); this.validators.add((Validator<T>) callConstructor(v));
@@ -50,6 +57,10 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
this.validators.add((Validator<T>) callConstructor(Validator._COMMAND_LEVEL_VALIDATOR.class)); this.validators.add((Validator<T>) callConstructor(Validator._COMMAND_LEVEL_VALIDATOR.class));
} }
} }
if (!scarpetApp.isEmpty())
{
this.validators.add((Validator<T>) callConstructor(Validator._SCARPET.class));
}
this.isClient = categories.contains(RuleCategory.CLIENT); this.isClient = categories.contains(RuleCategory.CLIENT);
if (this.isClient) if (this.isClient)
{ {
@@ -105,7 +116,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
public ParsedRule<T> set(ServerCommandSource source, String value) public ParsedRule<T> set(ServerCommandSource source, String value)
{ {
if (CarpetServer.settingsManager != null && CarpetServer.settingsManager.locked) if (settingsManager != null && settingsManager.locked)
return null; return null;
if (type == String.class) if (type == String.class)
{ {
@@ -156,7 +167,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
if (!value.equals(get()) || source == null) if (!value.equals(get()) || source == null)
{ {
this.field.set(null, value); this.field.set(null, value);
if (source != null) CarpetServer.settingsManager.notifyRuleChanged(source, this, stringValue); if (source != null) settingsManager.notifyRuleChanged(source, this, stringValue);
} }
} }
catch (IllegalAccessException e) catch (IllegalAccessException e)
@@ -187,7 +198,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
public boolean getBoolValue() public boolean getBoolValue()
{ {
if (type == boolean.class) return (Boolean) get(); if (type == boolean.class) return (Boolean) get();
if (type.isAssignableFrom(Number.class)) return ((Number) get()).doubleValue() > 0; if (NUMBER_CLASSES.contains(type)) return ((Number) get()).doubleValue() > 0;
return false; return false;
} }
+8
View File
@@ -52,6 +52,14 @@ public @interface Rule
*/ */
boolean strict() default true; boolean strict() default true;
/**
* If specified, the rule will automatically enable or disable
* a builtin Scarpet Rule App with this name.
* Consider telling the rule name so users can edit globals
* (in case there are relevant globals to edit ofc)
*/
String scarpetApp() default "";
/** /**
* The class of the validator checked when the rule is changed. * The class of the validator checked when the rule is changed.
*/ */
@@ -43,6 +43,7 @@ import java.util.TreeMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static carpet.utils.Translations.tr; import static carpet.utils.Translations.tr;
import static carpet.script.CarpetEventServer.Event.CARPET_RULE_CHANGES;
import static net.minecraft.command.CommandSource.suggestMatching; import static net.minecraft.command.CommandSource.suggestMatching;
import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal; import static net.minecraft.server.command.CommandManager.literal;
@@ -71,6 +72,9 @@ public class SettingsManager
this.fancyName = fancyName; this.fancyName = fancyName;
} }
public String getIdentifier() {
return identifier;
}
public void attachServer(MinecraftServer server) public void attachServer(MinecraftServer server)
{ {
@@ -90,7 +94,7 @@ public class SettingsManager
{ {
Rule rule = f.getAnnotation(Rule.class); Rule rule = f.getAnnotation(Rule.class);
if (rule == null) continue; if (rule == null) continue;
ParsedRule parsed = new ParsedRule(f, rule); ParsedRule parsed = new ParsedRule(f, rule, this);
rules.put(parsed.name, parsed); rules.put(parsed.name, parsed);
} }
} }
@@ -104,6 +108,30 @@ public class SettingsManager
{ {
observers.forEach(observer -> observer.accept(source, rule, userTypedValue)); observers.forEach(observer -> observer.accept(source, rule, userTypedValue));
ServerNetworkHandler.updateRuleWithConnectedClients(rule); ServerNetworkHandler.updateRuleWithConnectedClients(rule);
switchScarpetRule(source, rule);
CARPET_RULE_CHANGES.onCarpetRuleChanges(rule, source);
}
void switchScarpetRule(ServerCommandSource source, ParsedRule<?> rule)
{
if (!rule.scarpetApp.isEmpty())
{
if (rule.getBoolValue() || (rule.type == String.class && !rule.get().equals("false")))
{
CarpetServer.scriptServer.addScriptHost(source, rule.scarpetApp, false, false, true);
} else {
CarpetServer.scriptServer.removeScriptHost(source, rule.scarpetApp, false, true);
}
}
}
public void initializeScarpetRules() {
for (ParsedRule<?> rule : rules.values())
{
if (!rule.scarpetApp.isEmpty()) {
switchScarpetRule(server.getCommandSource(), rule);
}
}
} }
public Iterable<String> getCategories() public Iterable<String> getCategories()
@@ -58,6 +58,17 @@ public abstract class Validator<T>
public String description() { return "Can be limited to 'ops' only, or a custom permission level";} public String description() { return "Can be limited to 'ops' only, or a custom permission level";}
} }
public static class _SCARPET<T> extends Validator<T> {
@Override
public T validate(ServerCommandSource source, ParsedRule<T> currentRule, T newValue, String string)
{
return newValue;
}
public String description() {
return "It controls an accompanying Scarpet App";
}
}
public static class WIP<T> extends Validator<T> public static class WIP<T> extends Validator<T>
{ {
@Override @Override