Skip to content

Commit

Permalink
flag_map and __raw set
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Feb 11, 2022
1 parent 7240a33 commit ec96f65
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 34 deletions.
Expand Up @@ -12,13 +12,21 @@

public abstract class AbstractFlagTracker {

public abstract MapTag getRootMap(String key);

public abstract void setRootMap(String key, MapTag map);

public abstract ObjectTag getFlagValue(String key);

public abstract TimeTag getFlagExpirationTime(String key);

public abstract Collection<String> listAllFlags();

public abstract void setFlag(String key, ObjectTag value, TimeTag expiration);
public void setFlag(String key, ObjectTag value, TimeTag expiration) {
setFlag(key, value, expiration, true);
}

public abstract void setFlag(String key, ObjectTag value, TimeTag expiration, boolean doFlaggify);

public boolean hasFlag(String key) {
return getFlagValue(key) != null;
Expand Down Expand Up @@ -94,11 +102,13 @@ public static <T extends FlaggableObject> void registerFlagHandlers(ObjectTagPro
});

// <--[tag]
// @attribute <FlaggableObject.flag_map>
// @attribute <FlaggableObject.flag_map[<name>|...]>
// @returns MapTag
// @description
// Returns a raw map of the objects internal flag data.
// Note that this is exclusively for debug/testing reasons, and should never be used in a real script.
// Returns a raw map of the objects internal flag data for the flags with the given flag name. Names must be root names (no '.').
// Output is a MapTag wherein each key is a flag name, and each value is a MapTag, containing keys '__value' and '__expiration', where '__value' contains the real object value.
// Output also may contain key '__clear', which is a ListTag of flags that were listed in input but weren't present in output.
// Using this without a parameter to get ALL flags is allowed exclusively for debug/testing reasons, and should never be used in a real script.
// See <@link language flag system>.
// -->
processor.registerTag(MapTag.class, "flag_map", (attribute, object) -> {
Expand Down Expand Up @@ -162,13 +172,30 @@ public ListTag doListFlagsTag(Attribute attribute) {
public MapTag getFlagMap() {
MapTag result = new MapTag();
for (String key : listAllFlags()) {
result.putObject(key, getFlagValue(key));
result.putObject(key, getRootMap(key));
}
return result;
}

public MapTag doFlagMapTag(Attribute attribute) {
listFlagsTagWarning.warn(attribute.context);
return getFlagMap();
if (!attribute.hasParam()) {
listFlagsTagWarning.warn(attribute.context);
return getFlagMap();
}
MapTag result = new MapTag();
ListTag clear = new ListTag();
for (String key : attribute.paramAsType(ListTag.class)) {
MapTag map = getRootMap(key);
if (map != null) {
result.putObject(key, map);
}
else {
clear.addObject(new ElementTag(key, true));
}
}
if (!clear.isEmpty()) {
result.putObject("__clear", clear);
}
return result;
}
}
Expand Up @@ -2,7 +2,6 @@

import com.denizenscript.denizencore.DenizenCore;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.MapTag;
import com.denizenscript.denizencore.objects.core.TimeTag;
import com.denizenscript.denizencore.utilities.CoreUtilities;
Expand All @@ -20,10 +19,6 @@ public abstract class MapTagBasedFlagTracker extends AbstractFlagTracker {

public static boolean skipAllCleanings = false;

public abstract MapTag getRootMap(String key);

public abstract void setRootMap(String key, MapTag map);

public static boolean isExpired(ObjectTag expirationObj) {
if (expirationObj == null) {
return false;
Expand Down Expand Up @@ -157,7 +152,7 @@ public MapTag flaggifyMapTag(MapTag map) {
}

@Override
public void setFlag(String key, ObjectTag value, TimeTag expiration) {
public void setFlag(String key, ObjectTag value, TimeTag expiration, boolean doFlaggify) {
List<String> splitKey = CoreUtilities.split(key, '.');
if (value == null && splitKey.size() == 1) {
setRootMap(key, null);
Expand Down Expand Up @@ -191,19 +186,22 @@ public void setFlag(String key, ObjectTag value, TimeTag expiration) {
setRootMap(splitKey.get(0), rootMap);
}
else {
MapTag resultMap = new MapTag();
if (value instanceof MapTag) {
value = flaggifyMapTag((MapTag) value);
}
else if (value instanceof ElementTag && value.toString().startsWith("map@")) {
MapTag mappified = MapTag.valueOf(value.toString(), CoreUtilities.noDebugContext);
if (mappified != null) {
value = flaggifyMapTag(mappified);
}
MapTag resultMap;
if (value instanceof MapTag && !doFlaggify) {
resultMap = (MapTag) value;
}
resultMap.map.put(valueString, value);
if (expiration != null) {
resultMap.map.put(expirationString, expiration);
else {
resultMap = new MapTag();
if (value.shouldBeType(MapTag.class)) {
MapTag mappified = value.asType(MapTag.class, CoreUtilities.noDebugContext);
if (mappified != null) {
value = flaggifyMapTag(mappified);
}
}
resultMap.map.put(valueString, value);
if (expiration != null) {
resultMap.map.put(expirationString, expiration);
}
}
if (splitKey.size() != 1) {
map.putObject(endKey, resultMap);
Expand Down
Expand Up @@ -3,9 +3,11 @@
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.MapTag;
import com.denizenscript.denizencore.objects.core.TimeTag;
import com.denizenscript.denizencore.utilities.CoreUtilities;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class RedirectionFlagTracker extends AbstractFlagTracker {

Expand All @@ -18,6 +20,32 @@ public RedirectionFlagTracker(AbstractFlagTracker original, String prefix) {

public String prefix;

@Override
public MapTag getRootMap(String key) {
List<String> parts = CoreUtilities.split(prefix, '.');
parts.add(key);
MapTag target = original.getRootMap(parts.get(0));
if (target == null) {
return null;
}
for (int i = 1; i < parts.size(); i++) {
target = (MapTag) target.map.get(MapTagBasedFlagTracker.valueString);
if (target == null) {
return null;
}
target = (MapTag) target.getObject(parts.get(i));
if (target == null) {
return null;
}
}
return target;
}

@Override
public void setRootMap(String key, MapTag map) {
original.setFlag(prefix + "." + key, map, null, false);
}

@Override
public ObjectTag getFlagValue(String key) {
return original.getFlagValue(prefix + "." + key);
Expand All @@ -38,8 +66,8 @@ public Collection<String> listAllFlags() {
}

@Override
public void setFlag(String key, ObjectTag value, TimeTag expiration) {
original.setFlag(prefix + "." + key, value, expiration);
public void setFlag(String key, ObjectTag value, TimeTag expiration, boolean doFlaggify) {
original.setFlag(prefix + "." + key, value, expiration, doFlaggify);
}

@Override
Expand Down
Expand Up @@ -6,17 +6,17 @@
import com.denizenscript.denizencore.flags.FlaggableObject;
import com.denizenscript.denizencore.objects.Argument;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.DurationTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
import com.denizenscript.denizencore.objects.core.ListTag;
import com.denizenscript.denizencore.objects.core.TimeTag;
import com.denizenscript.denizencore.objects.core.*;
import com.denizenscript.denizencore.scripts.ScriptEntry;
import com.denizenscript.denizencore.scripts.commands.AbstractCommand;
import com.denizenscript.denizencore.utilities.CoreUtilities;
import com.denizenscript.denizencore.utilities.data.ActionableDataProvider;
import com.denizenscript.denizencore.utilities.data.DataAction;
import com.denizenscript.denizencore.utilities.data.DataActionHelper;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizencore.utilities.text.StringHolder;

import java.util.Map;

public class FlagCommand extends AbstractCommand {

Expand All @@ -27,6 +27,7 @@ public FlagCommand() {
isProcedural = false;
allowedDynamicPrefixes = true;
}

// <--[language]
// @name Flag System
// @group Denizen Scripting Language
Expand Down Expand Up @@ -57,9 +58,11 @@ public FlagCommand() {
// Item flags can also be used as a requirement in <@link command take>.
//
// Note that some internal flags exist, and are prefixed with '__' to avoid conflict with normal user flags.
// This includes '__scripts' which is where script flags are stored inside of server flags,
// and '__interact_step' which is used for interact script steps, related to <@link command zap>,
// and '__interact_cooldown' which is used for interact script cooldowns, related to <@link command cooldown>.
// This includes:
// - '__raw' and '__clear' which are part of a fake-flag system used for forcibly setting raw data to a flaggable object,
// - '__scripts', '__time', etc. which is where some object-type flags are stored inside of server flags,
// - '__interact_step' which is used for interact script steps, related to <@link command zap>,
// - '__interact_cooldown' which is used for interact script cooldowns, related to <@link command cooldown>.
//
// Flags have an expiration system, which is used by specifying a time at which they should expire (or via a duration which internally calculates the date/time of expiration by adding the duration input to the current date/time).
// Expirations are then *checked for* in flag tags - meaning, the flag tags will internally compare a stored date/time against the real current date/time,
Expand All @@ -68,6 +71,15 @@ public FlagCommand() {
// In other words, it is correct to say a flag "is expired" or a flag "is not expired",
// but it is incorrect to say a flag "expires", as it is not an active action (those this wording can be convenient when speaking informally).
// Expired flags are sometimes 'cleaned up' (meaning, any expired flags get actually removed from internal storage), usually when a flag save file is loaded into the server.
//
// As a bonus feature-combo, it is possible to transmit sets of flags exactly in-place and reapply them, this is particular useful for example to synchronize player data across Bungee servers.
// To do this, you can read raw flag data with the tag <@link tag FlaggableObject.flag_map> and the '__raw' prefix in a flag command. For example:
// <code>
// # Gather the original data
// - define playerdata <player.flag[flag1|flag2|taco|potato|waffle|etc]>
// # Now reapply it elsewhere (eg a different Bungee server)
// - flag <player> __raw:<[playerdata]>
// </code>
// -->

// <--[command]
Expand Down Expand Up @@ -198,6 +210,23 @@ public ObjectTag getValueAt(String keyName) {

@Override
public void setValueAt(String keyName, ObjectTag value) {
if (keyName.equals("__raw")) {
MapTag toSetMap = (MapTag) value;
ObjectTag toClear = toSetMap.getObject("__clear");
if (toClear != null) {
for (String key : toClear.asType(ListTag.class, CoreUtilities.noDebugContext)) {
if (toSetMap.getObject(key) == null) {
tracker.setRootMap(key, null);
}
}
}
for (Map.Entry<StringHolder, ObjectTag> mapData : toSetMap.map.entrySet()) {
if (!mapData.getKey().low.equals("__clear")) {
tracker.setRootMap(mapData.getKey().str, (MapTag) mapData.getValue());
}
}
return;
}
if (keyName.startsWith("__")) {
Debug.echoError("Assigning flag value to reserved '__' namespace (key: '" + keyName + "')");
}
Expand Down

0 comments on commit ec96f65

Please sign in to comment.