Skip to content

Commit

Permalink
(initial) data action system, define command support
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmonkey4eva committed Jun 12, 2019
1 parent 37db2da commit 8dafa00
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 25 deletions.
5 changes: 5 additions & 0 deletions src/main/java/net/aufdemrand/denizencore/objects/dList.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ public void addObject(int index, dObject obj) {
super.add(index, obj.toString());
}

public void setObject(int index, dObject obj) {
objectForms.set(index, obj);
super.set(index, obj.toString());
}

public dObject getObject(int id) {
return objectForms.get(id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,46 +253,43 @@ public void registerCoreCommands() {

// <--[command]
// @Name Define
// @Syntax define [<id>] [<value>]
// @Syntax define [<id>](:<action>)[:<value>]
// @Required 1
// @Short Creates a temporary variable inside a script queue.
// @Group core

// @Description
// Definitions are queue-level (or script-level) 'variables' that can be used throughout a script, once
// defined, by using the <def[<id>]> tag. Definitions are only valid on the current queue and are
// defined, by using the <[<id>]> tag. Definitions are only valid on the current queue and are
// not transferred to any new queues constructed within the script, such as a 'run' command, without explicitly
// specifying to do so.
//
// Definitions are lighter and faster than creating a temporary flag, but unlike flags, are only a single entry,
// that is, you can't add or remove from the definition, but you can re-create it if you wish to specify a new
// value. Definitions are also automatically removed when the queue is completed, so there is no worry for
// leaving unused data hanging around.

//
// Refer to <@link language data actions>
//
// @Tags
// <def[<id>]> to get the value assigned to an ID

// <[<id>]> to get the value assigned to an ID
//
// @Usage
// Use to make complex tags look less complex, and scripts more readable
// - narrate 'You invoke your power of notice...'
// - define range '<player.flag[range_level].mul[3]>'
// - define blocks '<player.flag[noticeable_blocks]>'
// - narrate '[NOTICE] You have noticed <player.location.find.blocks[<def[blocks]>].within[<def[range]>].size> blocks in the area that may be of interest.'

// - define range:<player.flag[range_level].mul[3]>
// - define blocks:<player.flag[noticeable_blocks]>
// - narrate '[NOTICE] You have noticed <player.location.find.blocks[<[blocks]>].within[<[range]>].size> blocks in the area that may be of interest.'
//
// @Usage
// Use to keep the value of a replaceable tag that you might use many times within a single script. Definitions
// can be faster and cleaner than reusing a replaceable tag over and over
// - define arg1 <c.args.get[1]>
// - if <def[arg1]> == hello:
// - define arg1:<context.args.get[1]>
// - if <[arg1]> == hello:
// - narrate 'Hello!'
// - else if <def[arg1]> == goodbye:
// - else if <[arg1]> == goodbye:
// - narrate 'Goodbye!'

// @Usage
// Use to pass some important information (arguments) on to another queue
// - run 'new_task' d:hello|world
// 'new_task' now has some definitions, <def[1]> and <def[2]>, that contains the contents specified, 'hello' and 'world'.

//
// @Usage
// Use to remove a definition
// - define myDef:!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,43 @@
import net.aufdemrand.denizencore.objects.dObject;
import net.aufdemrand.denizencore.scripts.ScriptEntry;
import net.aufdemrand.denizencore.scripts.commands.AbstractCommand;
import net.aufdemrand.denizencore.scripts.queues.ScriptQueue;
import net.aufdemrand.denizencore.utilities.CoreUtilities;
import net.aufdemrand.denizencore.utilities.data.ActionableDataProvider;
import net.aufdemrand.denizencore.utilities.data.DataAction;
import net.aufdemrand.denizencore.utilities.data.DataActionHelper;
import net.aufdemrand.denizencore.utilities.debugging.dB;

/**
* Creates a queue/script-level variable.
*/
public class DefineCommand extends AbstractCommand {

public static class DefinitionActionProvider extends ActionableDataProvider {

public ScriptQueue queue;

@Override
public dObject getValueAt(String keyName) {
return queue.getDefinitionObject(keyName);
}

@Override
public void setValueAt(String keyName, dObject value) {
queue.addDefinition(keyName, value);
}
}

@Override
public void parseArgs(ScriptEntry scriptEntry) throws InvalidArgumentsException {

for (aH.Argument arg : aH.interpretArguments(scriptEntry.aHArgs)) {

if (!scriptEntry.hasObject("definition")) {
if (arg.getValue().equals("!") && arg.hasPrefix()) {
scriptEntry.addObject("remove", new Element("true"));
scriptEntry.addObject("value", new Element("null"));
scriptEntry.addObject("definition", arg.getPrefix().asElement());
if (arg.raw_value.contains(":")) {
DefinitionActionProvider provider = new DefinitionActionProvider();
provider.queue = scriptEntry.getResidingQueue();
scriptEntry.addObject("action", DataActionHelper.parse(provider, arg.raw_value));
}
else {
scriptEntry.addObject("definition", new Element(CoreUtilities.toLowerCase(arg.getValue())));
Expand All @@ -39,7 +58,7 @@ else if (!scriptEntry.hasObject("value")) {
}
}

if (!scriptEntry.hasObject("definition") || !scriptEntry.hasObject("value")) {
if ((!scriptEntry.hasObject("definition") || !scriptEntry.hasObject("value")) && !scriptEntry.hasObject("action")) {
throw new InvalidArgumentsException("Must specify a definition and value!");
}
}
Expand All @@ -50,14 +69,21 @@ public void execute(ScriptEntry scriptEntry) {
Element definition = scriptEntry.getElement("definition");
dObject value = scriptEntry.getdObject("value");
Element remove = scriptEntry.getElement("remove");
Object actionObj = scriptEntry.getObject("action");
DataAction action = actionObj == null ? null : (DataAction) actionObj;

if (scriptEntry.dbCallShouldDebug()) {
dB.report(scriptEntry, getName(), aH.debugObj("queue", scriptEntry.getResidingQueue().id)
+ definition.debug()
+ value.debug()
+ (definition == null ? "" : definition.debug())
+ (value == null ? "" : value.debug())
+ (action == null ? "" : action.debug())
+ (remove != null ? remove.debug() : ""));
}

if (action != null) {
action.execute();
return;
}
if (scriptEntry.hasObject("remove")) {
scriptEntry.getResidingQueue().removeDefinition(definition.asString());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.aufdemrand.denizencore.utilities.data;

import net.aufdemrand.denizencore.objects.dObject;

public abstract class ActionableDataProvider {

/**
* Return the value object at a key.
* Result should generally be Element or dList.
*/
public abstract dObject getValueAt(String keyName);

/**
* Set the valueu object to a key.
* Value will be Element or dList.
* null indicates to remove the key.
*/
public abstract void setValueAt(String keyName, dObject value);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package net.aufdemrand.denizencore.utilities.data;

import net.aufdemrand.denizencore.objects.Element;
import net.aufdemrand.denizencore.objects.aH;
import net.aufdemrand.denizencore.objects.dList;
import net.aufdemrand.denizencore.objects.dObject;
import net.aufdemrand.denizencore.utilities.CoreUtilities;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class DataAction {

public ActionableDataProvider provider;

public DataActionType type;

public String key;

/**
* Zero = no index needed.
* Positive number = list index (starting at 1).
*/
public int index = 0;

public dObject inputValue = null;

public String debug() {
return aH.debugObj("action", "(" + key + "[" + index + "]:" + type + ":" + inputValue + ")");
}

public dList autoList(String key) {
dObject obj = provider.getValueAt(key);
if (obj == null) {
return new dList();
}
else {
return autoList(dList.getListFor(obj));
}
}

public dList autoList(dList list) {
return new dList(list);
}

public dObject autoDup(dObject object) {
if (object == null) {
return null;
}
if (object instanceof dList) {
return autoList((dList) object);
}
return new Element(object.toString());
}

public BigDecimal autoNumber() {
dObject obj = provider.getValueAt(key);
if (index != 0) {
dList subList = dList.getListFor(obj);
if (index < 0 || index > subList.size()) {
return BigDecimal.ZERO;
}
obj = subList.getObject(index - 1);
}
return autoNumber(obj);
}

public BigDecimal autoNumber(dObject obj) {
if (obj == null) {
return BigDecimal.ZERO;
}
return new BigDecimal(obj.toString());
}

public Element autoNumber(BigDecimal decimal) {
return new Element(decimal);
}

public void autoSet(dObject value) {
if (index != 0) {
dObject obj = provider.getValueAt(key);
dList subList = dList.getListFor(obj);
subList.setObject(index - 1, value);
value = subList;
}
provider.setValueAt(key, value);
}

public void requiresInputValue() {
if (inputValue == null) {
throw new DataActionException("Input value required for data action " + type + ".");
}
}

public void execute() {
switch (type) {
case INCREMENT: {
BigDecimal num = autoNumber();
num = num.add(BigDecimal.ONE);
autoSet(autoNumber(num));
break;
}
case DECREMENT: {
BigDecimal num = autoNumber();
num = num.subtract(BigDecimal.ONE);
autoSet(autoNumber(num));
break;
}
case ADD: {
requiresInputValue();
BigDecimal num = autoNumber();
num = num.add(autoNumber(inputValue));
autoSet(autoNumber(num));
break;
}
case SUBTRACT: {
requiresInputValue();
BigDecimal num = autoNumber();
num = num.subtract(autoNumber(inputValue));
autoSet(autoNumber(num));
break;
}
case MULTIPLY: {
requiresInputValue();
BigDecimal num = autoNumber();
num = num.multiply(autoNumber(inputValue));
autoSet(autoNumber(num));
break;
}
case DIVIDE: {
requiresInputValue();
BigDecimal num = autoNumber();
num = num.setScale(15, RoundingMode.HALF_UP);
num = num.divide(autoNumber(inputValue), RoundingMode.HALF_UP);
autoSet(autoNumber(num));
break;
}
case INSERT: {
requiresInputValue();
dList list = autoList(key);
list.addObject(inputValue);
provider.setValueAt(key, list);
break;
}
case REMOVE: {
dList list = autoList(key);
if (index != 0) {
list.remove(index - 1);
}
requiresInputValue();
String findValue = CoreUtilities.toLowerCase(inputValue.toString());
for (int i = 0; i < list.size(); i++) {
if (CoreUtilities.toLowerCase(list.get(i)).equals(findValue)) {
list.remove(i);
break;
}
}
provider.setValueAt(key, list);
break;
}
case SPLIT: {
requiresInputValue();
dList list = autoList(key);
list.addObjects(dList.getListFor(inputValue).objectForms);
provider.setValueAt(key, list);
break;
}
case SPLIT_NEW:
requiresInputValue();
provider.setValueAt(key, autoList(dList.getListFor(inputValue)));
break;
case SET:
requiresInputValue();
provider.setValueAt(key, autoDup(inputValue));
break;
case AUTO_SET:
provider.setValueAt(key, new Element(true));
break;
case CLEAR:
provider.setValueAt(key, null);
break;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.aufdemrand.denizencore.utilities.data;

public class DataActionException extends RuntimeException {

private static final long serialVersionUID = 3159123523457793068L;

public DataActionException(String message) {
super(message);
}
}
Loading

0 comments on commit 8dafa00

Please sign in to comment.