1 parent
5c76723091
commit
b9eee6e58b
12 files changed
+166
-26
No files matched your search
@@ -84,7 +84,7 @@ public class CarpetServer implements ClientModInitializer,DedicatedServerModInit
|
||||
public static void onServerLoadedWorlds(MinecraftServer minecraftServer)
|
||||
{
|
||||
extensions.forEach(e -> e.onServerLoadedWorlds(minecraftServer));
|
||||
scriptServer.loadAllWorldScripts();
|
||||
scriptServer.initializeForWorld();
|
||||
}
|
||||
|
||||
public static void tick(MinecraftServer server)
|
||||
|
||||
@@ -244,13 +244,13 @@ public class ScriptCommand
|
||||
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.listAvailableModules(true),bb)).
|
||||
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;
|
||||
}).
|
||||
then(literal("global").
|
||||
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;
|
||||
}
|
||||
)
|
||||
@@ -258,10 +258,10 @@ public class ScriptCommand
|
||||
);
|
||||
LiteralArgumentBuilder<ServerCommandSource> f = literal("unload").requires( (player) -> SettingsManager.canUseCommand(player, CarpetSettings.commandScriptACE) ).
|
||||
then(argument("app", StringArgumentType.word()).
|
||||
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.modules.keySet(),bb)).
|
||||
suggests( (cc, bb) -> suggestMatching(CarpetServer.scriptServer.unloadableModules,bb)).
|
||||
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;
|
||||
}));
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ public abstract class ArmorStandEntity_scarpetMarkerMixin extends LivingEntity
|
||||
@Inject(method = "readCustomDataFromTag", at = @At("HEAD"))
|
||||
private void checkScarpetMarkerUnloaded(CallbackInfo ci)
|
||||
{
|
||||
if ((CarpetSettings.scriptsAutoload || !CarpetSettings.commandScript.equals("false")) && !world.isClient)
|
||||
if (!world.isClient)
|
||||
{
|
||||
if (getScoreboardTags().contains(Auxiliary.MARKER_STRING))
|
||||
{
|
||||
|
||||
@@ -11,6 +11,7 @@ import carpet.script.value.NBTSerializableValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.settings.ParsedRule;
|
||||
import carpet.utils.Messenger;
|
||||
import net.minecraft.block.BlockState;
|
||||
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)
|
||||
{
|
||||
@@ -721,6 +741,7 @@ public class CarpetEventServer
|
||||
|
||||
public void onWorldEvent(ServerWorld world, BlockPos pos) { }
|
||||
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.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
@@ -41,17 +42,30 @@ public class CarpetScriptServer
|
||||
public final MinecraftServer server;
|
||||
public CarpetScriptHost globalHost;
|
||||
public Map<String, CarpetScriptHost> modules;
|
||||
public Set<String> unloadableModules;
|
||||
public long tickStart;
|
||||
public boolean stopAll;
|
||||
private Set<String> holyMoly;
|
||||
public CarpetEventServer events;
|
||||
|
||||
private static final List<Module> bundledModuleData = new ArrayList<>();
|
||||
private static final List<Module> ruleModuleData = new ArrayList<>();
|
||||
|
||||
public static void registerBuiltInScript(BundledModule 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
|
||||
{
|
||||
@@ -75,20 +89,27 @@ public class CarpetScriptServer
|
||||
ScriptHost.systemGlobals.clear();
|
||||
events = new CarpetEventServer(server);
|
||||
modules = new HashMap<>();
|
||||
unloadableModules = new HashSet<String>();
|
||||
tickStart = 0L;
|
||||
stopAll = false;
|
||||
holyMoly = server.getCommandManager().getDispatcher().getRoot().getChildren().stream().map(CommandNode::getName).collect(Collectors.toSet());
|
||||
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)
|
||||
{
|
||||
Messenger.m(server.getCommandSource(), "Auto-loading world scarpet apps");
|
||||
for (String moduleName: listAvailableModules(false))
|
||||
{
|
||||
addScriptHost(server.getCommandSource(), moduleName, true, true);
|
||||
addScriptHost(server.getCommandSource(), moduleName, true, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +140,18 @@ public class CarpetScriptServer
|
||||
}
|
||||
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)
|
||||
{
|
||||
@@ -152,17 +185,18 @@ public class CarpetScriptServer
|
||||
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
|
||||
name = name.toLowerCase(Locale.ROOT);
|
||||
boolean reload = false;
|
||||
if (modules.containsKey(name))
|
||||
{
|
||||
removeScriptHost(source, name, false);
|
||||
if (isRuleApp) return false;
|
||||
removeScriptHost(source, name, false, isRuleApp);
|
||||
reload = true;
|
||||
}
|
||||
Module module = getModule(name, false);
|
||||
Module module = isRuleApp ? getRuleModule(name) : getModule(name, false);
|
||||
if (module == null)
|
||||
{
|
||||
Messenger.m(source, "r Failed to add "+name+" app");
|
||||
@@ -194,18 +228,19 @@ public class CarpetScriptServer
|
||||
}
|
||||
|
||||
modules.put(name, newHost);
|
||||
if (!isRuleApp) unloadableModules.add(name);
|
||||
|
||||
if (autoload && !newHost.persistenceRequired)
|
||||
{
|
||||
removeScriptHost(source, name, false);
|
||||
removeScriptHost(source, name, false, false);
|
||||
return false;
|
||||
}
|
||||
//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;
|
||||
}
|
||||
|
||||
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);
|
||||
String loaded = isReload?"reloaded":"loaded";
|
||||
@@ -215,7 +250,7 @@ public class CarpetScriptServer
|
||||
}
|
||||
if (host.getFunction("__command") == null)
|
||||
{
|
||||
Messenger.m(source, "gi "+hostName+" app "+loaded+".");
|
||||
if (notifySource) Messenger.m(source, "gi "+hostName+" app "+loaded+".");
|
||||
return;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
if (!modules.containsKey(name))
|
||||
if (!modules.containsKey(name) || (!isRuleApp && !unloadableModules.contains(name)))
|
||||
{
|
||||
if (notifySource) Messenger.m(source, "r No such app found: ", "wb " + name);
|
||||
return false;
|
||||
@@ -320,6 +355,7 @@ public class CarpetScriptServer
|
||||
events.removeAllHostEvents(name);
|
||||
modules.get(name).onClose();
|
||||
modules.remove(name);
|
||||
if (!isRuleApp) unloadableModules.remove(name);
|
||||
CarpetServer.settingsManager.notifyPlayersCommandsChanged();
|
||||
if (notifySource) Messenger.m(source, "gi Removed "+name+" app");
|
||||
return true;
|
||||
@@ -367,9 +403,9 @@ public class CarpetScriptServer
|
||||
{
|
||||
Map<String, Boolean> apps = new HashMap<>();
|
||||
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();
|
||||
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;
|
||||
|
||||
import carpet.CarpetServer;
|
||||
import carpet.script.CarpetContext;
|
||||
import carpet.script.CarpetScriptHost;
|
||||
import carpet.script.value.ListValue;
|
||||
@@ -7,11 +8,14 @@ import carpet.script.value.MapValue;
|
||||
import carpet.script.value.NumericValue;
|
||||
import carpet.script.value.StringValue;
|
||||
import carpet.script.value.Value;
|
||||
import carpet.settings.ParsedRule;
|
||||
import carpet.settings.SettingsManager;
|
||||
import com.sun.management.OperatingSystemMXBean;
|
||||
import net.minecraft.util.WorldSavePath;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -102,6 +106,23 @@ public class SystemInfo {
|
||||
OperatingSystemMXBean.class);
|
||||
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;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import carpet.CarpetServer;
|
||||
import carpet.utils.Translations;
|
||||
import carpet.utils.Messenger;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import net.minecraft.server.command.ServerCommandSource;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
@@ -12,6 +13,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import static carpet.utils.Translations.tr;
|
||||
|
||||
@@ -19,6 +21,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
|
||||
public final Field field;
|
||||
public final String name;
|
||||
public final String description;
|
||||
public final String scarpetApp;
|
||||
public final ImmutableList<String> extraInfo;
|
||||
public final ImmutableList<String> categories;
|
||||
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 T defaultValue;
|
||||
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.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.extraInfo = ImmutableList.copyOf(rule.extra());
|
||||
this.categories = ImmutableList.copyOf(rule.category());
|
||||
this.scarpetApp = rule.scarpetApp();
|
||||
this.settingsManager = settingsManager;
|
||||
this.validators = new ArrayList<>();
|
||||
for (Class v : rule.validate())
|
||||
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));
|
||||
}
|
||||
}
|
||||
if (!scarpetApp.isEmpty())
|
||||
{
|
||||
this.validators.add((Validator<T>) callConstructor(Validator._SCARPET.class));
|
||||
}
|
||||
this.isClient = categories.contains(RuleCategory.CLIENT);
|
||||
if (this.isClient)
|
||||
{
|
||||
@@ -105,7 +116,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
|
||||
|
||||
public ParsedRule<T> set(ServerCommandSource source, String value)
|
||||
{
|
||||
if (CarpetServer.settingsManager != null && CarpetServer.settingsManager.locked)
|
||||
if (settingsManager != null && settingsManager.locked)
|
||||
return null;
|
||||
if (type == String.class)
|
||||
{
|
||||
@@ -156,7 +167,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
|
||||
if (!value.equals(get()) || source == null)
|
||||
{
|
||||
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)
|
||||
@@ -187,7 +198,7 @@ public final class ParsedRule<T> implements Comparable<ParsedRule> {
|
||||
public boolean getBoolValue()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,14 @@ public @interface Rule
|
||||
* For enums, its always strict, same for booleans - no need to set that for them.
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -43,6 +43,7 @@ import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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.server.command.CommandManager.argument;
|
||||
import static net.minecraft.server.command.CommandManager.literal;
|
||||
@@ -71,7 +72,10 @@ public class SettingsManager
|
||||
this.fancyName = fancyName;
|
||||
}
|
||||
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void attachServer(MinecraftServer server)
|
||||
{
|
||||
this.server = server;
|
||||
@@ -90,7 +94,7 @@ public class SettingsManager
|
||||
{
|
||||
Rule rule = f.getAnnotation(Rule.class);
|
||||
if (rule == null) continue;
|
||||
ParsedRule parsed = new ParsedRule(f, rule);
|
||||
ParsedRule parsed = new ParsedRule(f, rule, this);
|
||||
rules.put(parsed.name, parsed);
|
||||
}
|
||||
}
|
||||
@@ -104,6 +108,30 @@ public class SettingsManager
|
||||
{
|
||||
observers.forEach(observer -> observer.accept(source, rule, userTypedValue));
|
||||
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()
|
||||
|
||||
@@ -57,6 +57,17 @@ public abstract class Validator<T>
|
||||
}
|
||||
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>
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user