123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821 |
- package me.km.snuviscript;
- import me.km.KajetansMod;
- import me.km.api.GlobalText;
- import me.km.api.Module;
- import me.km.exception.CodeTooLongException;
- import me.km.exception.GoHigherAtRootTreeException;
- import me.km.exception.GotoLabelNotFoundException;
- import me.km.exception.HoldCodeException;
- import me.km.exception.IllegalStringException;
- import me.km.exception.NoChildTreeException;
- import me.km.exception.PrescriptException;
- import java.io.File;
- import java.io.IOException;
- import java.nio.file.Files;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.EmptyStackException;
- import java.util.List;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Stack;
- import java.util.stream.Collectors;
- import me.km.api.Location;
- import net.minecraft.command.ICommandSender;
- import net.minecraft.entity.player.EntityPlayer;
- import net.minecraft.util.text.TextComponentString;
- public class QuestData
- {
- private final QuestParser parser;
-
- private final BenchmarkClock treeClock;
- public final BenchmarkClock exeClock;
- private boolean benchmark;
-
- private final Tree<CodeFunction> code;
- private CodeFunction currentCode;
- private final HashMap<String, Object> variables;
- private final HashMap<String, Integer[]> gotos;
- private final Stack<Integer[]> stack;
- private final HashSet<String> events;
- private final HashSet<Location> loadedLocations;
-
- private boolean isWaiting;
- private boolean isTrying;
- private boolean tryFailed;
- private boolean shouldDoElse;
- private boolean isValid;
- private final Stack<Boolean> whileStack;
- private int overflowProtection;
-
- private String info;
- private String name;
- private final int id;
- private final boolean script;
- private int idCounter;
-
- private final ArrayList<EntityPlayer> quester;
-
- public QuestData(int id, EntityPlayer p, String filename, ICommandSender cs)
- {
- parser = KajetansMod.quest.getQuestParser();
- treeClock = new BenchmarkClock();
- exeClock = new BenchmarkClock();
- benchmark = false;
-
- this.id = id;
-
- code = new Tree<>();
- idCounter = 0;
-
- variables = new HashMap<>();
- gotos = new HashMap<>();
- stack = new Stack<>();
- events = new HashSet<>();
- loadedLocations = new HashSet<>();
- whileStack = new Stack<>();
-
- name = filename;
- isWaiting = false;
- isValid = true;
- overflowProtection = 0;
- isTrying = false;
-
- quester = new ArrayList<>();
-
- info = "Keine Info wurde gesetzt.";
-
- if(p != null)
- {
- quester.add(p);
- script = false;
- }
- else
- {
- script = true;
- }
-
- readCode(filename, cs);
- setVar("quote", "\"");
- }
-
- // -------------------------------------------------------------------------
- // Überladen
- // -------------------------------------------------------------------------
-
- public void loadNewCode(String filename, ICommandSender cs)
- {
- code.clear();
-
- gotos.clear();
- stack.clear();
- whileStack.clear();
-
- name = filename;
-
- readCode(filename, cs);
- isWaiting = false;
- isValid = true;
- }
-
- // -------------------------------------------------------------------------
- // Flow-Control
- // -------------------------------------------------------------------------
-
- public void goDeeper(boolean b) throws NoChildTreeException
- {
- code.goDeeper();
- addWhileMode(b);
- }
-
- public void goHigher()
- {
- try
- {
- code.goHigher();
- }
- catch(GoHigherAtRootTreeException ex)
- {
- }
- }
-
- public String getTreePath()
- {
- return Arrays.asList(code.getCurrentPosition()).stream().map(i -> i.toString()).collect(Collectors.joining(", "));
- }
-
- private void readCode(String filename, ICommandSender cs)
- {
- int line = 0;
- StringBuilder codeLine = new StringBuilder();
- try
- {
- File file = new File("./quests/" + filename + ".txt");
- List<String> lines;
- if(file.exists())
- {
- try
- {
- lines = Files.readAllLines(file.toPath());
- }
- catch (IOException ex)
- {
- throw new PrescriptException("Die Datei '" + filename + "' kann nicht gelesen werden.");
- }
- }
- else
- {
- //System.out.println("Die Datei '" + filename + "' wurde nicht gefunden.");
- throw new PrescriptException("Die Datei '" + filename + "' wurde nicht gefunden.");
- }
- int i = 0;
- int old = 0;
- int bracket = 0;
- boolean text = false;
- boolean bracketEnd = false;
- int bracketEndPos = 0;
- boolean oneLineChild = false;
- boolean comment = false;
- int commentPos = 0;
- while(line < lines.size())
- {
- if(old >= codeLine.length() && !comment)
- {
- codeLine = new StringBuilder(lines.get(line).trim());
- i = 0;
- old = 0;
- //System.out.println("NEU");
- }
- else
- {
- codeLine.append(lines.get(line).trim());
- //System.out.println("APPEND");
- }
- //System.out.println(codeLine);
- while(i < codeLine.length())
- {
- switch(codeLine.charAt(i))
- {
- case '"':
- if(!comment)
- {
- text = !text;
- }
- break;
- case '@':
- if(comment || text)
- {
- break;
- }
- old = i;
- while(i < codeLine.length() && codeLine.charAt(i) != ' ')
- {
- i++;
- }
- try
- {
- code.selectLastChild(); // Nur für richtige Position
- }
- catch(NoChildTreeException ex)
- {
- }
- String s = codeLine.substring(old + 1, i);
- if(gotos.put(s, code.getCurrentPosition()) != null)
- {
- throw new PrescriptException("Doppeltes Goto: " + s + " - " + (line + 1));
- }
- codeLine.delete(old, i + 1);
- i = old - 1;
- break;
- case '/':
- if(text)
- {
- break;
- }
- if(!comment && i + 1 < codeLine.length() && codeLine.charAt(i + 1) == '*')
- {
- comment = true;
- commentPos = i;
- }
- if(!comment && i + 1 < codeLine.length() && codeLine.charAt(i + 1) == '/')
- {
- codeLine.delete(i, codeLine.length());
- old = codeLine.length() + 1;
- }
- break;
- case '*':
- if(text)
- {
- break;
- }
- if(comment && i + 1 < codeLine.length() && codeLine.charAt(i + 1) == '/')
- {
- comment = false;
- codeLine.delete(commentPos, i + 2);
- i = commentPos;
- }
- break;
- case ';':
- if(comment || text)
- {
- break;
- }
- if(bracket != 0)
- {
- //System.out.println(bracket);
- throw new PrescriptException("; aber Klammern ungültig - " + (line + 1));
- }
- bracketEnd = false;
- code.addChild(new CodeFunction(codeLine.substring(old, i)), line);
- old = i + 1;
- if(oneLineChild)
- {
- oneLineChild = false;
- try
- {
- code.goHigher();
- }
- catch(GoHigherAtRootTreeException ex)
- {
- throw new PrescriptException("Das sollte nicht passieren - " + (line + 1));
- }
- }
- bracket = 0;
- break;
- case '(':
- if(!comment && !text)
- {
- bracket++;
- if(bracketEnd && !oneLineChild)
- {
- bracketEnd = false;
- oneLineChild = true;
- code.addChild(new CodeFunction(codeLine.substring(old, bracketEndPos)), line);
- old = bracketEndPos;
- try
- {
- code.selectLastChild();
- code.goDeeper();
- }
- catch(NoChildTreeException ex)
- {
- throw new PrescriptException("Das sollte nicht passieren - " + (line + 1));
- }
- }
- }
- break;
- case ')':
- if(comment || text)
- {
- break;
- }
- bracket--;
- if(oneLineChild)
- {
- break;
- }
- if(bracket < 0)
- {
- throw new PrescriptException(") ohne ( - " + (line + 1));
- }
- if(bracket == 0)
- {
- bracketEnd = true;
- bracketEndPos = i + 1;
- }
- break;
- case '{':
- if(comment || text)
- {
- break;
- }
- bracketEnd = false;
- code.addChild(new CodeFunction(codeLine.substring(old, i)), line);
- old = i + 1;
- try
- {
- code.selectLastChild();
- code.goDeeper();
- }
- catch(NoChildTreeException ex)
- {
- throw new PrescriptException("Das sollte nicht passieren - " + (line + 1));
- }
- break;
- case '}':
- if(comment || text)
- {
- break;
- }
- old = i + 1;
- try
- {
- code.goHigher();
- }
- catch(GoHigherAtRootTreeException ex)
- {
- throw new PrescriptException("} ohne { - " + (line + 1));
- }
- break;
- }
- i++;
- }
- line++;
- }
- code.goToRoot();
- }
- catch(Exception ex)
- {
- if(parser.printStack)
- {
- ex.printStackTrace();
- }
- resetOverflowProtection();
- Module m = KajetansMod.quest;
- int id = script ? 1 : 0;
- m.send(cs, "§cError in", id);
- m.sendHelpListElement(cs, "§cScript", getName(), id);
- m.sendHelpListElement(cs, "§cZeile", codeLine.toString(), id);
- m.sendHelpListElement(cs, "§cZeilennummer", String.valueOf(line + 1), id);
- if(ex.getLocalizedMessage() == null)
- {
- m.sendHelpListElement(cs, "§cException", ex.getClass().getSimpleName(), id);
- }
- else
- {
- m.sendHelpListElement(cs, "§cException", ex.getClass().getSimpleName() + " - " + ex.getLocalizedMessage(), id);
- }
- if(ex instanceof IllegalStringException)
- {
- m.sendHelpListElement(cs, "§cUngültiger Wert", ((IllegalStringException) ex).getBadString(), id);
- }
- KajetansMod.quest.term(this);
- }
- }
-
- public void runCode()
- {
- try
- {
- while(!isWaiting)
- {
- treeClock.pushTime(benchmark);
- try
- {
- //System.out.println("NEXT");
- code.selectNextChild();
- }
- catch(NoChildTreeException ex)
- {
- //System.out.println("NACH OBEN!");
- code.goHigher();
- setTryMode(false);
- setElseMode(false);
- if(removeWhileMode())
- {
- increaseOverflowProtection();
- code.selectPreviousChild();
- }
- treeClock.pushTime(benchmark);
- continue;
- }
- currentCode = code.getCurrentChildData();
- treeClock.pushTime(benchmark);
- //System.out.println(currentCode.getFunction());
- //System.out.println(currentCode);
- //System.out.println("AUFRUF");
- //findFunction(currentCode, 0, currentCode.length() - 1);
- doFunction(currentCode);
- }
- }
- catch(NoChildTreeException | GoHigherAtRootTreeException ex)
- {
- KajetansMod.quest.term(this);
- }
- catch(HoldCodeException ex2)
- {
- }
- catch(CodeTooLongException | PrescriptException ex3)
- {
- parser.printQuestException(this, ex3, currentCode.toString());
- }
- }
-
- public void runCodeLine(String c, ICommandSender cs)
- {
- try
- {
- doFunction(new CodeFunction(c));
- }
- catch(HoldCodeException ex)
- {
- }
- catch(Exception ex)
- {
- if(ex instanceof IllegalStringException)
- {
- KajetansMod.quest.send(cs, ((IllegalStringException) ex).getBadString(), script ? 1 : 0);
- }
- else
- {
- KajetansMod.quest.send(cs, ex.getClass().getSimpleName(), script ? 1 : 0);
- }
- }
- }
-
- private Object doFunction(CodeFunction cf)
- {
- Object[] old = cf.getParameters();
- Object[] newPars = new Object[old.length];
- for(int i = 0; i < old.length; i++)
- {
- if(old[i] != null && old[i].getClass() == CodeFunction.class)
- {
- newPars[i] = readParameter(doFunction((CodeFunction) old[i]));
- continue;
- }
- newPars[i] = readParameter(old[i]);
- }
- return parser.parseFunction(this, cf.getFunction(), newPars);
- }
-
- private Object readParameter(Object o)
- {
- if(o != null && o.getClass() == Variable.class)
- {
- return getVar(o.toString());
- }
- return o;
- }
-
- public int getActualCodeLine()
- {
- return code.getActualCodeLine();
- }
- // -------------------------------------------------------------------------
- // Quest / Scriptdaten
- // -------------------------------------------------------------------------
-
- public boolean isScript()
- {
- return script;
- }
-
- public int getId()
- {
- return id;
- }
-
- public String getInfo()
- {
- return info;
- }
-
- public void setInfo(String t)
- {
- info = t;
- }
- public String getName()
- {
- return name;
- }
-
- // -------------------------------------------------------------------------
- // Wait für Zeitutils
- // -------------------------------------------------------------------------
-
- public boolean isWaiting()
- {
- return isWaiting;
- }
-
- public void setIsWaiting(boolean b)
- {
- isWaiting = b;
- }
-
- // -------------------------------------------------------------------------
- // Valid
- // -------------------------------------------------------------------------
-
- public boolean isValid()
- {
- return isValid;
- }
-
- public void setIsValid(Boolean bool)
- {
- isValid = bool;
- }
-
- // -------------------------------------------------------------------------
- // Variablen
- // -------------------------------------------------------------------------
- public void setVar(String var, Object value)
- {
- variables.put(var, value);
- }
-
- public void setVar(Object var, Object value)
- {
- setVar(var.toString(), value);
- }
-
- public HashMap<String, Object> getVars()
- {
- return variables;
- }
-
- public Object getVar(String var)
- {
- return variables.get(var);
- }
-
- public Object getVar(Object var)
- {
- return getVar(var.toString());
- }
-
- public boolean getBoolean(String var)
- {
- try
- {
- return (boolean) getVar(var);
- }
- catch(ClassCastException | NullPointerException ex)
- {
- return false;
- }
- }
-
- public void removeVar(String var)
- {
- variables.remove(var);
- }
-
- // -------------------------------------------------------------------------
- // Goto
- // -------------------------------------------------------------------------
-
- public void gotoLabel(String label) throws NoChildTreeException, CodeTooLongException
- {
- Integer[] i = gotos.get(label);
- if(i == null)
- {
- throw new GotoLabelNotFoundException(label);
- }
- increaseOverflowProtection();
- resetWhileMode();
- setTryMode(false);
- code.goToPosition(i);
- }
-
- public void gotoLabelWithReturn(String label) throws NoChildTreeException, CodeTooLongException
- {
- stack.push(code.getCurrentPosition());
- gotoLabel(label);
- }
-
- public void doReturn() throws NoChildTreeException
- {
- code.goToPosition(stack.pop());
- /*try
- {
- code.selectNextChild();
- }
- catch(NoChildTreeException ex)
- {
- code.goHigher();
- }*/
- }
-
- public void resetOverflowProtection()
- {
- overflowProtection = 0;
- }
-
- public void increaseOverflowProtection() throws CodeTooLongException
- {
- overflowProtection++;
- if(overflowProtection > 1000)
- {
- overflowProtection = 0;
- throw new CodeTooLongException();
- }
- }
-
- // -------------------------------------------------------------------------
- // Event Handling
- // -------------------------------------------------------------------------
-
- public void loadEvent(String event)
- {
- events.add(event);
- }
-
- public void unloadEvent(String event)
- {
- events.remove(event);
- }
-
- public boolean isEventLoaded(String event)
- {
- return events.contains(event);
- }
-
- // -------------------------------------------------------------------------
- // Player Handling
- // -------------------------------------------------------------------------
-
- public void addPlayer(EntityPlayer p)
- {
- quester.add(p);
- }
-
- public boolean removePlayer(EntityPlayer p)
- {
- quester.remove(p);
- return quester.isEmpty();
- }
-
- public List<EntityPlayer> getPlayers()
- {
- return quester;
- }
-
- public List<String> getPlayerNames()
- {
- return getPlayers().stream().map(p -> p.getName()).collect(Collectors.toList());
- }
-
- // -------------------------------------------------------------------------
- // Location Handling für Wait-For-Location
- // -------------------------------------------------------------------------
-
- public void addLocation(Location l)
- {
- loadedLocations.add(l);
- }
-
- public boolean removeLocation(Location l)
- {
- return loadedLocations.remove(l);
- }
-
- public void clearLocations()
- {
- loadedLocations.clear();
- }
-
- // -------------------------------------------------------------------------
- // Try-Catch Handler
- // -------------------------------------------------------------------------
-
- public void setTryMode(boolean b)
- {
- isTrying = b;
- }
-
- public boolean getTryMode()
- {
- return isTrying;
- }
-
- public void setTryFail(boolean b)
- {
- tryFailed = b;
- }
-
- public boolean getTryFail()
- {
- return tryFailed;
- }
-
- // -------------------------------------------------------------------------
- // While Handler
- // -------------------------------------------------------------------------
-
- private void addWhileMode(boolean b)
- {
- whileStack.push(b);
- }
-
- public boolean removeWhileMode()
- {
- try
- {
- return whileStack.pop();
- }
- catch(EmptyStackException ex)
- {
- return false;
- }
- }
-
- public void resetWhileMode()
- {
- whileStack.clear();
- }
-
- // -------------------------------------------------------------------------
- // Else Handler
- // -------------------------------------------------------------------------
-
- public void setElseMode(boolean b)
- {
- shouldDoElse = b;
- }
-
- public boolean getElseMode()
- {
- return shouldDoElse;
- }
-
- // -------------------------------------------------------------------------
- // Für Inventar-IDs
- // -------------------------------------------------------------------------
-
- public int getNewId()
- {
- idCounter++;
- return idCounter;
- }
-
- // -------------------------------------------------------------------------
- // Für Benchmarks
- // -------------------------------------------------------------------------
-
- public void clearBenchmark()
- {
- exeClock.clear();
- treeClock.clear();
- }
-
- public boolean isBenchmarking()
- {
- return benchmark;
- }
-
- public void toggleBenchmark()
- {
- benchmark = !benchmark;
- }
-
- public void printBenchmarks(ICommandSender cs)
- {
- cs.sendMessage(new TextComponentString(GlobalText.Spacer()));
- cs.sendMessage(new TextComponentString("Ausführung: " + exeClock.getSummedTime() + " ms"));
- cs.sendMessage(new TextComponentString("Baum: " + treeClock.getSummedTime() + " ms"));
- }
- }
|