mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-09 09:16:34 +00:00
refactor structures
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.loot;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.inventory.Item;
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
import com.dfsek.terra.api.structures.loot.functions.AmountFunction;
|
||||
import com.dfsek.terra.api.structures.loot.functions.DamageFunction;
|
||||
import com.dfsek.terra.api.structures.loot.functions.EnchantFunction;
|
||||
import com.dfsek.terra.api.structures.loot.functions.LootFunction;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import net.jafama.FastMath;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Representation of a single item entry within a Loot Table pool.
|
||||
*/
|
||||
public class Entry {
|
||||
private final Item item;
|
||||
private final long weight;
|
||||
private final List<LootFunction> functions = new GlueList<>();
|
||||
|
||||
/**
|
||||
* Instantiates an Entry from a JSON representation.
|
||||
*
|
||||
* @param entry The JSON Object to instantiate from.
|
||||
*/
|
||||
public Entry(JSONObject entry, TerraPlugin main) {
|
||||
String id = entry.get("name").toString();
|
||||
this.item = main.getItemHandle().createItem(id);
|
||||
|
||||
long weight1;
|
||||
try {
|
||||
weight1 = (long) entry.get("weight");
|
||||
} catch(NullPointerException e) {
|
||||
weight1 = 1;
|
||||
}
|
||||
|
||||
this.weight = weight1;
|
||||
if(entry.containsKey("functions")) {
|
||||
for(Object function : (JSONArray) entry.get("functions")) {
|
||||
switch(((String) ((JSONObject) function).get("function"))) {
|
||||
case "minecraft:set_count":
|
||||
case "set_count":
|
||||
Object loot = ((JSONObject) function).get("count");
|
||||
long max, min;
|
||||
if(loot instanceof Long) {
|
||||
max = (Long) loot;
|
||||
min = (Long) loot;
|
||||
} else {
|
||||
max = (long) ((JSONObject) loot).get("max");
|
||||
min = (long) ((JSONObject) loot).get("min");
|
||||
}
|
||||
functions.add(new AmountFunction(FastMath.toIntExact(min), FastMath.toIntExact(max)));
|
||||
break;
|
||||
case "minecraft:set_damage":
|
||||
case "set_damage":
|
||||
long maxDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("max");
|
||||
long minDamage = (long) ((JSONObject) ((JSONObject) function).get("damage")).get("min");
|
||||
functions.add(new DamageFunction(FastMath.toIntExact(minDamage), FastMath.toIntExact(maxDamage)));
|
||||
break;
|
||||
case "minecraft:enchant_with_levels":
|
||||
case "enchant_with_levels":
|
||||
long maxEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("max");
|
||||
long minEnchant = (long) ((JSONObject) ((JSONObject) function).get("levels")).get("min");
|
||||
JSONArray disabled = null;
|
||||
if(((JSONObject) function).containsKey("disabled_enchants"))
|
||||
disabled = (JSONArray) ((JSONObject) function).get("disabled_enchants");
|
||||
functions.add(new EnchantFunction(FastMath.toIntExact(minEnchant), FastMath.toIntExact(maxEnchant), disabled, main));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a single ItemStack from the Entry, applying all functions to it.
|
||||
*
|
||||
* @param r The Random instance to apply functions with
|
||||
* @return ItemStack - The ItemStack with all functions applied.
|
||||
*/
|
||||
public ItemStack getItem(Random r) {
|
||||
ItemStack item = this.item.newItemStack(1);
|
||||
for(LootFunction f : functions) {
|
||||
item = f.apply(item, r);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the weight attribute of the Entry.
|
||||
*
|
||||
* @return long - The weight of the Entry.
|
||||
*/
|
||||
public long getWeight() {
|
||||
return this.weight;
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.loot;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.inventory.Inventory;
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Class representation of a Loot Table to populate chest loot.
|
||||
*/
|
||||
public class LootTableImpl implements com.dfsek.terra.api.structure.LootTable {
|
||||
private final List<Pool> pools = new GlueList<>();
|
||||
|
||||
/**
|
||||
* Instantiates a LootTable from a JSON String.
|
||||
*
|
||||
* @param json The JSON String representing the loot table.
|
||||
* @throws ParseException if malformed JSON is passed.
|
||||
*/
|
||||
public LootTableImpl(String json, TerraPlugin main) throws ParseException {
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
Object tableJSON = jsonParser.parse(json);
|
||||
JSONArray poolArray = (JSONArray) ((JSONObject) tableJSON).get("pools");
|
||||
for(Object pool : poolArray) {
|
||||
pools.add(new Pool((JSONObject) pool, main));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ItemStack> getLoot(Random r) {
|
||||
List<ItemStack> itemList = new GlueList<>();
|
||||
for(Pool pool : pools) {
|
||||
itemList.addAll(pool.getItems(r));
|
||||
}
|
||||
return itemList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillInventory(Inventory i, Random r) {
|
||||
List<ItemStack> loot = getLoot(r);
|
||||
for(ItemStack stack : loot) {
|
||||
int attempts = 0;
|
||||
while(stack.getAmount() != 0 && attempts < 10) {
|
||||
ItemStack newStack = stack.getType().newItemStack(stack.getAmount());
|
||||
newStack.setItemMeta(stack.getItemMeta());
|
||||
newStack.setAmount(1);
|
||||
int slot = r.nextInt(i.getSize());
|
||||
ItemStack slotItem = i.getItem(slot);
|
||||
if(slotItem == null) {
|
||||
i.setItem(slot, newStack);
|
||||
stack.setAmount(stack.getAmount() - 1);
|
||||
} else if(slotItem.getType().equals(newStack.getType())) {
|
||||
ItemStack dep = newStack.getType().newItemStack(newStack.getAmount());
|
||||
dep.setItemMeta(newStack.getItemMeta());
|
||||
dep.setAmount(newStack.getAmount() + slotItem.getAmount());
|
||||
i.setItem(slot, dep);
|
||||
stack.setAmount(stack.getAmount() - 1);
|
||||
}
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.loot;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.util.collections.ProbabilityCollectionImpl;
|
||||
import net.jafama.FastMath;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Representation of a Loot Table pool, or a set of items to be fetched independently.
|
||||
*/
|
||||
public class Pool {
|
||||
private final int max;
|
||||
private final int min;
|
||||
private final ProbabilityCollection<Entry> entries;
|
||||
|
||||
/**
|
||||
* Instantiates a Pool from a JSON representation.
|
||||
*
|
||||
* @param pool The JSON Object to instantiate from.
|
||||
*/
|
||||
public Pool(JSONObject pool, TerraPlugin main) {
|
||||
entries = new ProbabilityCollectionImpl<>();
|
||||
Object amount = pool.get("rolls");
|
||||
if(amount instanceof Long) {
|
||||
max = FastMath.toIntExact((Long) amount);
|
||||
min = FastMath.toIntExact((Long) amount);
|
||||
} else {
|
||||
max = FastMath.toIntExact((Long) ((JSONObject) amount).get("max"));
|
||||
min = FastMath.toIntExact((Long) ((JSONObject) amount).get("min"));
|
||||
}
|
||||
|
||||
for(Object entryJSON : (JSONArray) pool.get("entries")) {
|
||||
Entry entry = new Entry((JSONObject) entryJSON, main);
|
||||
entries.add(entry, FastMath.toIntExact(entry.getWeight()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a list of items from the pool using the provided Random instance.
|
||||
*
|
||||
* @param r The Random instance to use.
|
||||
* @return List<ItemStack> - The list of items fetched.
|
||||
*/
|
||||
public List<ItemStack> getItems(Random r) {
|
||||
|
||||
int rolls = r.nextInt(max - min + 1) + min;
|
||||
List<ItemStack> items = new GlueList<>();
|
||||
for(int i = 0; i < rolls; i++) {
|
||||
items.add(entries.get(r).getItem(r));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.loot.functions;
|
||||
|
||||
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Loot LootFunction fot setting the amount of an item.
|
||||
*/
|
||||
public class AmountFunction implements LootFunction {
|
||||
private final int max;
|
||||
private final int min;
|
||||
|
||||
/**
|
||||
* Instantiates an AmountFunction.
|
||||
*
|
||||
* @param min Minimum amount.
|
||||
* @param max Maximum amount.
|
||||
*/
|
||||
public AmountFunction(int min, int max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
@Override
|
||||
public ItemStack apply(ItemStack original, Random r) {
|
||||
original.setAmount(r.nextInt(max - min + 1) + min);
|
||||
return original;
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.loot.functions;
|
||||
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
import com.dfsek.terra.api.inventory.item.Damageable;
|
||||
import com.dfsek.terra.api.inventory.item.ItemMeta;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Loot LootFunction for setting the damage on items in Loot Tables
|
||||
*/
|
||||
public class DamageFunction implements LootFunction {
|
||||
private final int max;
|
||||
private final int min;
|
||||
|
||||
/**
|
||||
* Instantiates a DamageFunction.
|
||||
*
|
||||
* @param min Minimum amount of damage (percentage, out of 100)
|
||||
* @param max Maximum amount of damage (percentage, out of 100)
|
||||
*/
|
||||
public DamageFunction(int min, int max) {
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
@Override
|
||||
public ItemStack apply(ItemStack original, Random r) {
|
||||
if(original == null) return null;
|
||||
if(!original.isDamageable()) return original;
|
||||
ItemMeta meta = original.getItemMeta();
|
||||
double itemDurability = (r.nextDouble() * (max - min)) + min;
|
||||
Damageable damage = (Damageable) meta;
|
||||
damage.setDamage((int) (original.getType().getMaxDurability() - (itemDurability / 100) * original.getType().getMaxDurability()));
|
||||
original.setItemMeta((ItemMeta) damage);
|
||||
return original;
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.loot.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
import com.dfsek.terra.api.inventory.item.Enchantment;
|
||||
import com.dfsek.terra.api.inventory.item.ItemMeta;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import net.jafama.FastMath;
|
||||
import org.json.simple.JSONArray;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class EnchantFunction implements LootFunction {
|
||||
private final int min;
|
||||
private final int max;
|
||||
private final JSONArray disabled;
|
||||
private final TerraPlugin main;
|
||||
|
||||
|
||||
public EnchantFunction(int min, int max, JSONArray disabled, TerraPlugin main) {
|
||||
this.max = max;
|
||||
this.min = min;
|
||||
this.disabled = disabled;
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
@Override
|
||||
public ItemStack apply(ItemStack original, Random r) {
|
||||
if(original.getItemMeta() == null) return original;
|
||||
|
||||
double enchant = (r.nextDouble() * (max - min)) + min;
|
||||
List<Enchantment> possible = new GlueList<>();
|
||||
for(Enchantment ench : main.getItemHandle().getEnchantments()) {
|
||||
if(ench.canEnchantItem(original) && (disabled == null || !this.disabled.contains(ench.getID()))) {
|
||||
possible.add(ench);
|
||||
}
|
||||
}
|
||||
int numEnchant = (r.nextInt((int) FastMath.abs(enchant)) / 10 + 1);
|
||||
Collections.shuffle(possible);
|
||||
ItemMeta meta = original.getItemMeta();
|
||||
iter:
|
||||
for(int i = 0; i < numEnchant && i < possible.size(); i++) {
|
||||
Enchantment chosen = possible.get(i);
|
||||
for(Enchantment ench : meta.getEnchantments().keySet()) {
|
||||
if(chosen.conflictsWith(ench)) continue iter;
|
||||
}
|
||||
int lvl = r.nextInt(1 + (int) (((enchant / 40 > 1) ? 1 : enchant / 40) * (chosen.getMaxLevel())));
|
||||
try {
|
||||
meta.addEnchantment(chosen, FastMath.max(lvl, 1));
|
||||
} catch(IllegalArgumentException e) {
|
||||
main.logger().warning("Attempted to enchant " + original.getType() + " with " + chosen + " at level " + FastMath.max(lvl, 1) + ", but an unexpected exception occurred! Usually this is caused by a misbehaving enchantment plugin.");
|
||||
}
|
||||
}
|
||||
original.setItemMeta(meta);
|
||||
return original;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.loot.functions;
|
||||
|
||||
|
||||
import com.dfsek.terra.api.inventory.ItemStack;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Interface for mutating items in Loot Tables.
|
||||
*/
|
||||
public interface LootFunction {
|
||||
/**
|
||||
* Applies the function to an ItemStack.
|
||||
*
|
||||
* @param original The ItemStack on which to apply the function.
|
||||
* @param r The Random instance to use.
|
||||
* @return - ItemStack - The mutated ItemStack.
|
||||
*/
|
||||
ItemStack apply(ItemStack original, Random r);
|
||||
}
|
||||
@@ -1,443 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Item;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.NumericConstant;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.StringConstant;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.parser.lang.keywords.flow.BreakKeyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ContinueKeyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.keywords.flow.FailKeyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.keywords.flow.ReturnKeyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.ForKeyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.IfKeyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.keywords.looplike.WhileKeyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BooleanAndOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BooleanNotOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BooleanOrOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.ConcatenationOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.DivisionOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.ModuloOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.MultiplicationOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.NegationOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.NumberAdditionOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.SubtractionOperation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.EqualsStatement;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterOrEqualsThanStatement;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.GreaterThanStatement;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanOrEqualsStatement;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.LessThanStatement;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.statements.NotEqualsStatement;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Assignment;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Declaration;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Getter;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Token;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Tokenizer;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Parser {
|
||||
private final String data;
|
||||
private final Map<String, FunctionBuilder<? extends Function<?>>> functions = new HashMap<>();
|
||||
private final List<String> ignoredFunctions = new GlueList<>();
|
||||
|
||||
private String id;
|
||||
|
||||
public Parser(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Parser registerFunction(String name, FunctionBuilder<? extends Function<?>> functionBuilder) {
|
||||
functions.put(name, functionBuilder);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Parser ignoreFunction(String name) {
|
||||
ignoredFunctions.add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse input
|
||||
*
|
||||
* @return executable {@link Block}
|
||||
* @throws ParseException If parsing fails.
|
||||
*/
|
||||
public Block parse() throws ParseException {
|
||||
Tokenizer tokens = new Tokenizer(data);
|
||||
|
||||
// Parse ID
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.ID); // First token must be ID
|
||||
Token idToken = tokens.get();
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STRING); // Second token must be string literal containing ID
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
this.id = idToken.getContent();
|
||||
|
||||
|
||||
return parseBlock(tokens, new HashMap<>(), false);
|
||||
}
|
||||
|
||||
|
||||
private Keyword<?> parseLoopLike(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
|
||||
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(identifier, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
|
||||
|
||||
switch(identifier.getType()) {
|
||||
case FOR_LOOP:
|
||||
return parseForLoop(tokens, variableMap, identifier.getPosition());
|
||||
case IF_STATEMENT:
|
||||
return parseIfStatement(tokens, variableMap, identifier.getPosition(), loop);
|
||||
case WHILE_LOOP:
|
||||
return parseWhileLoop(tokens, variableMap, identifier.getPosition());
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unknown keyword " + identifier.getContent() + ": " + identifier.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
private WhileKeyword parseWhileLoop(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start) throws ParseException {
|
||||
Returnable<?> first = parseExpression(tokens, true, variableMap);
|
||||
ParserUtil.checkReturnType(first, Returnable.ReturnType.BOOLEAN);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
|
||||
return new WhileKeyword(parseStatementBlock(tokens, variableMap, true), (Returnable<Boolean>) first, start); // While loop
|
||||
}
|
||||
|
||||
private IfKeyword parseIfStatement(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, Position start, boolean loop) throws ParseException {
|
||||
Returnable<?> condition = parseExpression(tokens, true, variableMap);
|
||||
ParserUtil.checkReturnType(condition, Returnable.ReturnType.BOOLEAN);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
|
||||
Block elseBlock = null;
|
||||
Block statement = parseStatementBlock(tokens, variableMap, loop);
|
||||
|
||||
List<IfKeyword.Pair<Returnable<Boolean>, Block>> elseIf = new GlueList<>();
|
||||
|
||||
while(tokens.hasNext() && tokens.get().getType().equals(Token.Type.ELSE)) {
|
||||
tokens.consume(); // Consume else.
|
||||
if(tokens.get().getType().equals(Token.Type.IF_STATEMENT)) {
|
||||
tokens.consume(); // Consume if.
|
||||
Returnable<?> elseCondition = parseExpression(tokens, true, variableMap);
|
||||
ParserUtil.checkReturnType(elseCondition, Returnable.ReturnType.BOOLEAN);
|
||||
elseIf.add(new IfKeyword.Pair<>((Returnable<Boolean>) elseCondition, parseStatementBlock(tokens, variableMap, loop)));
|
||||
} else {
|
||||
elseBlock = parseStatementBlock(tokens, variableMap, loop);
|
||||
break; // Else must be last.
|
||||
}
|
||||
}
|
||||
|
||||
return new IfKeyword(statement, (Returnable<Boolean>) condition, elseIf, elseBlock, start); // If statement
|
||||
}
|
||||
|
||||
private Block parseStatementBlock(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
|
||||
|
||||
if(tokens.get().getType().equals(Token.Type.BLOCK_BEGIN)) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_BEGIN);
|
||||
Block block = parseBlock(tokens, variableMap, loop);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.BLOCK_END);
|
||||
return block;
|
||||
} else {
|
||||
Position position = tokens.get().getPosition();
|
||||
Block block = new Block(Collections.singletonList(parseItem(tokens, variableMap, loop)), position);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
private ForKeyword parseForLoop(Tokenizer tokens, Map<String, Returnable.ReturnType> old, Position start) throws ParseException {
|
||||
Map<String, Returnable.ReturnType> variableMap = new HashMap<>(old); // New scope
|
||||
Token f = tokens.get();
|
||||
ParserUtil.checkType(f, Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.IDENTIFIER);
|
||||
Item<?> initializer;
|
||||
if(f.isVariableDeclaration()) {
|
||||
Declaration<?> forVar = parseVariableDeclaration(tokens, variableMap);
|
||||
Token name = tokens.get();
|
||||
if(functions.containsKey(name.getContent()) || variableMap.containsKey(name.getContent()))
|
||||
throw new ParseException(name.getContent() + " is already defined in this scope", name.getPosition());
|
||||
initializer = forVar;
|
||||
} else initializer = parseExpression(tokens, true, variableMap);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
Returnable<?> conditional = parseExpression(tokens, true, variableMap);
|
||||
ParserUtil.checkReturnType(conditional, Returnable.ReturnType.BOOLEAN);
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
|
||||
Item<?> incrementer;
|
||||
Token token = tokens.get();
|
||||
if(variableMap.containsKey(token.getContent())) { // Assume variable assignment
|
||||
incrementer = parseAssignment(tokens, variableMap);
|
||||
} else incrementer = parseFunction(tokens, true, variableMap);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
|
||||
return new ForKeyword(parseStatementBlock(tokens, variableMap, true), initializer, (Returnable<Boolean>) conditional, incrementer, start);
|
||||
}
|
||||
|
||||
private Returnable<?> parseExpression(Tokenizer tokens, boolean full, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
|
||||
boolean booleanInverted = false; // Check for boolean not operator
|
||||
boolean negate = false;
|
||||
if(tokens.get().getType().equals(Token.Type.BOOLEAN_NOT)) {
|
||||
booleanInverted = true;
|
||||
tokens.consume();
|
||||
} else if(tokens.get().getType().equals(Token.Type.SUBTRACTION_OPERATOR)) {
|
||||
negate = true;
|
||||
tokens.consume();
|
||||
}
|
||||
|
||||
Token id = tokens.get();
|
||||
|
||||
ParserUtil.checkType(id, Token.Type.IDENTIFIER, Token.Type.BOOLEAN, Token.Type.STRING, Token.Type.NUMBER, Token.Type.GROUP_BEGIN);
|
||||
|
||||
Returnable<?> expression;
|
||||
if(id.isConstant()) {
|
||||
expression = parseConstantExpression(tokens);
|
||||
} else if(id.getType().equals(Token.Type.GROUP_BEGIN)) { // Parse grouped expression
|
||||
expression = parseGroup(tokens, variableMap);
|
||||
} else {
|
||||
if(functions.containsKey(id.getContent()))
|
||||
expression = parseFunction(tokens, false, variableMap);
|
||||
else if(variableMap.containsKey(id.getContent())) {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.IDENTIFIER);
|
||||
expression = new Getter(id.getContent(), id.getPosition(), variableMap.get(id.getContent()));
|
||||
} else throw new ParseException("Unexpected token \" " + id.getContent() + "\"", id.getPosition());
|
||||
}
|
||||
|
||||
if(booleanInverted) { // Invert operation if boolean not detected
|
||||
ParserUtil.checkReturnType(expression, Returnable.ReturnType.BOOLEAN);
|
||||
expression = new BooleanNotOperation((Returnable<Boolean>) expression, expression.getPosition());
|
||||
} else if(negate) {
|
||||
ParserUtil.checkReturnType(expression, Returnable.ReturnType.NUMBER);
|
||||
expression = new NegationOperation((Returnable<Number>) expression, expression.getPosition());
|
||||
}
|
||||
|
||||
if(full && tokens.get().isBinaryOperator()) { // Parse binary operations
|
||||
return parseBinaryOperation(expression, tokens, variableMap);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
private ConstantExpression<?> parseConstantExpression(Tokenizer tokens) throws ParseException {
|
||||
Token constantToken = tokens.consume();
|
||||
Position position = constantToken.getPosition();
|
||||
switch(constantToken.getType()) {
|
||||
case NUMBER:
|
||||
String content = constantToken.getContent();
|
||||
return new NumericConstant(content.contains(".") ? Double.parseDouble(content) : Integer.parseInt(content), position);
|
||||
case STRING:
|
||||
return new StringConstant(constantToken.getContent(), position);
|
||||
case BOOLEAN:
|
||||
return new BooleanConstant(Boolean.parseBoolean(constantToken.getContent()), position);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported constant token: " + constantToken.getType() + " at position: " + position);
|
||||
}
|
||||
}
|
||||
|
||||
private Returnable<?> parseGroup(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN);
|
||||
Returnable<?> expression = parseExpression(tokens, true, variableMap); // Parse inside of group as a separate expression
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END);
|
||||
return expression;
|
||||
}
|
||||
|
||||
|
||||
private BinaryOperation<?, ?> parseBinaryOperation(Returnable<?> left, Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
|
||||
Token binaryOperator = tokens.consume();
|
||||
ParserUtil.checkBinaryOperator(binaryOperator);
|
||||
|
||||
Returnable<?> right = parseExpression(tokens, false, variableMap);
|
||||
|
||||
Token other = tokens.get();
|
||||
if(ParserUtil.hasPrecedence(binaryOperator.getType(), other.getType())) {
|
||||
return assemble(left, parseBinaryOperation(right, tokens, variableMap), binaryOperator);
|
||||
} else if(other.isBinaryOperator()) {
|
||||
return parseBinaryOperation(assemble(left, right, binaryOperator), tokens, variableMap);
|
||||
}
|
||||
return assemble(left, right, binaryOperator);
|
||||
}
|
||||
|
||||
private BinaryOperation<?, ?> assemble(Returnable<?> left, Returnable<?> right, Token binaryOperator) throws ParseException {
|
||||
if(binaryOperator.isStrictNumericOperator())
|
||||
ParserUtil.checkArithmeticOperation(left, right, binaryOperator); // Numeric type checking
|
||||
if(binaryOperator.isStrictBooleanOperator()) ParserUtil.checkBooleanOperation(left, right, binaryOperator); // Boolean type checking
|
||||
switch(binaryOperator.getType()) {
|
||||
case ADDITION_OPERATOR:
|
||||
if(left.returnType().equals(Returnable.ReturnType.NUMBER) && right.returnType().equals(Returnable.ReturnType.NUMBER)) {
|
||||
return new NumberAdditionOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
}
|
||||
return new ConcatenationOperation((Returnable<Object>) left, (Returnable<Object>) right, binaryOperator.getPosition());
|
||||
case SUBTRACTION_OPERATOR:
|
||||
return new SubtractionOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case MULTIPLICATION_OPERATOR:
|
||||
return new MultiplicationOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case DIVISION_OPERATOR:
|
||||
return new DivisionOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case EQUALS_OPERATOR:
|
||||
return new EqualsStatement((Returnable<Object>) left, (Returnable<Object>) right, binaryOperator.getPosition());
|
||||
case NOT_EQUALS_OPERATOR:
|
||||
return new NotEqualsStatement((Returnable<Object>) left, (Returnable<Object>) right, binaryOperator.getPosition());
|
||||
case GREATER_THAN_OPERATOR:
|
||||
return new GreaterThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case LESS_THAN_OPERATOR:
|
||||
return new LessThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case GREATER_THAN_OR_EQUALS_OPERATOR:
|
||||
return new GreaterOrEqualsThanStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case LESS_THAN_OR_EQUALS_OPERATOR:
|
||||
return new LessThanOrEqualsStatement((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
case BOOLEAN_AND:
|
||||
return new BooleanAndOperation((Returnable<Boolean>) left, (Returnable<Boolean>) right, binaryOperator.getPosition());
|
||||
case BOOLEAN_OR:
|
||||
return new BooleanOrOperation((Returnable<Boolean>) left, (Returnable<Boolean>) right, binaryOperator.getPosition());
|
||||
case MODULO_OPERATOR:
|
||||
return new ModuloOperation((Returnable<Number>) left, (Returnable<Number>) right, binaryOperator.getPosition());
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsupported binary operator: " + binaryOperator.getType());
|
||||
}
|
||||
}
|
||||
|
||||
private Declaration<?> parseVariableDeclaration(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
|
||||
Token type = tokens.consume();
|
||||
ParserUtil.checkType(type, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.NUMBER_VARIABLE);
|
||||
|
||||
Returnable.ReturnType returnType = ParserUtil.getVariableReturnType(type);
|
||||
|
||||
ParserUtil.checkVarType(type, returnType); // Check for type mismatch
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
|
||||
if(functions.containsKey(identifier.getContent()) || variableMap.containsKey(identifier.getContent()))
|
||||
throw new ParseException(identifier.getContent() + " is already defined in this scope", identifier.getPosition());
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
|
||||
|
||||
Returnable<?> value = parseExpression(tokens, true, variableMap);
|
||||
ParserUtil.checkReturnType(value, returnType);
|
||||
|
||||
variableMap.put(identifier.getContent(), returnType);
|
||||
|
||||
return new Declaration<>(tokens.get().getPosition(), identifier.getContent(), value, returnType);
|
||||
}
|
||||
|
||||
private Block parseBlock(Tokenizer tokens, Map<String, Returnable.ReturnType> superVars, boolean loop) throws ParseException {
|
||||
List<Item<?>> parsedItems = new GlueList<>();
|
||||
|
||||
Map<String, Returnable.ReturnType> parsedVariables = new HashMap<>(superVars); // New hashmap as to not mutate parent scope's declarations.
|
||||
|
||||
Token first = tokens.get();
|
||||
|
||||
while(tokens.hasNext()) {
|
||||
Token token = tokens.get();
|
||||
if(token.getType().equals(Token.Type.BLOCK_END)) break; // Stop parsing at block end.
|
||||
Item<?> parsedItem = parseItem(tokens, parsedVariables, loop);
|
||||
if(parsedItem != Function.NULL) {
|
||||
parsedItems.add(parsedItem);
|
||||
}
|
||||
if(tokens.hasNext() && !token.isLoopLike()) ParserUtil.checkType(tokens.consume(), Token.Type.STATEMENT_END);
|
||||
}
|
||||
return new Block(parsedItems, first.getPosition());
|
||||
}
|
||||
|
||||
private Item<?> parseItem(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap, boolean loop) throws ParseException {
|
||||
Token token = tokens.get();
|
||||
if(loop) ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
|
||||
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.BREAK, Token.Type.CONTINUE, Token.Type.FAIL);
|
||||
else ParserUtil.checkType(token, Token.Type.IDENTIFIER, Token.Type.IF_STATEMENT, Token.Type.WHILE_LOOP, Token.Type.FOR_LOOP,
|
||||
Token.Type.NUMBER_VARIABLE, Token.Type.STRING_VARIABLE, Token.Type.BOOLEAN_VARIABLE, Token.Type.RETURN, Token.Type.FAIL);
|
||||
|
||||
if(token.isLoopLike()) { // Parse loop-like tokens (if, while, etc)
|
||||
return parseLoopLike(tokens, variableMap, loop);
|
||||
} else if(token.isIdentifier()) { // Parse identifiers
|
||||
if(variableMap.containsKey(token.getContent())) { // Assume variable assignment
|
||||
return parseAssignment(tokens, variableMap);
|
||||
} else return parseFunction(tokens, true, variableMap);
|
||||
} else if(token.isVariableDeclaration()) {
|
||||
|
||||
return parseVariableDeclaration(tokens, variableMap);
|
||||
|
||||
} else if(token.getType().equals(Token.Type.RETURN)) return new ReturnKeyword(tokens.consume().getPosition());
|
||||
else if(token.getType().equals(Token.Type.BREAK)) return new BreakKeyword(tokens.consume().getPosition());
|
||||
else if(token.getType().equals(Token.Type.CONTINUE)) return new ContinueKeyword(tokens.consume().getPosition());
|
||||
else if(token.getType().equals(Token.Type.FAIL)) return new FailKeyword(tokens.consume().getPosition());
|
||||
else throw new UnsupportedOperationException("Unexpected token " + token.getType() + ": " + token.getPosition());
|
||||
}
|
||||
|
||||
private Assignment<?> parseAssignment(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
|
||||
Token identifier = tokens.consume();
|
||||
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER);
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.ASSIGNMENT);
|
||||
|
||||
Returnable<?> value = parseExpression(tokens, true, variableMap);
|
||||
|
||||
ParserUtil.checkReturnType(value, variableMap.get(identifier.getContent()));
|
||||
|
||||
return new Assignment<>(value, identifier.getContent(), identifier.getPosition());
|
||||
}
|
||||
|
||||
private Function<?> parseFunction(Tokenizer tokens, boolean fullStatement, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
|
||||
Token identifier = tokens.consume();
|
||||
ParserUtil.checkType(identifier, Token.Type.IDENTIFIER); // First token must be identifier
|
||||
|
||||
if(!functions.containsKey(identifier.getContent()))
|
||||
throw new ParseException("No such function \"" + identifier.getContent() + "\"", identifier.getPosition());
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_BEGIN); // Second is body begin
|
||||
|
||||
|
||||
List<Returnable<?>> args = getArgs(tokens, variableMap); // Extract arguments, consume the rest.
|
||||
|
||||
ParserUtil.checkType(tokens.consume(), Token.Type.GROUP_END); // Remove body end
|
||||
|
||||
if(fullStatement) ParserUtil.checkType(tokens.get(), Token.Type.STATEMENT_END);
|
||||
|
||||
if(ignoredFunctions.contains(identifier.getContent())) {
|
||||
return Function.NULL;
|
||||
}
|
||||
|
||||
if(functions.containsKey(identifier.getContent())) {
|
||||
FunctionBuilder<?> builder = functions.get(identifier.getContent());
|
||||
|
||||
if(builder.argNumber() != -1 && args.size() != builder.argNumber())
|
||||
throw new ParseException("Expected " + builder.argNumber() + " arguments, found " + args.size(), identifier.getPosition());
|
||||
|
||||
for(int i = 0; i < args.size(); i++) {
|
||||
Returnable<?> argument = args.get(i);
|
||||
if(builder.getArgument(i) == null)
|
||||
throw new ParseException("Unexpected argument at position " + i + " in function " + identifier.getContent(), identifier.getPosition());
|
||||
ParserUtil.checkReturnType(argument, builder.getArgument(i));
|
||||
}
|
||||
return builder.build(args, identifier.getPosition());
|
||||
}
|
||||
throw new UnsupportedOperationException("Unsupported function: " + identifier.getContent());
|
||||
}
|
||||
|
||||
|
||||
private List<Returnable<?>> getArgs(Tokenizer tokens, Map<String, Returnable.ReturnType> variableMap) throws ParseException {
|
||||
List<Returnable<?>> args = new GlueList<>();
|
||||
|
||||
while(!tokens.get().getType().equals(Token.Type.GROUP_END)) {
|
||||
args.add(parseExpression(tokens, true, variableMap));
|
||||
ParserUtil.checkType(tokens.get(), Token.Type.SEPARATOR, Token.Type.GROUP_END);
|
||||
if(tokens.get().getType().equals(Token.Type.SEPARATOR)) tokens.consume();
|
||||
}
|
||||
return args;
|
||||
}
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Token;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ParserUtil {
|
||||
|
||||
private static final Map<Token.Type, Map<Token.Type, Boolean>> PRECEDENCE = new HashMap<>(); // If second has precedence, true.
|
||||
private static final List<Token.Type> ARITHMETIC = Arrays.asList(Token.Type.ADDITION_OPERATOR, Token.Type.SUBTRACTION_OPERATOR, Token.Type.MULTIPLICATION_OPERATOR, Token.Type.DIVISION_OPERATOR, Token.Type.MODULO_OPERATOR);
|
||||
private static final List<Token.Type> COMPARISON = Arrays.asList(Token.Type.EQUALS_OPERATOR, Token.Type.NOT_EQUALS_OPERATOR, Token.Type.LESS_THAN_OPERATOR, Token.Type.LESS_THAN_OR_EQUALS_OPERATOR, Token.Type.GREATER_THAN_OPERATOR, Token.Type.GREATER_THAN_OR_EQUALS_OPERATOR);
|
||||
|
||||
static { // Setup precedence
|
||||
Map<Token.Type, Boolean> add = new HashMap<>(); // Addition/subtraction before Multiplication/division.
|
||||
add.put(Token.Type.MULTIPLICATION_OPERATOR, true);
|
||||
add.put(Token.Type.DIVISION_OPERATOR, true);
|
||||
|
||||
PRECEDENCE.put(Token.Type.ADDITION_OPERATOR, add);
|
||||
PRECEDENCE.put(Token.Type.SUBTRACTION_OPERATOR, add);
|
||||
|
||||
Map<Token.Type, Boolean> numericBoolean = new HashMap<>();
|
||||
|
||||
ARITHMETIC.forEach(op -> numericBoolean.put(op, true)); // Numbers before comparison
|
||||
COMPARISON.forEach(op -> PRECEDENCE.put(op, numericBoolean));
|
||||
|
||||
|
||||
Map<Token.Type, Boolean> booleanOps = new HashMap<>();
|
||||
ARITHMETIC.forEach(op -> booleanOps.put(op, true)); // Everything before boolean
|
||||
COMPARISON.forEach(op -> booleanOps.put(op, true));
|
||||
|
||||
|
||||
PRECEDENCE.put(Token.Type.BOOLEAN_AND, booleanOps);
|
||||
PRECEDENCE.put(Token.Type.BOOLEAN_OR, booleanOps);
|
||||
}
|
||||
|
||||
public static void checkType(Token token, Token.Type... expected) throws ParseException {
|
||||
for(Token.Type type : expected) if(token.getType().equals(type)) return;
|
||||
throw new ParseException("Expected " + Arrays.toString(expected) + " but found " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
public static void checkReturnType(Returnable<?> returnable, Returnable.ReturnType... types) throws ParseException {
|
||||
for(Returnable.ReturnType type : types) if(returnable.returnType().equals(type)) return;
|
||||
throw new ParseException("Expected " + Arrays.toString(types) + " but found " + returnable.returnType(), returnable.getPosition());
|
||||
}
|
||||
|
||||
public static void checkArithmeticOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
|
||||
if(!left.returnType().equals(Returnable.ReturnType.NUMBER) || !right.returnType().equals(Returnable.ReturnType.NUMBER)) {
|
||||
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkBooleanOperation(Returnable<?> left, Returnable<?> right, Token operation) throws ParseException {
|
||||
if(!left.returnType().equals(Returnable.ReturnType.BOOLEAN) || !right.returnType().equals(Returnable.ReturnType.BOOLEAN)) {
|
||||
throw new ParseException("Operation " + operation.getType() + " not supported between " + left.returnType() + " and " + right.returnType(), operation.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkVarType(Token token, Returnable.ReturnType returnType) throws ParseException {
|
||||
if(returnType.equals(Returnable.ReturnType.STRING) && token.getType().equals(Token.Type.STRING_VARIABLE)) return;
|
||||
if(returnType.equals(Returnable.ReturnType.NUMBER) && token.getType().equals(Token.Type.NUMBER_VARIABLE)) return;
|
||||
if(returnType.equals(Returnable.ReturnType.BOOLEAN) && token.getType().equals(Token.Type.BOOLEAN_VARIABLE)) return;
|
||||
throw new ParseException("Type mismatch, cannot convert from " + returnType + " to " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if token is a binary operator
|
||||
*
|
||||
* @param token Token to check
|
||||
* @throws ParseException If token isn't a binary operator
|
||||
*/
|
||||
public static void checkBinaryOperator(Token token) throws ParseException {
|
||||
if(!token.isBinaryOperator())
|
||||
throw new ParseException("Expected binary operator, found " + token.getType(), token.getPosition());
|
||||
}
|
||||
|
||||
public static Returnable.ReturnType getVariableReturnType(Token varToken) throws ParseException {
|
||||
switch(varToken.getType()) {
|
||||
case NUMBER_VARIABLE:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
case STRING_VARIABLE:
|
||||
return Returnable.ReturnType.STRING;
|
||||
case BOOLEAN_VARIABLE:
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
default:
|
||||
throw new ParseException("Unexpected token " + varToken.getType() + "; expected variable declaration", varToken.getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasPrecedence(Token.Type first, Token.Type second) {
|
||||
if(!PRECEDENCE.containsKey(first)) return false;
|
||||
Map<Token.Type, Boolean> pre = PRECEDENCE.get(first);
|
||||
if(!pre.containsKey(second)) return false;
|
||||
return pre.get(second);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.exceptions;
|
||||
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class ParseException extends Exception {
|
||||
private static final long serialVersionUID = 6744390543046766386L;
|
||||
private final Position position;
|
||||
|
||||
public ParseException(String message, Position position) {
|
||||
super(message);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public ParseException(String message, Position position, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return super.getMessage() + ": " + position;
|
||||
}
|
||||
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Block implements Item<Block.ReturnInfo<?>> {
|
||||
private final List<Item<?>> items;
|
||||
private final Position position;
|
||||
|
||||
public Block(List<Item<?>> items, Position position) {
|
||||
this.items = items;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public List<Item<?>> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public ReturnInfo<?> apply(ImplementationArguments implementationArguments) {
|
||||
return apply(implementationArguments, new HashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
Map<String, Variable<?>> scope = new HashMap<>(variableMap);
|
||||
for(Item<?> item : items) {
|
||||
Object result = item.apply(implementationArguments, scope);
|
||||
if(result instanceof ReturnInfo) {
|
||||
ReturnInfo<?> level = (ReturnInfo<?>) result;
|
||||
if(!level.getLevel().equals(ReturnLevel.NONE)) return level;
|
||||
}
|
||||
}
|
||||
return new ReturnInfo<>(ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public static class ReturnInfo<T> {
|
||||
private final ReturnLevel level;
|
||||
private final T data;
|
||||
|
||||
public ReturnInfo(ReturnLevel level, T data) {
|
||||
this.level = level;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public ReturnLevel getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ReturnLevel {
|
||||
NONE(false), BREAK(false), CONTINUE(false), RETURN(true), FAIL(true);
|
||||
|
||||
private final boolean returnFast;
|
||||
|
||||
ReturnLevel(boolean returnFast) {
|
||||
this.returnFast = returnFast;
|
||||
}
|
||||
|
||||
public boolean isReturnFast() {
|
||||
return returnFast;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang;
|
||||
|
||||
/**
|
||||
* Arguments passed to {@link Item}s by the implementation
|
||||
*/
|
||||
public interface ImplementationArguments {
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface Item<T> {
|
||||
T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap);
|
||||
|
||||
Position getPosition();
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang;
|
||||
|
||||
public interface Keyword<T> extends Returnable<T> {
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang;
|
||||
|
||||
public interface Returnable<T> extends Item<T> {
|
||||
ReturnType returnType();
|
||||
|
||||
enum ReturnType {
|
||||
NUMBER(true), STRING(true), BOOLEAN(false), VOID(false), OBJECT(false);
|
||||
|
||||
private final boolean comparable;
|
||||
|
||||
ReturnType(boolean comparable) {
|
||||
this.comparable = comparable;
|
||||
}
|
||||
|
||||
public boolean isComparable() {
|
||||
return comparable;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang;
|
||||
|
||||
public interface Statement extends Item<Boolean> {
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.constants;
|
||||
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class BooleanConstant extends ConstantExpression<Boolean> {
|
||||
public BooleanConstant(Boolean constant, Position position) {
|
||||
super(constant, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.constants;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class ConstantExpression<T> implements Returnable<T> {
|
||||
private final T constant;
|
||||
private final Position position;
|
||||
|
||||
public ConstantExpression(T constant, Position position) {
|
||||
this.constant = constant;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public T getConstant() {
|
||||
return constant;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.constants;
|
||||
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class NumericConstant extends ConstantExpression<Number> {
|
||||
public NumericConstant(Number constant, Position position) {
|
||||
super(constant, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.constants;
|
||||
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class StringConstant extends ConstantExpression<String> {
|
||||
public StringConstant(String constant, Position position) {
|
||||
super(constant, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.functions;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface Function<T> extends Returnable<T> {
|
||||
Function<?> NULL = new Function<Object>() {
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.functions;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface FunctionBuilder<T extends Function<?>> {
|
||||
T build(List<Returnable<?>> argumentList, Position position) throws ParseException;
|
||||
|
||||
int argNumber();
|
||||
|
||||
Returnable.ReturnType getArgument(int position);
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.functions.def;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Item;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class FunctionBlock<T> implements Item<T> {
|
||||
private final List<Item<?>> items;
|
||||
private final Position position;
|
||||
private final T defaultVal;
|
||||
|
||||
public FunctionBlock(List<Item<?>> items, T defaultVal, Position position) {
|
||||
this.items = items;
|
||||
this.position = position;
|
||||
this.defaultVal = defaultVal;
|
||||
}
|
||||
|
||||
public List<Item<?>> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public synchronized T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
Map<String, Variable<?>> scope = new HashMap<>(variableMap);
|
||||
for(Item<?> item : items) {
|
||||
Object result = item.apply(implementationArguments, variableMap);
|
||||
if(result instanceof Block.ReturnInfo) {
|
||||
Block.ReturnInfo<T> level = (Block.ReturnInfo<T>) result;
|
||||
if(level.getLevel().equals(Block.ReturnLevel.RETURN)) return level.getData();
|
||||
}
|
||||
}
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BreakKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
public BreakKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.BREAK, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ContinueKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
public ContinueKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.CONTINUE, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class FailKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
public FailKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.FAIL, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.keywords.flow;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ReturnKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Position position;
|
||||
|
||||
public ReturnKeyword(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.RETURN, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.keywords.looplike;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Item;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ForKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Block conditional;
|
||||
private final Item<?> initializer;
|
||||
private final Returnable<Boolean> statement;
|
||||
private final Item<?> incrementer;
|
||||
private final Position position;
|
||||
|
||||
public ForKeyword(Block conditional, Item<?> initializer, Returnable<Boolean> statement, Item<?> incrementer, Position position) {
|
||||
this.conditional = conditional;
|
||||
this.initializer = initializer;
|
||||
this.statement = statement;
|
||||
this.incrementer = incrementer;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
for(initializer.apply(implementationArguments, variableMap); statement.apply(implementationArguments, variableMap); incrementer.apply(implementationArguments, variableMap)) {
|
||||
Block.ReturnInfo<?> level = conditional.apply(implementationArguments, variableMap);
|
||||
if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break;
|
||||
if(level.getLevel().isReturnFast()) return level;
|
||||
}
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.keywords.looplike;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class IfKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Block conditional;
|
||||
private final Returnable<Boolean> statement;
|
||||
private final Position position;
|
||||
private final List<Pair<Returnable<Boolean>, Block>> elseIf;
|
||||
private final Block elseBlock;
|
||||
|
||||
public IfKeyword(Block conditional, Returnable<Boolean> statement, List<Pair<Returnable<Boolean>, Block>> elseIf, @Nullable Block elseBlock, Position position) {
|
||||
this.conditional = conditional;
|
||||
this.statement = statement;
|
||||
this.position = position;
|
||||
this.elseIf = elseIf;
|
||||
this.elseBlock = elseBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
if(statement.apply(implementationArguments, variableMap)) return conditional.apply(implementationArguments, variableMap);
|
||||
else {
|
||||
for(Pair<Returnable<Boolean>, Block> pair : elseIf) {
|
||||
if(pair.getLeft().apply(implementationArguments, variableMap)) {
|
||||
return pair.getRight().apply(implementationArguments, variableMap);
|
||||
}
|
||||
}
|
||||
if(elseBlock != null) return elseBlock.apply(implementationArguments, variableMap);
|
||||
}
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
public static class Pair<L, R> {
|
||||
private final L left;
|
||||
private final R right;
|
||||
|
||||
public Pair(L left, R right) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
public L getLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
public R getRight() {
|
||||
return right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.keywords.looplike;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Keyword;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WhileKeyword implements Keyword<Block.ReturnInfo<?>> {
|
||||
private final Block conditional;
|
||||
private final Returnable<Boolean> statement;
|
||||
private final Position position;
|
||||
|
||||
public WhileKeyword(Block conditional, Returnable<Boolean> statement, Position position) {
|
||||
this.conditional = conditional;
|
||||
this.statement = statement;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block.ReturnInfo<?> apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
while(statement.apply(implementationArguments, variableMap)) {
|
||||
Block.ReturnInfo<?> level = conditional.apply(implementationArguments, variableMap);
|
||||
if(level.getLevel().equals(Block.ReturnLevel.BREAK)) break;
|
||||
if(level.getLevel().isReturnFast()) return level;
|
||||
}
|
||||
return new Block.ReturnInfo<>(Block.ReturnLevel.NONE, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class BinaryOperation<I, O> implements Returnable<O> {
|
||||
private final Returnable<I> left;
|
||||
private final Returnable<I> right;
|
||||
private final Position start;
|
||||
|
||||
public BinaryOperation(Returnable<I> left, Returnable<I> right, Position start) {
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public abstract O apply(I left, I right);
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public O apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return apply(left.apply(implementationArguments, variableMap), right.apply(implementationArguments, variableMap));
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class BooleanAndOperation extends BinaryOperation<Boolean, Boolean> {
|
||||
public BooleanAndOperation(Returnable<Boolean> left, Returnable<Boolean> right, Position start) {
|
||||
super(left, right, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Boolean left, Boolean right) {
|
||||
return left && right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class BooleanNotOperation extends UnaryOperation<Boolean> {
|
||||
public BooleanNotOperation(Returnable<Boolean> input, Position position) {
|
||||
super(input, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Boolean input) {
|
||||
return !input;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class BooleanOrOperation extends BinaryOperation<Boolean, Boolean> {
|
||||
public BooleanOrOperation(Returnable<Boolean> left, Returnable<Boolean> right, Position start) {
|
||||
super(left, right, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Boolean left, Boolean right) {
|
||||
return left || right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class ConcatenationOperation extends BinaryOperation<Object, Object> {
|
||||
public ConcatenationOperation(Returnable<Object> left, Returnable<Object> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(Object left, Object right) {
|
||||
return left.toString() + right.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class DivisionOperation extends BinaryOperation<Number, Number> {
|
||||
public DivisionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number left, Number right) {
|
||||
return left.doubleValue() / right.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class ModuloOperation extends BinaryOperation<Number, Number> {
|
||||
public ModuloOperation(Returnable<Number> left, Returnable<Number> right, Position start) {
|
||||
super(left, right, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number left, Number right) {
|
||||
return left.doubleValue() % right.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class MultiplicationOperation extends BinaryOperation<Number, Number> {
|
||||
public MultiplicationOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number left, Number right) {
|
||||
return left.doubleValue() * right.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class NegationOperation extends UnaryOperation<Number> {
|
||||
public NegationOperation(Returnable<Number> input, Position position) {
|
||||
super(input, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number input) {
|
||||
return -input.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class NumberAdditionOperation extends BinaryOperation<Number, Number> {
|
||||
public NumberAdditionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number left, Number right) {
|
||||
return left.doubleValue() + right.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class SubtractionOperation extends BinaryOperation<Number, Number> {
|
||||
public SubtractionOperation(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(Number left, Number right) {
|
||||
return left.doubleValue() - right.doubleValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class UnaryOperation<T> implements Returnable<T> {
|
||||
private final Returnable<T> input;
|
||||
private final Position position;
|
||||
|
||||
public UnaryOperation(Returnable<T> input, Position position) {
|
||||
this.input = input;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public abstract T apply(T input);
|
||||
|
||||
@Override
|
||||
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return apply(input.apply(implementationArguments, variableMap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public class EqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
private static final double EPSILON = 0.000000001D;
|
||||
|
||||
public EqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Object left, Object right) {
|
||||
if(left instanceof Number && right instanceof Number) {
|
||||
return FastMath.abs(((Number) left).doubleValue() - ((Number) right).doubleValue()) <= EPSILON;
|
||||
}
|
||||
|
||||
return left.equals(right);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class GreaterOrEqualsThanStatement extends BinaryOperation<Number, Boolean> {
|
||||
public GreaterOrEqualsThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Number left, Number right) {
|
||||
return left.doubleValue() >= right.doubleValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class GreaterThanStatement extends BinaryOperation<Number, Boolean> {
|
||||
public GreaterThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Number left, Number right) {
|
||||
return left.doubleValue() > right.doubleValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class LessThanOrEqualsStatement extends BinaryOperation<Number, Boolean> {
|
||||
public LessThanOrEqualsStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Number left, Number right) {
|
||||
return left.doubleValue() <= right.doubleValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class LessThanStatement extends BinaryOperation<Number, Boolean> {
|
||||
public LessThanStatement(Returnable<Number> left, Returnable<Number> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Number left, Number right) {
|
||||
return left.doubleValue() < right.doubleValue();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.operations.statements;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.operations.BinaryOperation;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class NotEqualsStatement extends BinaryOperation<Object, Boolean> {
|
||||
public NotEqualsStatement(Returnable<Object> left, Returnable<Object> right, Position position) {
|
||||
super(left, right, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(Object left, Object right) {
|
||||
return !left.equals(right);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Item;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Assignment<T> implements Item<T> {
|
||||
private final Returnable<T> value;
|
||||
private final Position position;
|
||||
private final String identifier;
|
||||
|
||||
public Assignment(Returnable<T> value, String identifier, Position position) {
|
||||
this.value = value;
|
||||
this.identifier = identifier;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public synchronized T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
T val = value.apply(implementationArguments, variableMap);
|
||||
((Variable<T>) variableMap.get(identifier)).setValue(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class BooleanVariable implements Variable<Boolean> {
|
||||
private final Position position;
|
||||
private Boolean value;
|
||||
|
||||
public BooleanVariable(Boolean value, Position position) {
|
||||
this.value = value;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getType() {
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Item;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Declaration<T> implements Item<T> {
|
||||
private final Position position;
|
||||
private final String identifier;
|
||||
private final Returnable<T> value;
|
||||
private final Returnable.ReturnType type;
|
||||
|
||||
public Declaration(Position position, String identifier, Returnable<T> value, Returnable.ReturnType type) {
|
||||
switch(type) {
|
||||
case STRING:
|
||||
case BOOLEAN:
|
||||
case NUMBER:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid variable type: " + type);
|
||||
}
|
||||
this.position = position;
|
||||
this.identifier = identifier;
|
||||
this.value = value;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
T result = value.apply(implementationArguments, variableMap);
|
||||
switch(type) {
|
||||
case NUMBER:
|
||||
variableMap.put(identifier, new NumberVariable((Number) result, position));
|
||||
break;
|
||||
case BOOLEAN:
|
||||
variableMap.put(identifier, new BooleanVariable((Boolean) result, position));
|
||||
break;
|
||||
case STRING:
|
||||
variableMap.put(identifier, new StringVariable((String) result, position));
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public Returnable.ReturnType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Getter implements Returnable<Object> {
|
||||
private final String identifier;
|
||||
private final Position position;
|
||||
private final ReturnType type;
|
||||
|
||||
public Getter(String identifier, Position position, ReturnType type) {
|
||||
this.identifier = identifier;
|
||||
this.position = position;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return variableMap.get(identifier).getValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class NumberVariable implements Variable<Number> {
|
||||
private final Position position;
|
||||
private Number value;
|
||||
|
||||
public NumberVariable(Number value, Position position) {
|
||||
this.value = value;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Number value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getType() {
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public class StringVariable implements Variable<String> {
|
||||
private final Position position;
|
||||
private String value;
|
||||
|
||||
public StringVariable(String value, Position position) {
|
||||
this.value = value;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getType() {
|
||||
return Returnable.ReturnType.STRING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.parser.lang.variables;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
public interface Variable<T> {
|
||||
T getValue();
|
||||
|
||||
void setValue(T value);
|
||||
|
||||
Returnable.ReturnType getType();
|
||||
|
||||
Position getPosition();
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.profiler.ProfileFrame;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.structure.LootTable;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.structure.buffer.Buffer;
|
||||
import com.dfsek.terra.api.structure.rotation.Rotation;
|
||||
import com.dfsek.terra.api.structures.parser.Parser;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Block;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.BinaryNumberFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.BiomeFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.BlockFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.CheckBlockFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.CheckFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.EntityFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.GetMarkFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.LootFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.PullFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.RandomFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.RecursionsFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.SetMarkFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.StateFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.StructureFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.UnaryBooleanFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.UnaryNumberFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.UnaryStringFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.builders.ZeroArgFunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.Chunk;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import net.jafama.FastMath;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class StructureScript implements Structure {
|
||||
private final Block block;
|
||||
private final String id;
|
||||
private final Cache<Vector3, StructureBuffer> cache;
|
||||
private final TerraPlugin main;
|
||||
private String tempID;
|
||||
|
||||
public StructureScript(InputStream inputStream, TerraPlugin main, Registry<Structure> registry, Registry<LootTable> lootRegistry, Registry<FunctionBuilder<?>> functionRegistry) throws ParseException {
|
||||
Parser parser;
|
||||
try {
|
||||
parser = new Parser(IOUtils.toString(inputStream, Charset.defaultCharset()));
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
functionRegistry.forEach(parser::registerFunction); // Register registry functions.
|
||||
|
||||
parser.registerFunction("block", new BlockFunctionBuilder(main, false))
|
||||
.registerFunction("dynamicBlock", new BlockFunctionBuilder(main, true))
|
||||
.registerFunction("debugBlock", new BlockFunctionBuilder(main, false))
|
||||
.registerFunction("check", new CheckFunctionBuilder(main))
|
||||
.registerFunction("structure", new StructureFunctionBuilder(registry, main))
|
||||
.registerFunction("randomInt", new RandomFunctionBuilder())
|
||||
.registerFunction("recursions", new RecursionsFunctionBuilder())
|
||||
.registerFunction("setMark", new SetMarkFunctionBuilder())
|
||||
.registerFunction("getMark", new GetMarkFunctionBuilder())
|
||||
.registerFunction("pull", new PullFunctionBuilder(main))
|
||||
.registerFunction("loot", new LootFunctionBuilder(main, lootRegistry, this))
|
||||
.registerFunction("entity", new EntityFunctionBuilder(main))
|
||||
.registerFunction("getBiome", new BiomeFunctionBuilder(main))
|
||||
.registerFunction("getBlock", new CheckBlockFunctionBuilder())
|
||||
.registerFunction("state", new StateFunctionBuilder(main))
|
||||
.registerFunction("setWaterlog", new UnaryBooleanFunctionBuilder((waterlog, args) -> args.setWaterlog(waterlog)))
|
||||
.registerFunction("originX", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getX(), Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("originY", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getY(), Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("originZ", new ZeroArgFunctionBuilder<Number>(arguments -> arguments.getBuffer().getOrigin().getZ(), Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("rotation", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().toString(), Returnable.ReturnType.STRING))
|
||||
.registerFunction("rotationDegrees", new ZeroArgFunctionBuilder<>(arguments -> arguments.getRotation().getDegrees(), Returnable.ReturnType.NUMBER))
|
||||
.registerFunction("print", new UnaryStringFunctionBuilder(string -> main.getDebugLogger().info("[" + tempID + "] " + string)))
|
||||
.registerFunction("abs", new UnaryNumberFunctionBuilder(number -> FastMath.abs(number.doubleValue())))
|
||||
.registerFunction("pow", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.pow(number.doubleValue(), number2.doubleValue())))
|
||||
.registerFunction("sqrt", new UnaryNumberFunctionBuilder(number -> FastMath.sqrt(number.doubleValue())))
|
||||
.registerFunction("floor", new UnaryNumberFunctionBuilder(number -> FastMath.floor(number.doubleValue())))
|
||||
.registerFunction("ceil", new UnaryNumberFunctionBuilder(number -> FastMath.ceil(number.doubleValue())))
|
||||
.registerFunction("log", new UnaryNumberFunctionBuilder(number -> FastMath.log(number.doubleValue())))
|
||||
.registerFunction("round", new UnaryNumberFunctionBuilder(number -> FastMath.round(number.doubleValue())))
|
||||
.registerFunction("sin", new UnaryNumberFunctionBuilder(number -> FastMath.sin(number.doubleValue())))
|
||||
.registerFunction("cos", new UnaryNumberFunctionBuilder(number -> FastMath.cos(number.doubleValue())))
|
||||
.registerFunction("tan", new UnaryNumberFunctionBuilder(number -> FastMath.tan(number.doubleValue())))
|
||||
.registerFunction("asin", new UnaryNumberFunctionBuilder(number -> FastMath.asin(number.doubleValue())))
|
||||
.registerFunction("acos", new UnaryNumberFunctionBuilder(number -> FastMath.acos(number.doubleValue())))
|
||||
.registerFunction("atan", new UnaryNumberFunctionBuilder(number -> FastMath.atan(number.doubleValue())))
|
||||
.registerFunction("max", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.max(number.doubleValue(), number2.doubleValue())))
|
||||
.registerFunction("min", new BinaryNumberFunctionBuilder((number, number2) -> FastMath.min(number.doubleValue(), number2.doubleValue())));
|
||||
|
||||
if(!main.getTerraConfig().isDebugScript()) {
|
||||
parser.ignoreFunction("debugBlock");
|
||||
}
|
||||
|
||||
block = parser.parse();
|
||||
this.id = parser.getID();
|
||||
tempID = id;
|
||||
this.main = main;
|
||||
this.cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getStructureCache()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public boolean generate(Vector3 location, World world, Random random, Rotation rotation) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript:" + id)) {
|
||||
StructureBuffer buffer = new StructureBuffer(location);
|
||||
boolean level = applyBlock(new TerraImplementationArguments(buffer, rotation, random, world, 0));
|
||||
buffer.paste(location, world);
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public boolean generate(Vector3 location, World world, Chunk chunk, Random random, Rotation rotation) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_chunk:" + id)) {
|
||||
StructureBuffer buffer = computeBuffer(location, world, random, rotation);
|
||||
buffer.paste(location, chunk);
|
||||
return buffer.succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public boolean test(Vector3 location, World world, Random random, Rotation rotation) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_test:" + id)) {
|
||||
StructureBuffer buffer = computeBuffer(location, world, random, rotation);
|
||||
return buffer.succeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private StructureBuffer computeBuffer(Vector3 location, World world, Random random, Rotation rotation) {
|
||||
try {
|
||||
return cache.get(location, () -> {
|
||||
StructureBuffer buf = new StructureBuffer(location);
|
||||
buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, world, 0)));
|
||||
return buf;
|
||||
});
|
||||
} catch(ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public boolean generate(Buffer buffer, World world, Random random, Rotation rotation, int recursions) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_recursive:" + id)) {
|
||||
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, world, recursions));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public boolean generateDirect(Vector3 location, World world, Random random, Rotation rotation) {
|
||||
try(ProfileFrame ignore = main.getProfiler().profile("terrascript_direct:" + id)) {
|
||||
DirectBuffer buffer = new DirectBuffer(location, world);
|
||||
return applyBlock(new TerraImplementationArguments(buffer, rotation, random, world, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private boolean applyBlock(TerraImplementationArguments arguments) {
|
||||
try {
|
||||
return block.apply(arguments).getLevel() != Block.ReturnLevel.FAIL;
|
||||
} catch(RuntimeException e) {
|
||||
main.logger().severe("Failed to generate structure at " + arguments.getBuffer().getOrigin() + ": " + e.getMessage());
|
||||
main.getDebugLogger().stack(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script;
|
||||
|
||||
import com.dfsek.terra.api.structure.buffer.Buffer;
|
||||
import com.dfsek.terra.api.structure.rotation.Rotation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class TerraImplementationArguments implements ImplementationArguments {
|
||||
private final Buffer buffer;
|
||||
private final Rotation rotation;
|
||||
private final Random random;
|
||||
private final World world;
|
||||
private final int recursions;
|
||||
private boolean waterlog = false;
|
||||
|
||||
public TerraImplementationArguments(Buffer buffer, Rotation rotation, Random random, World world, int recursions) {
|
||||
this.buffer = buffer;
|
||||
this.rotation = rotation;
|
||||
this.random = random;
|
||||
this.world = world;
|
||||
this.recursions = recursions;
|
||||
}
|
||||
|
||||
public Buffer getBuffer() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public int getRecursions() {
|
||||
return recursions;
|
||||
}
|
||||
|
||||
public Random getRandom() {
|
||||
return random;
|
||||
}
|
||||
|
||||
public Rotation getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public boolean isWaterlog() {
|
||||
return waterlog;
|
||||
}
|
||||
|
||||
public void setWaterlog(boolean waterlog) {
|
||||
this.waterlog = waterlog;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class BinaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
|
||||
|
||||
private final BiFunction<Number, Number, Number> function;
|
||||
|
||||
public BinaryNumberFunctionBuilder(BiFunction<Number, Number, Number> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Number> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<Number>() {
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, variableMap), ((Returnable<Number>) argumentList.get(1)).apply(implementationArguments, variableMap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0 || position == 1) return Returnable.ReturnType.NUMBER;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.BiomeFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BiomeFunctionBuilder implements FunctionBuilder<BiomeFunction> {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public BiomeFunctionBuilder(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public BiomeFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new BiomeFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.BooleanConstant;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.AbstractBlockFunction;
|
||||
import com.dfsek.terra.api.structures.script.functions.BlockFunction;
|
||||
import com.dfsek.terra.api.structures.script.functions.DynamicBlockFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockFunctionBuilder implements FunctionBuilder<AbstractBlockFunction> {
|
||||
private final TerraPlugin main;
|
||||
private final boolean dynamic;
|
||||
|
||||
public BlockFunctionBuilder(TerraPlugin main, boolean dynamic) {
|
||||
this.main = main;
|
||||
this.dynamic = dynamic;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public AbstractBlockFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
if(argumentList.size() < 4) throw new ParseException("Expected data", position);
|
||||
Returnable<Boolean> booleanReturnable = new BooleanConstant(true, position);
|
||||
if(argumentList.size() == 5) booleanReturnable = (Returnable<Boolean>) argumentList.get(4);
|
||||
if(dynamic)
|
||||
return new DynamicBlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), booleanReturnable, main, position);
|
||||
return new BlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), booleanReturnable, main, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
case 3:
|
||||
return Returnable.ReturnType.STRING;
|
||||
case 4:
|
||||
return Returnable.ReturnType.BOOLEAN;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.CheckBlockFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CheckBlockFunctionBuilder implements FunctionBuilder<CheckBlockFunction> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public CheckBlockFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new CheckBlockFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.CheckFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CheckFunctionBuilder implements FunctionBuilder<CheckFunction> {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public CheckFunctionBuilder(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public CheckFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
return new CheckFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.EntityFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EntityFunctionBuilder implements FunctionBuilder<EntityFunction> {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public EntityFunctionBuilder(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public EntityFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
return new EntityFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
case 3:
|
||||
return Returnable.ReturnType.STRING;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.GetMarkFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GetMarkFunctionBuilder implements FunctionBuilder<GetMarkFunction> {
|
||||
|
||||
public GetMarkFunctionBuilder() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public GetMarkFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new GetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.structure.LootTable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.structures.script.functions.LootFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LootFunctionBuilder implements FunctionBuilder<LootFunction> {
|
||||
private final TerraPlugin main;
|
||||
private final Registry<LootTable> registry;
|
||||
private final StructureScript script;
|
||||
|
||||
public LootFunctionBuilder(TerraPlugin main, Registry<LootTable> registry, StructureScript script) {
|
||||
this.main = main;
|
||||
this.registry = registry;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public LootFunction build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new LootFunction(registry, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position, script);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
case 3:
|
||||
return Returnable.ReturnType.STRING;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.PullFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PullFunctionBuilder implements FunctionBuilder<PullFunction> {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public PullFunctionBuilder(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public PullFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
return new PullFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
case 3:
|
||||
return Returnable.ReturnType.STRING;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.RandomFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RandomFunctionBuilder implements FunctionBuilder<RandomFunction> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public RandomFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
return new RandomFunction((Returnable<Number>) argumentList.get(0), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.NUMBER;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.RecursionsFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class RecursionsFunctionBuilder implements FunctionBuilder<RecursionsFunction> {
|
||||
@Override
|
||||
public RecursionsFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
return new RecursionsFunction(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.SetMarkFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SetMarkFunctionBuilder implements FunctionBuilder<SetMarkFunction> {
|
||||
|
||||
public SetMarkFunctionBuilder() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public SetMarkFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
return new SetMarkFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
case 3:
|
||||
return Returnable.ReturnType.STRING;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.StateFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class StateFunctionBuilder implements FunctionBuilder<StateFunction> {
|
||||
private final TerraPlugin main;
|
||||
|
||||
public StateFunctionBuilder(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public StateFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
if(argumentList.size() < 4) throw new ParseException("Expected data", position);
|
||||
return new StateFunction((Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), (Returnable<String>) argumentList.get(3), main, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
case 3:
|
||||
return Returnable.ReturnType.STRING;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.script.functions.StructureFunction;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class StructureFunctionBuilder implements FunctionBuilder<StructureFunction> {
|
||||
private final Registry<Structure> registry;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public StructureFunctionBuilder(Registry<Structure> registry, TerraPlugin main) {
|
||||
this.registry = registry;
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public StructureFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
|
||||
if(argumentList.size() < 5) throw new ParseException("Expected rotations", position);
|
||||
|
||||
return new StructureFunction((Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0), (Returnable<Number>) argumentList.remove(0), (Returnable<String>) argumentList.remove(0),
|
||||
argumentList.stream().map(item -> ((Returnable<String>) item)).collect(Collectors.toList()), registry, position, main);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
switch(position) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return Returnable.ReturnType.NUMBER;
|
||||
default:
|
||||
return Returnable.ReturnType.STRING;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public class UnaryBooleanFunctionBuilder implements FunctionBuilder<Function<Void>> {
|
||||
|
||||
private final BiConsumer<Boolean, TerraImplementationArguments> function;
|
||||
|
||||
public UnaryBooleanFunctionBuilder(BiConsumer<Boolean, TerraImplementationArguments> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Void> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<Void>() {
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
function.accept(((Returnable<Boolean>) argumentList.get(0)).apply(implementationArguments, variableMap), (TerraImplementationArguments) implementationArguments);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.BOOLEAN;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class UnaryNumberFunctionBuilder implements FunctionBuilder<Function<Number>> {
|
||||
|
||||
private final java.util.function.Function<Number, Number> function;
|
||||
|
||||
public UnaryNumberFunctionBuilder(java.util.function.Function<Number, Number> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Number> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<Number>() {
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return function.apply(((Returnable<Number>) argumentList.get(0)).apply(implementationArguments, variableMap));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.NUMBER;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class UnaryStringFunctionBuilder implements FunctionBuilder<Function<Void>> {
|
||||
|
||||
private final java.util.function.Consumer<String> function;
|
||||
|
||||
public UnaryStringFunctionBuilder(java.util.function.Consumer<String> function) {
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<Void> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<Void>() {
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
function.accept(((Returnable<String>) argumentList.get(0)).apply(implementationArguments, variableMap));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return Returnable.ReturnType.STRING;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.builders;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ZeroArgFunctionBuilder<T> implements FunctionBuilder<Function<T>> {
|
||||
private final java.util.function.Function<TerraImplementationArguments, T> function;
|
||||
private final Returnable.ReturnType type;
|
||||
|
||||
public ZeroArgFunctionBuilder(java.util.function.Function<TerraImplementationArguments, T> function, Returnable.ReturnType type) {
|
||||
this.function = function;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<T> build(List<Returnable<?>> argumentList, Position position) {
|
||||
return new Function<T>() {
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return function.apply((TerraImplementationArguments) implementationArguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int argNumber() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Returnable.ReturnType getArgument(int position) {
|
||||
if(position == 0) return type;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedBlock;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class AbstractBlockFunction implements Function<Void> {
|
||||
protected final Returnable<Number> x, y, z;
|
||||
protected final Returnable<String> blockData;
|
||||
protected final TerraPlugin main;
|
||||
private final Returnable<Boolean> overwrite;
|
||||
private final Position position;
|
||||
|
||||
protected AbstractBlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> blockData, Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.blockData = blockData;
|
||||
this.overwrite = overwrite;
|
||||
this.main = main;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
void setBlock(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap, TerraImplementationArguments arguments, BlockState rot) {
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
|
||||
arguments.getBuffer().addItem(new BufferedBlock(rot, overwrite.apply(implementationArguments, variableMap), main, arguments.isWaterlog()), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BiomeFunction implements Function<String> {
|
||||
private final TerraPlugin main;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
|
||||
public BiomeFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
|
||||
this.main = main;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
BiomeProvider grid = main.getWorld(arguments.getWorld()).getBiomeProvider();
|
||||
|
||||
return grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())))).getID();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockFunction extends AbstractBlockFunction {
|
||||
private final BlockState data;
|
||||
|
||||
public BlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, Returnable<Boolean> overwrite, TerraPlugin main, Position position) throws ParseException {
|
||||
super(x, y, z, data, overwrite, main, position);
|
||||
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
|
||||
try {
|
||||
this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant());
|
||||
} catch(IllegalArgumentException e) {
|
||||
throw new ParseException("Could not parse block data", data.getPosition(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
BlockState rot = data.clone();
|
||||
setBlock(implementationArguments, variableMap, arguments, rot);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CheckBlockFunction implements Function<String> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
public CheckBlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
String data = arguments.getWorld().getBlockData(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())))).getAsString();
|
||||
if(data.contains("[")) return data.substring(0, data.indexOf('[')); // Strip properties
|
||||
else return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.TerraWorld;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.generator.SamplerCache;
|
||||
import com.dfsek.terra.config.templates.BiomeTemplate;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class CheckFunction implements Function<String> {
|
||||
private final TerraPlugin main;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
public CheckFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
|
||||
this.main = main;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
|
||||
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
Vector3 location = arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ())));
|
||||
|
||||
return apply(location, arguments.getWorld());
|
||||
}
|
||||
|
||||
private String apply(Vector3 vector, World world) {
|
||||
TerraWorld tw = main.getWorld(world);
|
||||
SamplerCache cache = tw.getConfig().getSamplerCache();
|
||||
double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), cache);
|
||||
|
||||
if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land.
|
||||
|
||||
BiomeProvider provider = tw.getBiomeProvider();
|
||||
UserDefinedBiome b = (UserDefinedBiome) provider.getBiome(vector.getBlockX(), vector.getBlockZ());
|
||||
BiomeTemplate c = b.getConfig();
|
||||
|
||||
if(vector.getY() > c.getSeaLevel()) return "AIR"; // Above sea level
|
||||
return "OCEAN"; // Below sea level
|
||||
}
|
||||
|
||||
private double sample(int x, int y, int z, SamplerCache cache) {
|
||||
int cx = FastMath.floorDiv(x, 16);
|
||||
int cz = FastMath.floorDiv(z, 16);
|
||||
return cache.get(x, z).sample(x - (cx << 4), y, z - (cz << 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class DynamicBlockFunction extends AbstractBlockFunction {
|
||||
private final Map<String, BlockState> data = new HashMap<>();
|
||||
private final Position position;
|
||||
|
||||
|
||||
public DynamicBlockFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, Returnable<Boolean> overwrite, TerraPlugin main, Position position) {
|
||||
super(x, y, z, data, overwrite, main, position);
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
BlockState rot = data.computeIfAbsent(blockData.apply(implementationArguments, variableMap), main.getWorldHandle()::createBlockData).clone();
|
||||
setBlock(implementationArguments, variableMap, arguments, rot);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedEntity;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class EntityFunction implements Function<Void> {
|
||||
private final EntityType data;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public EntityFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) throws ParseException {
|
||||
this.position = position;
|
||||
this.main = main;
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Entity data must be constant", data.getPosition());
|
||||
|
||||
this.data = main.getWorldHandle().getEntity(((ConstantExpression<String>) data).getConstant());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
arguments.getBuffer().addItem(new BufferedEntity(data, main), new Vector3(xz.getX(), y.apply(implementationArguments, variableMap).doubleValue(), xz.getZ()));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GetMarkFunction implements Function<String> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
public GetMarkFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) {
|
||||
this.position = position;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
String mark = arguments.getBuffer().getMark(new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())));
|
||||
return mark == null ? "" : mark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.STRING;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.structure.LootTable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class LootFunction implements Function<Void> {
|
||||
private final Registry<LootTable> registry;
|
||||
private final Returnable<String> data;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final TerraPlugin main;
|
||||
private final StructureScript script;
|
||||
|
||||
public LootFunction(Registry<LootTable> registry, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position, StructureScript script) {
|
||||
this.registry = registry;
|
||||
this.position = position;
|
||||
this.data = data;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.main = main;
|
||||
this.script = script;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
String id = data.apply(implementationArguments, variableMap);
|
||||
LootTable table = registry.get(id);
|
||||
|
||||
if(table == null) {
|
||||
main.logger().severe("No such loot table " + id);
|
||||
return null;
|
||||
}
|
||||
|
||||
arguments.getBuffer().addItem(new BufferedLootApplication(table, main, script), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.structures.parser.exceptions.ParseException;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.constants.ConstantExpression;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedPulledBlock;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class PullFunction implements Function<Void> {
|
||||
private final BlockState data;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
|
||||
public PullFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) throws ParseException {
|
||||
this.position = position;
|
||||
if(!(data instanceof ConstantExpression)) throw new ParseException("Block data must be constant", data.getPosition());
|
||||
|
||||
this.data = main.getWorldHandle().createBlockData(((ConstantExpression<String>) data).getConstant());
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
BlockState rot = data.clone();
|
||||
RotationUtil.rotateBlockData(rot, arguments.getRotation().inverse());
|
||||
arguments.getBuffer().addItem(new BufferedPulledBlock(rot), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class RandomFunction implements Function<Integer> {
|
||||
private final Returnable<Number> numberReturnable;
|
||||
private final Position position;
|
||||
|
||||
public RandomFunction(Returnable<Number> numberReturnable, Position position) {
|
||||
this.numberReturnable = numberReturnable;
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(numberReturnable.apply(implementationArguments, variableMap).intValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class RecursionsFunction implements Function<Number> {
|
||||
private final Position position;
|
||||
|
||||
public RecursionsFunction(Position position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.NUMBER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
return ((TerraImplementationArguments) implementationArguments).getRecursions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SetMarkFunction implements Function<Void> {
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final Returnable<String> mark;
|
||||
|
||||
public SetMarkFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> mark, Position position) {
|
||||
this.position = position;
|
||||
this.mark = mark;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
arguments.getBuffer().setMark(mark.apply(implementationArguments, variableMap), new Vector3(FastMath.floorToInt(xz.getX()), FastMath.floorToInt(y.apply(implementationArguments, variableMap).doubleValue()), FastMath.floorToInt(xz.getZ())));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.items.BufferedStateManipulator;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class StateFunction implements Function<Void> {
|
||||
private final Returnable<String> data;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public StateFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> data, TerraPlugin main, Position position) {
|
||||
this.position = position;
|
||||
this.main = main;
|
||||
this.data = data;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
arguments.getBuffer().addItem(new BufferedStateManipulator(main, data.apply(implementationArguments, variableMap)), new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.VOID;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.script.functions;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.structure.Structure;
|
||||
import com.dfsek.terra.api.structure.rotation.Rotation;
|
||||
import com.dfsek.terra.api.structures.parser.lang.ImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.parser.lang.Returnable;
|
||||
import com.dfsek.terra.api.structures.parser.lang.functions.Function;
|
||||
import com.dfsek.terra.api.structures.parser.lang.variables.Variable;
|
||||
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
|
||||
import com.dfsek.terra.api.structures.structure.buffer.IntermediateBuffer;
|
||||
import com.dfsek.terra.api.structures.tokenizer.Position;
|
||||
import com.dfsek.terra.api.util.RotationUtil;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class StructureFunction implements Function<Boolean> {
|
||||
private final Registry<Structure> registry;
|
||||
private final Returnable<String> id;
|
||||
private final Returnable<Number> x, y, z;
|
||||
private final Position position;
|
||||
private final TerraPlugin main;
|
||||
private final List<Returnable<String>> rotations;
|
||||
|
||||
public StructureFunction(Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Returnable<String> id, List<Returnable<String>> rotations, Registry<Structure> registry, Position position, TerraPlugin main) {
|
||||
this.registry = registry;
|
||||
this.id = id;
|
||||
this.position = position;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.main = main;
|
||||
this.rotations = rotations;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReturnType returnType() {
|
||||
return ReturnType.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean apply(ImplementationArguments implementationArguments, Map<String, Variable<?>> variableMap) {
|
||||
TerraImplementationArguments arguments = (TerraImplementationArguments) implementationArguments;
|
||||
|
||||
if(arguments.getRecursions() > main.getTerraConfig().getMaxRecursion())
|
||||
throw new RuntimeException("Structure recursion too deep: " + arguments.getRecursions());
|
||||
|
||||
Vector2 xz = new Vector2(x.apply(implementationArguments, variableMap).doubleValue(), z.apply(implementationArguments, variableMap).doubleValue());
|
||||
|
||||
RotationUtil.rotateVector(xz, arguments.getRotation());
|
||||
|
||||
String app = id.apply(implementationArguments, variableMap);
|
||||
Structure script = registry.get(app);
|
||||
if(script == null) {
|
||||
main.logger().severe("No such structure " + app);
|
||||
return null;
|
||||
}
|
||||
|
||||
Rotation rotation1;
|
||||
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, variableMap);
|
||||
try {
|
||||
rotation1 = Rotation.valueOf(rotString);
|
||||
} catch(IllegalArgumentException e) {
|
||||
main.logger().severe("Invalid rotation " + rotString);
|
||||
return null;
|
||||
}
|
||||
|
||||
Vector3 offset = new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).doubleValue(), FastMath.roundToInt(xz.getZ()));
|
||||
|
||||
return script.generate(new IntermediateBuffer(arguments.getBuffer(), offset), arguments.getWorld(), arguments.getRandom(), arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Position getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer;
|
||||
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Cell implements BufferedItem {
|
||||
private final List<BufferedItem> items = new GlueList<>();
|
||||
private String mark = null;
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
items.forEach(item -> item.paste(origin.clone(), world));
|
||||
}
|
||||
|
||||
public void add(BufferedItem item) {
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
public String getMark() {
|
||||
return mark;
|
||||
}
|
||||
|
||||
public void setMark(String mark) {
|
||||
this.mark = mark;
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer;
|
||||
|
||||
import com.dfsek.terra.api.structure.buffer.Buffer;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.Chunk;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Buffer implementation that directly pastes to the world.
|
||||
*/
|
||||
public class DirectBuffer implements Buffer {
|
||||
private final Vector3 origin;
|
||||
private final World target;
|
||||
private final Map<Vector3, String> marks = new LinkedHashMap<>();
|
||||
|
||||
public DirectBuffer(Vector3 origin, World target) {
|
||||
this.origin = origin;
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, Chunk chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer addItem(BufferedItem item, Vector3 location) {
|
||||
item.paste(origin.clone().add(location), target);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMark(Vector3 location) {
|
||||
return marks.get(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer setMark(String mark, Vector3 location) {
|
||||
marks.put(location, mark);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer;
|
||||
|
||||
import com.dfsek.terra.api.structure.buffer.Buffer;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.Chunk;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
public class IntermediateBuffer implements Buffer {
|
||||
private final Buffer original;
|
||||
private final Vector3 offset;
|
||||
|
||||
public IntermediateBuffer(Buffer original, Vector3 offset) {
|
||||
this.original = original;
|
||||
this.offset = offset.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, Chunk chunk) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer addItem(BufferedItem item, Vector3 location) {
|
||||
return original.addItem(item, location.clone().add(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getOrigin() {
|
||||
return original.getOrigin().clone().add(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMark(Vector3 location) {
|
||||
return original.getMark(location.clone().add(offset));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer setMark(String mark, Vector3 location) {
|
||||
original.setMark(mark, location.clone().add(offset));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer;
|
||||
|
||||
import com.dfsek.terra.api.structure.buffer.Buffer;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.Chunk;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class StructureBuffer implements Buffer {
|
||||
private final Map<Vector3, Cell> bufferedItemMap = new LinkedHashMap<>();
|
||||
private final Vector3 origin;
|
||||
private boolean succeeded;
|
||||
|
||||
public StructureBuffer(Vector3 origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public void paste(Vector3 origin, World world) {
|
||||
bufferedItemMap.forEach(((vector3, item) -> item.paste(origin.clone().add(vector3), world)));
|
||||
}
|
||||
|
||||
public void paste(Vector3 origin, Chunk chunk) {
|
||||
bufferedItemMap.forEach(((location, item) -> {
|
||||
Vector3 current = origin.clone().add(location);
|
||||
if(FastMath.floorDiv(current.getBlockX(), 16) != chunk.getX() || FastMath.floorDiv(current.getBlockZ(), 16) != chunk.getZ())
|
||||
return;
|
||||
item.paste(current, chunk.getWorld());
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer addItem(BufferedItem item, Vector3 location) {
|
||||
bufferedItemMap.computeIfAbsent(location.clone(), l -> new Cell()).add(item);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMark(Vector3 location) {
|
||||
Cell cell = bufferedItemMap.get(location);
|
||||
if(cell != null) {
|
||||
return cell.getMark();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Buffer setMark(String mark, Vector3 location) {
|
||||
bufferedItemMap.computeIfAbsent(location.clone(), l -> new Cell()).setMark(mark);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setSucceeded(boolean succeeded) {
|
||||
this.succeeded = succeeded;
|
||||
}
|
||||
|
||||
public boolean succeeded() {
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3 getOrigin() {
|
||||
return origin.clone();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer.items;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.block.state.properties.base.Properties;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
public class BufferedBlock implements BufferedItem {
|
||||
private final BlockState data;
|
||||
private final boolean overwrite;
|
||||
private final TerraPlugin main;
|
||||
private final boolean waterlog;
|
||||
|
||||
public BufferedBlock(BlockState data, boolean overwrite, TerraPlugin main, boolean waterlog) {
|
||||
this.data = data;
|
||||
this.overwrite = overwrite;
|
||||
this.main = main;
|
||||
this.waterlog = waterlog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
try {
|
||||
BlockState current = world.getBlockData(origin);
|
||||
if(overwrite || current.isAir()) {
|
||||
if(waterlog && current.has(Properties.WATERLOGGED) && current.getBlockType().isWater()) {
|
||||
current.set(Properties.WATERLOGGED, true);
|
||||
}
|
||||
world.setBlockData(origin, data);
|
||||
}
|
||||
} catch(RuntimeException e) {
|
||||
main.logger().severe("Failed to place block at location " + origin + ": " + e.getMessage());
|
||||
main.getDebugLogger().stack(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer.items;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.entity.Entity;
|
||||
import com.dfsek.terra.api.entity.EntityType;
|
||||
import com.dfsek.terra.api.event.events.world.generation.EntitySpawnEvent;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
public class BufferedEntity implements BufferedItem {
|
||||
|
||||
private final EntityType type;
|
||||
private final TerraPlugin main;
|
||||
|
||||
public BufferedEntity(EntityType type, TerraPlugin main) {
|
||||
this.type = type;
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
Entity entity = world.spawnEntity(origin.clone().add(0.5, 0, 0.5), type);
|
||||
main.getEventManager().callEvent(new EntitySpawnEvent(entity.world().getTerraGenerator().getConfigPack(), entity));
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer.items;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.api.block.entity.Container;
|
||||
import com.dfsek.terra.api.event.events.world.generation.LootPopulateEvent;
|
||||
import com.dfsek.terra.api.structure.LootTable;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.structures.script.StructureScript;
|
||||
import com.dfsek.terra.api.util.FastRandom;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
public class BufferedLootApplication implements BufferedItem {
|
||||
private final LootTable table;
|
||||
private final TerraPlugin main;
|
||||
private final StructureScript structure;
|
||||
|
||||
public BufferedLootApplication(LootTable table, TerraPlugin main, StructureScript structure) {
|
||||
this.table = table;
|
||||
this.main = main;
|
||||
this.structure = structure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
try {
|
||||
BlockEntity data = world.getBlockState(origin);
|
||||
if(!(data instanceof Container)) {
|
||||
main.logger().severe("Failed to place loot at " + origin + "; block " + data + " is not container.");
|
||||
return;
|
||||
}
|
||||
Container container = (Container) data;
|
||||
|
||||
LootPopulateEvent event = new LootPopulateEvent(container, table, world.getTerraGenerator().getConfigPack(), structure);
|
||||
main.getEventManager().callEvent(event);
|
||||
if(event.isCancelled()) return;
|
||||
|
||||
event.getTable().fillInventory(container.getInventory(), new FastRandom(origin.hashCode()));
|
||||
data.update(false);
|
||||
} catch(Exception e) {
|
||||
main.logger().warning("Could not apply loot at " + origin + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer.items;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
public class BufferedPulledBlock implements BufferedItem {
|
||||
private final BlockState data;
|
||||
|
||||
public BufferedPulledBlock(BlockState data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
Vector3 mutable = origin.clone();
|
||||
while(mutable.getY() > world.getMinHeight()) {
|
||||
if(!world.getBlockData(mutable).isAir()) {
|
||||
world.setBlockData(mutable, data);
|
||||
break;
|
||||
}
|
||||
mutable.subtract(0, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.structure.buffer.items;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.block.entity.BlockEntity;
|
||||
import com.dfsek.terra.api.structure.buffer.BufferedItem;
|
||||
import com.dfsek.terra.api.vector.Vector3;
|
||||
import com.dfsek.terra.api.world.World;
|
||||
|
||||
public class BufferedStateManipulator implements BufferedItem {
|
||||
private final TerraPlugin main;
|
||||
private final String data;
|
||||
|
||||
public BufferedStateManipulator(TerraPlugin main, String state) {
|
||||
this.main = main;
|
||||
this.data = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paste(Vector3 origin, World world) {
|
||||
try {
|
||||
BlockEntity state = world.getBlockState(origin);
|
||||
state.applyState(data);
|
||||
state.update(false);
|
||||
} catch(Exception e) {
|
||||
main.logger().warning("Could not apply BlockState at " + origin + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.dfsek.terra.api.structures.tokenizer;
|
||||
|
||||
public class Char {
|
||||
private final char character;
|
||||
private final int index;
|
||||
private final int line;
|
||||
|
||||
|
||||
public Char(char character, int index, int line) {
|
||||
this.character = character;
|
||||
this.index = index;
|
||||
this.line = line;
|
||||
}
|
||||
|
||||
public char getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public boolean isWhitespace() {
|
||||
return Character.isWhitespace(character);
|
||||
}
|
||||
|
||||
public boolean isNewLine() {
|
||||
return character == '\n';
|
||||
}
|
||||
|
||||
public boolean isDigit() {
|
||||
return Character.isDigit(character);
|
||||
}
|
||||
|
||||
public boolean is(char... tests) {
|
||||
for(char test : tests) {
|
||||
if(test == character && test != '\0') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isEOF() {
|
||||
return character == '\0';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Character.toString(character);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user