package me.hammerle.supersnuvi.gamelogic; import java.io.File; import java.util.LinkedList; import java.util.TreeSet; import java.util.function.Consumer; import me.hammerle.snuviscript.code.Script; import me.hammerle.supersnuvi.Game; import me.hammerle.supersnuvi.Keys; import me.hammerle.supersnuvi.entity.Entity; import me.hammerle.supersnuvi.entity.EntityBuilder; import me.hammerle.supersnuvi.tiles.Tile; import me.hammerle.supersnuvi.util.Utils; public final class FileLevel extends Level { // level data private final LevelData data; private final String name; private final String fileName; // level stats private int souls = 0; private int maxSouls = 0; private float time = 0.0f; private final LinkedList messages = new LinkedList<>(); // controlling private TreeSet spawns = new TreeSet<>(); // scripting private Script levelScript = null; public FileLevel(File f) { this.data = new LevelData(f); if(!data.load()) { throw new IllegalArgumentException(f + " is not a valid level."); } this.name = data.getString("name", "error"); data.forEachInteractTile((x, y, tile) -> { Tile t = Game.get().getTile(tile); if(t != null) { maxSouls += t.getBottleScore(); } if(tile == 24) // start tile { spawns.add(new Point(x, y - 1)); } }); data.forEachEntity((x, y, tile) -> { if(tile == 1) { maxSouls++; } }, 0, data.getWidth(), 0, data.getHeight()); fileName = f.getName(); // there must be at least one spawn if(spawns.isEmpty()) { spawns.add(new Point(5, 5)); } // make sure hero is spawned before any script starts reset(); String scriptName = f.getPath().replace(".map", ""); // mark current level as active to make currentLevel calls work Level l = Game.get().getCurrentLevel(); Game.get().setCurrentLevel(this); levelScript = Game.get().getParser().startScript(false, ".snuvi", scriptName); // call level reset here, because levelScript was null in resetLevel() callEvent("level_reset"); // mark previous level as active Game.get().setCurrentLevel(l); } // ------------------------------------------------------------------------- // level data // ------------------------------------------------------------------------- @Override public LevelData getData() { return data; } @Override public String getName() { return name; } @Override public String getFileName() { return fileName; } @Override public void addMessage(String message) { messages.add(message); } @Override public String getMessage() { return messages.isEmpty() ? null : messages.getFirst(); } // ------------------------------------------------------------------------- // level stats // ------------------------------------------------------------------------- @Override public int getCurrentBottles() { return souls; } @Override public int getMaxBottles() { return maxSouls; } @Override public void addBottles(int score) { souls += score; } @Override public float getTime() { return time; } // ------------------------------------------------------------------------- // controlling // ------------------------------------------------------------------------- @Override public void tick() { if(!messages.isEmpty() && Keys.ENTER.getTime() == 1) { messages.removeFirst(); } time += Game.SECS_PER_TICK; Game.get().tickTiles(); tickEntities(); } @Override protected void onReset() { Game.get().resetTiles(this); data.activateEntities(); souls = 0; time = 0.0f; Entity h = spawnHero(true); setHero(h); removeEntities(); spawnEntity(h); messages.clear(); setAmbientLight(1.0f, 1.0f, 1.0f); getTileUpdater().updateAll(); callEvent("level_reset"); } public Entity spawnHero(boolean first) { Point p; if(getHero() == null || getHero().getX() < 0 || first) { // first spawn or out of map, use first spawn p = spawns.first(); } else { // hero is somewhere in the map, getting last spawn p = spawns.floor(new Point(Utils.toBlock(getHero().getX()), Utils.toBlock(getHero().getY()))); if(p == null) { p = spawns.first(); } } return EntityBuilder.buildHero(this, Utils.toCoord(p.getX()), Utils.toCoord(p.getY())); } // ------------------------------------------------------------------------- // scripting // ------------------------------------------------------------------------- @Override public void callEvent(String name, Consumer