mirror of
https://github.com/badvision/lawless-legends.git
synced 2024-06-16 20:29:30 +00:00
268 lines
8.9 KiB
Java
268 lines
8.9 KiB
Java
/*
|
|
* Copyright (C) 2015 The 8-Bit Bunch. Licensed under the Apache License, Version 1.1
|
|
* (the "License"); you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at <http://www.apache.org/licenses/LICENSE-1.1>.
|
|
* Unless required by applicable law or agreed to in writing, software distributed under
|
|
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
|
* ANY KIND, either express or implied. See the License for the specific language
|
|
* governing permissions and limitations under the License.
|
|
*/
|
|
package org.badvision.outlaweditor.data;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
|
|
import org.badvision.outlaweditor.api.ApplicationState;
|
|
import org.badvision.outlaweditor.api.Platform;
|
|
import org.badvision.outlaweditor.data.xml.Map;
|
|
import org.badvision.outlaweditor.data.xml.Map.Chunk;
|
|
import org.badvision.outlaweditor.data.xml.ObjectFactory;
|
|
import org.badvision.outlaweditor.data.xml.Script;
|
|
import org.badvision.outlaweditor.data.xml.Script.LocationTrigger;
|
|
import org.badvision.outlaweditor.data.xml.Scripts;
|
|
import org.badvision.outlaweditor.data.xml.Tile;
|
|
import org.badvision.outlaweditor.ui.UIAction;
|
|
|
|
import jakarta.xml.bind.JAXBElement;
|
|
import javafx.scene.control.Alert;
|
|
import javafx.scene.image.WritableImage;
|
|
import javafx.scene.paint.Color;
|
|
|
|
/**
|
|
*
|
|
* @author brobert
|
|
*/
|
|
public class TileMap extends ArrayList<ArrayList<Tile>> implements Serializable {
|
|
|
|
public static final long serialVersionUID = 6486309334559843742L;
|
|
Map backingMap;
|
|
boolean backingMapStale;
|
|
int width;
|
|
int height;
|
|
|
|
public TileMap(Map m) {
|
|
backingMapStale = false;
|
|
width = 0;
|
|
height = 0;
|
|
loadFromMap(m);
|
|
}
|
|
|
|
public static final double SATURATION = 0.70;
|
|
public static final double VALUE = 1.0;
|
|
public static double HUE = 180;
|
|
private final java.util.Map<Integer, List<Script>> locationScripts = new HashMap<>();
|
|
private final java.util.Map<Script, Color> scriptColors = new HashMap<>();
|
|
|
|
public Optional<Color> getScriptColor(Script s) {
|
|
return Optional.ofNullable(scriptColors.get(s));
|
|
}
|
|
|
|
public List<Script> getLocationScripts(int x, int y) {
|
|
List<Script> list = locationScripts.get(getMortonNumber(x, y));
|
|
if (list != null) {
|
|
return list;
|
|
} else {
|
|
return Collections.EMPTY_LIST;
|
|
}
|
|
}
|
|
|
|
public void putLocationScript(int x, int y, Script s) {
|
|
if (x < 0 || y < 0) {
|
|
return;
|
|
}
|
|
LocationTrigger trigger = new Script.LocationTrigger();
|
|
trigger.setX(x);
|
|
trigger.setY(y);
|
|
s.getLocationTrigger().add(trigger);
|
|
registerLocationScript(x, y, s);
|
|
}
|
|
|
|
public void removeLocationScripts(int x, int y) {
|
|
int loc = getMortonNumber(x, y);
|
|
List<Script> scripts = locationScripts.get(loc);
|
|
if (scripts != null) {
|
|
scripts.forEach(s -> {
|
|
s.getLocationTrigger().removeIf(t -> {
|
|
return t.getX() == x && t.getY() == y;
|
|
});
|
|
});
|
|
}
|
|
locationScripts.remove(loc);
|
|
ApplicationState.getInstance().getController().redrawScripts();
|
|
}
|
|
|
|
private void registerLocationScript(int x, int y, Script s) {
|
|
if (!scriptColors.containsKey(s)) {
|
|
scriptColors.put(s, Color.hsb(HUE, SATURATION, 0.75 + Math.cos(HUE / Math.PI / 2.0) / 8.0));
|
|
HUE = (HUE + 27) % 360;
|
|
}
|
|
int loc = getMortonNumber(x, y);
|
|
List<Script> list = locationScripts.get(loc);
|
|
if (list == null) {
|
|
list = new ArrayList<>();
|
|
locationScripts.put(loc, list);
|
|
}
|
|
list.add(s);
|
|
ApplicationState.getInstance().getController().redrawScripts();
|
|
}
|
|
|
|
private int getMortonNumber(int x, int y) {
|
|
int morton = 0;
|
|
for (int i = 0; i < 16; i++) {
|
|
int mask = 1 << (i);
|
|
morton += (x & mask) << (i + 1);
|
|
morton += (y & mask) << i;
|
|
}
|
|
return morton;
|
|
}
|
|
|
|
public Tile get(int x, int y) {
|
|
if (size() <= y || get(y) == null) {
|
|
return null;
|
|
}
|
|
if (get(y).size() <= x) {
|
|
return null;
|
|
}
|
|
return get(y).get(x);
|
|
}
|
|
|
|
public void put(int x, int y, Tile t) {
|
|
if (x < 0 || y < 0) {
|
|
return;
|
|
}
|
|
width = Math.max(x + 1, width);
|
|
height = Math.max(y + 1, height);
|
|
for (int i = size(); i <= y; i++) {
|
|
add(null);
|
|
}
|
|
if (get(y) == null) {
|
|
set(y, new ArrayList<>());
|
|
}
|
|
List<Tile> row = get(y);
|
|
for (int i = row.size(); i <= x; i++) {
|
|
row.add(null);
|
|
}
|
|
row.set(x, t);
|
|
backingMapStale = true;
|
|
}
|
|
|
|
public Map getBackingMap() {
|
|
return backingMap;
|
|
}
|
|
|
|
public void updateBackingMap() {
|
|
ObjectFactory f = new ObjectFactory();
|
|
backingMap.getChunk().clear();
|
|
Chunk c = new Map.Chunk();
|
|
c.setX(0);
|
|
c.setY(0);
|
|
for (int y = 0; y < height; y++) {
|
|
List<String> row = new ArrayList<>();
|
|
for (int x = 0; x < width; x++) {
|
|
Tile t = get(x, y);
|
|
if (t == null) {
|
|
row.add(NULL_TILE_ID);
|
|
} else {
|
|
row.add(TileUtils.getId(t));
|
|
}
|
|
}
|
|
c.getRow().add(f.createMapChunkRow(row));
|
|
}
|
|
backingMap.getChunk().add(c);
|
|
backingMapStale = false;
|
|
}
|
|
|
|
private void loadFromMap(Map m) {
|
|
clear();
|
|
locationScripts.clear();
|
|
width = 0;
|
|
height = 0;
|
|
Set<Tile> unknownTiles = new HashSet<>();
|
|
Scripts scripts = m.getScripts();
|
|
if (scripts != null) {
|
|
List<Script> allScripts = new ArrayList<>(scripts.getScript());
|
|
allScripts.forEach(
|
|
s -> s.getLocationTrigger().forEach(
|
|
l -> registerLocationScript(l.getX(), l.getY(), s)
|
|
)
|
|
);
|
|
}
|
|
m.getChunk().forEach(c -> {
|
|
int y = c.getY();
|
|
for (JAXBElement<List<String>> row : c.getRow()) {
|
|
int x = c.getX();
|
|
for (String tileId : row.getValue()) {
|
|
Tile t = null;
|
|
if (!isNullTile(tileId)) {
|
|
t = TilesetUtils.getTileById(tileId);
|
|
if (t == null) {
|
|
t = new Tile();
|
|
unknownTiles.add(t);
|
|
Platform p = ApplicationState.getInstance().getCurrentPlatform();
|
|
WritableImage img = UIAction.getBadImage(p.tileRenderer.getWidth(), p.tileRenderer.getHeight());
|
|
TileUtils.setImage(t, p, img);
|
|
}
|
|
}
|
|
put(x, y, t);
|
|
x++;
|
|
}
|
|
y++;
|
|
}
|
|
});
|
|
if (!unknownTiles.isEmpty()) {
|
|
int numMissing = unknownTiles.size();
|
|
Alert missingTileAlert = new Alert(Alert.AlertType.WARNING);
|
|
missingTileAlert.setContentText(
|
|
(numMissing > 1
|
|
? "There were " + numMissing + " missing tiles." : "There was a missing tile. ")
|
|
+ "Blank placeholders have been added.");
|
|
missingTileAlert.showAndWait();
|
|
}
|
|
backingMap = m;
|
|
backingMapStale = false;
|
|
}
|
|
public static String NULL_TILE_ID = "_";
|
|
|
|
public static boolean isNullTile(String tileId) {
|
|
return tileId.equalsIgnoreCase(NULL_TILE_ID);
|
|
}
|
|
|
|
public void clearScriptTriggersFromMap(Script script) {
|
|
script.getLocationTrigger().clear();
|
|
locationScripts.values().stream().filter((scripts) -> !(scripts == null)).forEach((scripts) -> {
|
|
scripts.remove(script);
|
|
});
|
|
}
|
|
|
|
public void removeScriptFromMap(Script script) {
|
|
clearScriptTriggersFromMap(script);
|
|
backingMap.getScripts().getScript().remove(script);
|
|
}
|
|
|
|
public void shift(int xAmt, int yAmt) {
|
|
Scripts scripts = backingMap.getScripts();
|
|
if (scripts != null) {
|
|
List<Script> allScripts = new ArrayList<>(scripts.getScript());
|
|
allScripts.forEach(
|
|
s -> s.getLocationTrigger().forEach(
|
|
l -> {
|
|
l.setX(l.getX() + xAmt);
|
|
l.setY(l.getY() + yAmt);
|
|
}
|
|
)
|
|
);
|
|
}
|
|
backingMap.getChunk().forEach(c -> {
|
|
c.setX(c.getX() + xAmt);
|
|
c.setY(c.getY() + yAmt);
|
|
});
|
|
loadFromMap(backingMap);
|
|
}
|
|
}
|