Checkpoint with more updates and a decent single unit pathing experience

This commit is contained in:
Retera 2020-07-25 20:31:10 -04:00
parent d5a1ee643d
commit dcb68ba6c9
25 changed files with 3153 additions and 211 deletions

View File

@ -4,7 +4,7 @@ import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.Arrays; import java.util.ArrayList;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -36,9 +36,12 @@ import com.etheller.warsmash.datasources.CompoundDataSourceDescriptor;
import com.etheller.warsmash.datasources.DataSource; import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.datasources.DataSourceDescriptor; import com.etheller.warsmash.datasources.DataSourceDescriptor;
import com.etheller.warsmash.datasources.FolderDataSourceDescriptor; import com.etheller.warsmash.datasources.FolderDataSourceDescriptor;
import com.etheller.warsmash.datasources.MpqDataSourceDescriptor;
import com.etheller.warsmash.parsers.fdf.GameUI; import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.jass.Jass2; import com.etheller.warsmash.parsers.jass.Jass2;
import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener; import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.units.Element;
import com.etheller.warsmash.util.DataSourceFileHandle; import com.etheller.warsmash.util.DataSourceFileHandle;
import com.etheller.warsmash.util.ImageUtils; import com.etheller.warsmash.util.ImageUtils;
import com.etheller.warsmash.util.WarsmashConstants; import com.etheller.warsmash.util.WarsmashConstants;
@ -97,6 +100,11 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
private final List<Message> messages = new LinkedList<>(); private final List<Message> messages = new LinkedList<>();
private MdxModel timeIndicator; private MdxModel timeIndicator;
private final DataTable warsmashIni;
public WarsmashGdxMapGame(final DataTable warsmashIni) {
this.warsmashIni = warsmashIni;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
@ -118,24 +126,32 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER); final String renderer = Gdx.gl.glGetString(GL20.GL_RENDERER);
System.err.println("Renderer: " + renderer); System.err.println("Renderer: " + renderer);
final FolderDataSourceDescriptor war3mpq = new FolderDataSourceDescriptor("E:\\Backups\\Warcraft\\Data\\127"); final Element dataSourcesConfig = this.warsmashIni.get("DataSources");
final FolderDataSourceDescriptor smashmpq = new FolderDataSourceDescriptor("..\\..\\resources"); final int dataSourcesCount = dataSourcesConfig.getFieldValue("Count");
// final FolderDataSourceDescriptor war3mpq = new FolderDataSourceDescriptor( final List<DataSourceDescriptor> dataSourcesList = new ArrayList<>();
// "D:\\NEEDS_ORGANIZING\\MPQBuild\\War3.mpq\\war3.mpq"); for (int i = 0; i < dataSourcesCount; i++) {
// final FolderDataSourceDescriptor war3xLocalmpq = new FolderDataSourceDescriptor( final String type = dataSourcesConfig.getField("Type" + (i < 10 ? "0" : "") + i);
// "D:\\NEEDS_ORGANIZING\\MPQBuild\\War3xLocal.mpq\\enus-war3local.mpq"); final String path = dataSourcesConfig.getField("Path" + (i < 10 ? "0" : "") + i);
// final FolderDataSourceDescriptor rebirth = new FolderDataSourceDescriptor( switch (type) {
// "E:\\Games\\Warcraft III Patch 1.31 Rebirth"); case "Folder": {
final FolderDataSourceDescriptor testingFolder = new FolderDataSourceDescriptor("E:\\Backups\\Warsmash\\Data"); dataSourcesList.add(new FolderDataSourceDescriptor(path));
final FolderDataSourceDescriptor currentFolder = new FolderDataSourceDescriptor("."); break;
this.codebase = new CompoundDataSourceDescriptor(Arrays.<DataSourceDescriptor>asList(war3mpq, smashmpq, }
/* war3xLocalmpq, */ testingFolder, currentFolder)).createDataSource(); case "MPQ": {
dataSourcesList.add(new MpqDataSourceDescriptor(path));
break;
}
default:
throw new RuntimeException("Unknown data source type: " + type);
}
}
this.codebase = new CompoundDataSourceDescriptor(dataSourcesList).createDataSource();
this.viewer = new War3MapViewer(this.codebase, this); this.viewer = new War3MapViewer(this.codebase, this);
this.viewer.worldScene.enableAudio(); this.viewer.worldScene.enableAudio();
this.viewer.enableAudio(); this.viewer.enableAudio();
try { try {
this.viewer.loadMap("Maps\\Campaign\\NightElf03.w3m"); this.viewer.loadMap(this.warsmashIni.get("Map").getField("FilePath"));
} }
catch (final IOException e) { catch (final IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@ -249,8 +265,10 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
this.minimap.y + ((this.minimap.height - minimapFilledHeight) / 2), minimapFilledWidth, this.minimap.y + ((this.minimap.height - minimapFilledHeight) / 2), minimapFilledWidth,
minimapFilledHeight); minimapFilledHeight);
this.cameraManager.target.x = this.viewer.startLocations[0].x; if (this.viewer.startLocations[0] != null) {
this.cameraManager.target.y = this.viewer.startLocations[0].y; this.cameraManager.target.x = this.viewer.startLocations[0].x;
this.cameraManager.target.y = this.viewer.startLocations[0].y;
}
this.shapeRenderer = new ShapeRenderer(); this.shapeRenderer = new ShapeRenderer();
this.talentTreeWindow = new Rectangle(100, 300, 1400, 800); this.talentTreeWindow = new Rectangle(100, 300, 1400, 800);
@ -592,7 +610,8 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
} }
if (button == Input.Buttons.RIGHT) { if (button == Input.Buttons.RIGHT) {
final RenderUnit rayPickUnit = this.viewer.rayPickUnit(screenX, worldScreenY); final RenderUnit rayPickUnit = this.viewer.rayPickUnit(screenX, worldScreenY);
if ((rayPickUnit != null) && (rayPickUnit.playerIndex != this.selectedUnit.playerIndex)) { if ((rayPickUnit != null) && (this.selectedUnit != null)
&& (rayPickUnit.playerIndex != this.selectedUnit.playerIndex)) {
if (this.viewer.orderSmart(rayPickUnit)) { if (this.viewer.orderSmart(rayPickUnit)) {
StandSequence.randomPortraitTalkSequence(this.portraitCameraManager.modelInstance); StandSequence.randomPortraitTalkSequence(this.portraitCameraManager.modelInstance);
this.selectedSoundCount = 0; this.selectedSoundCount = 0;

View File

@ -71,6 +71,7 @@ public final class GameUI extends AbstractUIFrame implements UIFrame {
final DataSourceFDFParserBuilder dataSourceFDFParserBuilder = new DataSourceFDFParserBuilder(this.dataSource); final DataSourceFDFParserBuilder dataSourceFDFParserBuilder = new DataSourceFDFParserBuilder(this.dataSource);
final FrameDefinitionVisitor fdfVisitor = new FrameDefinitionVisitor(this.templates, final FrameDefinitionVisitor fdfVisitor = new FrameDefinitionVisitor(this.templates,
dataSourceFDFParserBuilder); dataSourceFDFParserBuilder);
System.err.println("Loading TOC file: " + tocFilePath);
try (BufferedReader reader = new BufferedReader( try (BufferedReader reader = new BufferedReader(
new InputStreamReader(this.dataSource.getResourceAsStream(tocFilePath)))) { new InputStreamReader(this.dataSource.getResourceAsStream(tocFilePath)))) {
String line; String line;

View File

@ -19,8 +19,10 @@ public class Player {
private final float[] startLocation = new float[2]; private final float[] startLocation = new float[2];
private long allyLowPriorities; private long allyLowPriorities;
private long allyHighPriorities; private long allyHighPriorities;
private long enemyLowPrioritiesFlags;
private long enemyHighPrioritiesFlags;
public void load(final LittleEndianDataInputStream stream) throws IOException { public void load(final LittleEndianDataInputStream stream, final int version) throws IOException {
this.id = ParseUtils.readWar3ID(stream); this.id = ParseUtils.readWar3ID(stream);
this.type = stream.readInt(); this.type = stream.readInt();
this.race = stream.readInt(); this.race = stream.readInt();
@ -29,6 +31,10 @@ public class Player {
ParseUtils.readFloatArray(stream, this.startLocation); ParseUtils.readFloatArray(stream, this.startLocation);
this.allyLowPriorities = ParseUtils.readUInt32(stream); this.allyLowPriorities = ParseUtils.readUInt32(stream);
this.allyHighPriorities = ParseUtils.readUInt32(stream); this.allyHighPriorities = ParseUtils.readUInt32(stream);
if (version > 30) {
enemyLowPrioritiesFlags = ParseUtils.readUInt32(stream);
enemyHighPrioritiesFlags = ParseUtils.readUInt32(stream);
}
} }
public void save(final LittleEndianDataOutputStream stream) throws IOException { public void save(final LittleEndianDataOutputStream stream) throws IOException {

View File

@ -43,7 +43,7 @@ public class War3MapW3i {
private String soundEnvironment; private String soundEnvironment;
private char lightEnvironmentTileset; private char lightEnvironmentTileset;
private final short[] waterVertexColor = new short[4]; private final short[] waterVertexColor = new short[4];
private final short[] unknown2 = new short[4]; private final short[] unknown2ProbablyLua = new short[4];
private final List<Player> players = new ArrayList<>(); private final List<Player> players = new ArrayList<>();
private final List<Force> forces = new ArrayList<>(); private final List<Force> forces = new ArrayList<>();
private final List<UpgradeAvailabilityChange> upgradeAvailabilityChanges = new ArrayList<>(); private final List<UpgradeAvailabilityChange> upgradeAvailabilityChanges = new ArrayList<>();
@ -106,13 +106,17 @@ public class War3MapW3i {
} }
if (this.version > 27) { if (this.version > 27) {
ParseUtils.readUInt8Array(stream, this.unknown2); ParseUtils.readUInt8Array(stream, this.unknown2ProbablyLua);
}
if (this.version > 30) {
final long supportedModes = ParseUtils.readUInt32(stream);
final long gameDataVersion = ParseUtils.readUInt32(stream);
} }
for (int i = 0, l = stream.readInt(); i < l; i++) { for (int i = 0, l = stream.readInt(); i < l; i++) {
final Player player = new Player(); final Player player = new Player();
player.load(stream); player.load(stream, this.version);
this.players.add(player); this.players.add(player);
} }
@ -125,37 +129,49 @@ public class War3MapW3i {
this.forces.add(force); this.forces.add(force);
} }
for (int i = 0, l = stream.readInt(); i < l; i++) { if (stream.available() == 1) {
final UpgradeAvailabilityChange upgradeAvailabilityChange = new UpgradeAvailabilityChange(); // some kind of really stupid protected map???
return;
}
if (stream.available() > 0) {
for (int i = 0, l = stream.readInt(); i < l; i++) {
final UpgradeAvailabilityChange upgradeAvailabilityChange = new UpgradeAvailabilityChange();
upgradeAvailabilityChange.load(stream); upgradeAvailabilityChange.load(stream);
this.upgradeAvailabilityChanges.add(upgradeAvailabilityChange); this.upgradeAvailabilityChanges.add(upgradeAvailabilityChange);
}
} }
for (int i = 0, l = stream.readInt(); i < l; i++) { if (stream.available() > 0) {
final TechAvailabilityChange techAvailabilityChange = new TechAvailabilityChange(); for (int i = 0, l = stream.readInt(); i < l; i++) {
final TechAvailabilityChange techAvailabilityChange = new TechAvailabilityChange();
techAvailabilityChange.load(stream); techAvailabilityChange.load(stream);
this.techAvailabilityChanges.add(techAvailabilityChange); this.techAvailabilityChanges.add(techAvailabilityChange);
}
} }
for (int i = 0, l = stream.readInt(); i < l; i++) { if (stream.available() > 0) {
final RandomUnitTable randomUnitTable = new RandomUnitTable(); for (int i = 0, l = stream.readInt(); i < l; i++) {
final RandomUnitTable randomUnitTable = new RandomUnitTable();
randomUnitTable.load(stream); randomUnitTable.load(stream);
this.randomUnitTables.add(randomUnitTable); this.randomUnitTables.add(randomUnitTable);
}
} }
if (this.version > 24) { if (this.version > 24) {
for (int i = 0, l = stream.readInt(); i < l; i++) { if (stream.available() > 0) {
final RandomItemTable randomItemTable = new RandomItemTable(); for (int i = 0, l = stream.readInt(); i < l; i++) {
final RandomItemTable randomItemTable = new RandomItemTable();
randomItemTable.load(stream); randomItemTable.load(stream);
this.randomItemTables.add(randomItemTable); this.randomItemTables.add(randomItemTable);
}
} }
} }
} }
@ -209,7 +225,7 @@ public class War3MapW3i {
} }
if (this.version > 27) { if (this.version > 27) {
ParseUtils.writeUInt8Array(stream, this.unknown2); ParseUtils.writeUInt8Array(stream, this.unknown2ProbablyLua);
} }
ParseUtils.writeUInt32(stream, this.players.size()); ParseUtils.writeUInt32(stream, this.players.size());
@ -411,7 +427,7 @@ public class War3MapW3i {
} }
public short[] getUnknown2() { public short[] getUnknown2() {
return this.unknown2; return this.unknown2ProbablyLua;
} }
public List<Player> getPlayers() { public List<Player> getPlayers() {

View File

@ -6,6 +6,7 @@ import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
@ -168,7 +169,7 @@ public class DataTable implements ObjectData {
flipMode = true; flipMode = true;
} }
int rowStartCount = 0; int rowStartCount = 0;
final String[] dataNames = new String[colCount]; String[] dataNames = new String[colCount];
int col = 0; int col = 0;
int lastFieldId = 0; int lastFieldId = 0;
while ((input = reader.readLine()) != null) { while ((input = reader.readLine()) != null) {
@ -219,6 +220,9 @@ public class DataTable implements ObjectData {
} }
final int quotationIndex = kInput.indexOf("\""); final int quotationIndex = kInput.indexOf("\"");
if ((fieldId - 1) >= dataNames.length) {
dataNames = Arrays.copyOf(dataNames, fieldId);
}
if (quotationIndex == -1) { if (quotationIndex == -1) {
dataNames[fieldId - 1] = kInput.substring(eIndex + 1); dataNames[fieldId - 1] = kInput.substring(eIndex + 1);
} }
@ -249,8 +253,11 @@ public class DataTable implements ObjectData {
} }
final int quotationIndex = kInput.indexOf("\""); final int quotationIndex = kInput.indexOf("\"");
if ((fieldId - 1) >= dataNames.length) {
dataNames = Arrays.copyOf(dataNames, fieldId);
}
if (quotationIndex == -1) { if (quotationIndex == -1) {
dataNames[fieldId - 1] = kInput.substring(eIndex + 1); dataNames[fieldId - 1] = kInput.substring(eIndex + 1, kInput.length());
} }
else { else {
dataNames[fieldId - 1] = kInput.substring(quotationIndex + 1, kInput.lastIndexOf("\"")); dataNames[fieldId - 1] = kInput.substring(quotationIndex + 1, kInput.lastIndexOf("\""));

View File

@ -14,6 +14,11 @@ public class DataSourceFileHandle extends FileHandle {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
@Override
public String path() {
return file().getPath();
}
@Override @Override
public InputStream read() { public InputStream read() {
try { try {

View File

@ -14,12 +14,14 @@ public class WorldEditStrings implements StringBundle {
private ResourceBundle bundlegs; private ResourceBundle bundlegs;
public WorldEditStrings(final DataSource dataSource) { public WorldEditStrings(final DataSource dataSource) {
try (InputStream fis = dataSource.getResourceAsStream("UI\\WorldEditStrings.txt"); if (dataSource.has("UI\\WorldEditStrings.txt")) {
InputStreamReader reader = new InputStreamReader(fis, "utf-8")) { try (InputStream fis = dataSource.getResourceAsStream("UI\\WorldEditStrings.txt");
this.bundle = new PropertyResourceBundle(reader); InputStreamReader reader = new InputStreamReader(fis, "utf-8")) {
} this.bundle = new PropertyResourceBundle(reader);
catch (final IOException e) { }
throw new RuntimeException(e); catch (final IOException e) {
throw new RuntimeException(e);
}
} }
try (InputStream fis = dataSource.getResourceAsStream("UI\\WorldEditGameStrings.txt"); try (InputStream fis = dataSource.getResourceAsStream("UI\\WorldEditGameStrings.txt");
InputStreamReader reader = new InputStreamReader(fis, "utf-8")) { InputStreamReader reader = new InputStreamReader(fis, "utf-8")) {
@ -49,6 +51,9 @@ public class WorldEditStrings implements StringBundle {
} }
private String internalGetString(final String key) { private String internalGetString(final String key) {
if (this.bundle == null) {
return this.bundlegs.getString(key.toUpperCase());
}
try { try {
String string = this.bundle.getString(key.toUpperCase()); String string = this.bundle.getString(key.toUpperCase());
if ((string.charAt(0) == '"') && (string.length() >= 2) && (string.charAt(string.length() - 1) == '"')) { if ((string.charAt(0) == '"') && (string.length() >= 2) && (string.charAt(string.length() - 1) == '"')) {
@ -63,6 +68,9 @@ public class WorldEditStrings implements StringBundle {
@Override @Override
public String getStringCaseSensitive(final String key) { public String getStringCaseSensitive(final String key) {
if (this.bundle == null) {
return this.bundlegs.getString(key);
}
try { try {
return this.bundle.getString(key); return this.bundle.getString(key);
} }

View File

@ -303,7 +303,7 @@ public abstract class Scene {
private static final class InstanceDepthComparator implements Comparator<ModelInstance> { private static final class InstanceDepthComparator implements Comparator<ModelInstance> {
@Override @Override
public int compare(final ModelInstance o1, final ModelInstance o2) { public int compare(final ModelInstance o1, final ModelInstance o2) {
return (int) Math.signum(o2.depth - o1.depth); return -Float.compare(o2.depth, o1.depth);
} }
} }
} }

View File

@ -122,7 +122,7 @@ public abstract class Sd<TYPE> {
return this.globalSequence.getValue(out, return this.globalSequence.getValue(out,
this.globalSequence.end == 0 ? 0 : counter % this.globalSequence.end); this.globalSequence.end == 0 ? 0 : counter % this.globalSequence.end);
} }
else if ((sequence != -1) && (this.sequences.size() > 0)) { else if ((sequence != -1) && (this.sequences.size() > sequence)) {
return this.sequences.get(sequence).getValue(out, frame); return this.sequences.get(sequence).getValue(out, frame);
} }
else { else {

View File

@ -17,10 +17,11 @@ public class TerrainDoodad {
final MdxSimpleInstance instance = (MdxSimpleInstance) model.addInstance(1); final MdxSimpleInstance instance = (MdxSimpleInstance) model.addInstance(1);
locationHeap[0] = (doodad.getLocation()[0] * 128) + centerOffset[0] + 128; locationHeap[0] = (doodad.getLocation()[0] * 128) + centerOffset[0] + 128;
locationHeap[0] = (doodad.getLocation()[1] * 128) + centerOffset[1] + 128; locationHeap[1] = (doodad.getLocation()[1] * 128) + centerOffset[1] + 128;
instance.move(locationHeap); instance.move(locationHeap);
instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z, row.readSLKTagFloat("fixedRot"))); instance.rotate(new Quaternion().setFromAxisRad(RenderMathUtils.VEC3_UNIT_Z,
(float) Math.toRadians(row.readSLKTagFloat("fixedRot"))));
instance.setScene(map.worldScene); instance.setScene(map.worldScene);
this.instance = instance; this.instance = instance;

View File

@ -454,12 +454,21 @@ public class War3MapViewer extends ModelViewer {
BufferedImage bufferedImage = this.filePathToPathingMap.get(pathingTexture.toLowerCase()); BufferedImage bufferedImage = this.filePathToPathingMap.get(pathingTexture.toLowerCase());
if (bufferedImage == null) { if (bufferedImage == null) {
bufferedImage = TgaFile.readTGA(pathingTexture, if (this.mapMpq.has(pathingTexture)) {
this.mapMpq.getResourceAsStream(pathingTexture)); try {
this.filePathToPathingMap.put(pathingTexture.toLowerCase(), bufferedImage); bufferedImage = TgaFile.readTGA(pathingTexture,
this.mapMpq.getResourceAsStream(pathingTexture));
this.filePathToPathingMap.put(pathingTexture.toLowerCase(), bufferedImage);
}
catch (final Exception exc) {
exc.printStackTrace();
}
}
}
if (bufferedImage != null) {
this.terrain.pathingGrid.blitPathingOverlayTexture(doodad.getLocation()[0],
doodad.getLocation()[1], (int) Math.toDegrees(doodad.getAngle()), bufferedImage);
} }
this.terrain.pathingGrid.blitPathingOverlayTexture(doodad.getLocation()[0],
doodad.getLocation()[1], (int) Math.toDegrees(doodad.getAngle()), bufferedImage);
} }
} }
// First see if the model is local. // First see if the model is local.
@ -488,7 +497,7 @@ public class War3MapViewer extends ModelViewer {
// Cliff/Terrain doodads. // Cliff/Terrain doodads.
for (final com.etheller.warsmash.parsers.w3x.doo.TerrainDoodad doodad : doo.getTerrainDoodads()) { for (final com.etheller.warsmash.parsers.w3x.doo.TerrainDoodad doodad : doo.getTerrainDoodads()) {
final MutableGameObject row = modifications.getDoodads().get(doodad.getId()); final MutableGameObject row = modifications.getDoodads().get(doodad.getId());
String file = row.readSLKTag("file"); String file = "UI\\Feedback\\WaypointFlags\\WaypointFlag.mdx";// row.readSLKTag("file");
if (file.toLowerCase().endsWith(".mdl")) { if (file.toLowerCase().endsWith(".mdl")) {
file = file.substring(0, file.length() - 4); file = file.substring(0, file.length() - 4);
} }
@ -514,43 +523,96 @@ public class War3MapViewer extends ModelViewer {
private void loadUnitsAndItems(final Warcraft3MapObjectData modifications) throws IOException { private void loadUnitsAndItems(final Warcraft3MapObjectData modifications) throws IOException {
final War3Map mpq = this.mapMpq; final War3Map mpq = this.mapMpq;
final War3MapUnitsDoo dooFile = mpq.readUnits(); if (this.dataSource.has("war3mapUnits.doo")) {
final War3MapUnitsDoo dooFile = mpq.readUnits();
final Map<String, UnitSoundset> soundsetNameToSoundset = new HashMap<>(); final Map<String, UnitSoundset> soundsetNameToSoundset = new HashMap<>();
// Collect the units and items data. // Collect the units and items data.
UnitSoundset soundset = null; UnitSoundset soundset = null;
for (final com.etheller.warsmash.parsers.w3x.unitsdoo.Unit unit : dooFile.getUnits()) { for (final com.etheller.warsmash.parsers.w3x.unitsdoo.Unit unit : dooFile.getUnits()) {
MutableGameObject row = null; MutableGameObject row = null;
String path = null; String path = null;
Splat unitShadowSplat = null; Splat unitShadowSplat = null;
// Hardcoded? // Hardcoded?
WorldEditorDataType type = null; WorldEditorDataType type = null;
if (sloc.equals(unit.getId())) { if (sloc.equals(unit.getId())) {
// path = "Objects\\StartLocation\\StartLocation.mdx"; // path = "Objects\\StartLocation\\StartLocation.mdx";
type = null; /// ?????? type = null; /// ??????
this.startLocations[unit.getPlayer()] = new Vector2(unit.getLocation()[0], unit.getLocation()[1]); this.startLocations[unit.getPlayer()] = new Vector2(unit.getLocation()[0], unit.getLocation()[1]);
} }
else { else {
row = modifications.getUnits().get(unit.getId()); row = modifications.getUnits().get(unit.getId());
if (row == null) { if (row == null) {
row = modifications.getItems().get(unit.getId()); row = modifications.getItems().get(unit.getId());
if (row != null) { if (row != null) {
type = WorldEditorDataType.ITEM; type = WorldEditorDataType.ITEM;
path = row.getFieldAsString(ITEM_FILE, 0); path = row.getFieldAsString(ITEM_FILE, 0);
if (path.toLowerCase().endsWith(".mdl") || path.toLowerCase().endsWith(".mdx")) {
path = path.substring(0, path.length() - 4);
}
final String unitShadow = "Shadow";
if ((unitShadow != null) && !"_".equals(unitShadow)) {
final String texture = "ReplaceableTextures\\Shadows\\" + unitShadow + ".blp";
final float shadowX = 50;
final float shadowY = 50;
final float shadowWidth = 128;
final float shadowHeight = 128;
if (!this.terrain.splats.containsKey(texture)) {
final Splat splat = new Splat();
splat.opacity = 0.5f;
this.terrain.splats.put(texture, splat);
}
final float x = unit.getLocation()[0] - shadowX;
final float y = unit.getLocation()[1] - shadowY;
this.terrain.splats.get(texture).locations
.add(new float[] { x, y, x + shadowWidth, y + shadowHeight, 3 });
unitShadowSplat = this.terrain.splats.get(texture);
}
path += ".mdx";
}
}
else {
type = WorldEditorDataType.UNITS;
path = row.getFieldAsString(UNIT_FILE, 0);
if (path.toLowerCase().endsWith(".mdl") || path.toLowerCase().endsWith(".mdx")) { if (path.toLowerCase().endsWith(".mdl") || path.toLowerCase().endsWith(".mdx")) {
path = path.substring(0, path.length() - 4); path = path.substring(0, path.length() - 4);
} }
if ((row.readSLKTagInt("fileVerFlags") == 2) && this.dataSource.has(path + "_V1.mdx")) {
path += "_V1";
}
final String unitShadow = "Shadow"; path += ".mdx";
final String uberSplat = row.getFieldAsString(UBER_SPLAT, 0);
if (uberSplat != null) {
final Element uberSplatInfo = this.terrain.uberSplatTable.get(uberSplat);
if (uberSplatInfo != null) {
final String texturePath = uberSplatInfo.getField("Dir") + "\\"
+ uberSplatInfo.getField("file") + ".blp";
if (!this.terrain.splats.containsKey(texturePath)) {
this.terrain.splats.put(texturePath, new Splat());
}
final float x = unit.getLocation()[0];
final float y = unit.getLocation()[1];
final float s = uberSplatInfo.getFieldFloatValue("Scale");
this.terrain.splats.get(texturePath).locations
.add(new float[] { x - s, y - s, x + s, y + s, 1 });
}
}
final String unitShadow = row.getFieldAsString(UNIT_SHADOW, 0);
if ((unitShadow != null) && !"_".equals(unitShadow)) { if ((unitShadow != null) && !"_".equals(unitShadow)) {
final String texture = "ReplaceableTextures\\Shadows\\" + unitShadow + ".blp"; final String texture = "ReplaceableTextures\\Shadows\\" + unitShadow + ".blp";
final float shadowX = 50; final float shadowX = row.getFieldAsFloat(UNIT_SHADOW_X, 0);
final float shadowY = 50; final float shadowY = row.getFieldAsFloat(UNIT_SHADOW_Y, 0);
final float shadowWidth = 128; final float shadowWidth = row.getFieldAsFloat(UNIT_SHADOW_W, 0);
final float shadowHeight = 128; final float shadowHeight = row.getFieldAsFloat(UNIT_SHADOW_H, 0);
if (!this.terrain.splats.containsKey(texture)) { if (!this.terrain.splats.containsKey(texture)) {
final Splat splat = new Splat(); final Splat splat = new Splat();
splat.opacity = 0.5f; splat.opacity = 0.5f;
@ -563,134 +625,83 @@ public class War3MapViewer extends ModelViewer {
unitShadowSplat = this.terrain.splats.get(texture); unitShadowSplat = this.terrain.splats.get(texture);
} }
path += ".mdx"; final String buildingShadow = row.getFieldAsString(BUILDING_SHADOW, 0);
} if ((buildingShadow != null) && !"_".equals(buildingShadow)) {
} this.terrain.addShadow(buildingShadow, unit.getLocation()[0], unit.getLocation()[1]);
else { }
type = WorldEditorDataType.UNITS; final String pathingTexture = row.getFieldAsString(UNIT_PATHING, 0);
path = row.getFieldAsString(UNIT_FILE, 0); if ((pathingTexture != null) && (pathingTexture.length() > 0) && !"_".equals(pathingTexture)) {
BufferedImage bufferedImage = this.filePathToPathingMap.get(pathingTexture.toLowerCase());
if (path.toLowerCase().endsWith(".mdl") || path.toLowerCase().endsWith(".mdx")) { if (bufferedImage == null) {
path = path.substring(0, path.length() - 4); bufferedImage = TgaFile.readTGA(pathingTexture,
} this.mapMpq.getResourceAsStream(pathingTexture));
if ((row.readSLKTagInt("fileVerFlags") == 2) && this.dataSource.has(path + "_V1.mdx")) { this.filePathToPathingMap.put(pathingTexture.toLowerCase(), bufferedImage);
path += "_V1";
}
path += ".mdx";
final String uberSplat = row.getFieldAsString(UBER_SPLAT, 0);
if (uberSplat != null) {
final Element uberSplatInfo = this.terrain.uberSplatTable.get(uberSplat);
if (uberSplatInfo != null) {
final String texturePath = uberSplatInfo.getField("Dir") + "\\"
+ uberSplatInfo.getField("file") + ".blp";
if (!this.terrain.splats.containsKey(texturePath)) {
this.terrain.splats.put(texturePath, new Splat());
} }
final float x = unit.getLocation()[0]; this.terrain.pathingGrid.blitPathingOverlayTexture(unit.getLocation()[0],
final float y = unit.getLocation()[1]; unit.getLocation()[1], (int) Math.toDegrees(unit.getAngle()), bufferedImage);
final float s = uberSplatInfo.getFieldFloatValue("Scale");
this.terrain.splats.get(texturePath).locations
.add(new float[] { x - s, y - s, x + s, y + s, 1 });
} }
}
final String unitShadow = row.getFieldAsString(UNIT_SHADOW, 0); final String soundName = row.getFieldAsString(UNIT_SOUNDSET, 0);
if ((unitShadow != null) && !"_".equals(unitShadow)) { UnitSoundset unitSoundset = soundsetNameToSoundset.get(soundName);
final String texture = "ReplaceableTextures\\Shadows\\" + unitShadow + ".blp"; if (unitSoundset == null) {
final float shadowX = row.getFieldAsFloat(UNIT_SHADOW_X, 0); unitSoundset = new UnitSoundset(this.dataSource, this.unitAckSoundsTable, soundName);
final float shadowY = row.getFieldAsFloat(UNIT_SHADOW_Y, 0); soundsetNameToSoundset.put(soundName, unitSoundset);
final float shadowWidth = row.getFieldAsFloat(UNIT_SHADOW_W, 0);
final float shadowHeight = row.getFieldAsFloat(UNIT_SHADOW_H, 0);
if (!this.terrain.splats.containsKey(texture)) {
final Splat splat = new Splat();
splat.opacity = 0.5f;
this.terrain.splats.put(texture, splat);
} }
final float x = unit.getLocation()[0] - shadowX; soundset = unitSoundset;
final float y = unit.getLocation()[1] - shadowY;
this.terrain.splats.get(texture).locations
.add(new float[] { x, y, x + shadowWidth, y + shadowHeight, 3 });
unitShadowSplat = this.terrain.splats.get(texture);
} }
final String buildingShadow = row.getFieldAsString(BUILDING_SHADOW, 0);
if ((buildingShadow != null) && !"_".equals(buildingShadow)) {
this.terrain.addShadow(buildingShadow, unit.getLocation()[0], unit.getLocation()[1]);
}
final String pathingTexture = row.getFieldAsString(UNIT_PATHING, 0);
if ((pathingTexture != null) && (pathingTexture.length() > 0) && !"_".equals(pathingTexture)) {
BufferedImage bufferedImage = this.filePathToPathingMap.get(pathingTexture.toLowerCase());
if (bufferedImage == null) {
bufferedImage = TgaFile.readTGA(pathingTexture,
this.mapMpq.getResourceAsStream(pathingTexture));
this.filePathToPathingMap.put(pathingTexture.toLowerCase(), bufferedImage);
}
this.terrain.pathingGrid.blitPathingOverlayTexture(unit.getLocation()[0], unit.getLocation()[1],
(int) Math.toDegrees(unit.getAngle()), bufferedImage);
}
final String soundName = row.getFieldAsString(UNIT_SOUNDSET, 0);
UnitSoundset unitSoundset = soundsetNameToSoundset.get(soundName);
if (unitSoundset == null) {
unitSoundset = new UnitSoundset(this.dataSource, this.unitAckSoundsTable, soundName);
soundsetNameToSoundset.put(soundName, unitSoundset);
}
soundset = unitSoundset;
} }
}
if (path != null) { if (path != null) {
final MdxModel model = (MdxModel) this.load(path, this.mapPathSolver, this.solverParams); final MdxModel model = (MdxModel) this.load(path, this.mapPathSolver, this.solverParams);
MdxModel portraitModel; MdxModel portraitModel;
final String portraitPath = path.substring(0, path.length() - 4) + "_portrait.mdx"; final String portraitPath = path.substring(0, path.length() - 4) + "_portrait.mdx";
if (this.dataSource.has(portraitPath)) { if (this.dataSource.has(portraitPath)) {
portraitModel = (MdxModel) this.load(portraitPath, this.mapPathSolver, this.solverParams); portraitModel = (MdxModel) this.load(portraitPath, this.mapPathSolver, this.solverParams);
}
else {
portraitModel = model;
}
if (type == WorldEditorDataType.UNITS) {
float angle;
if (this.simulation.getUnitData().isBuilding(row.getAlias())) {
// TODO pretty sure 270 is a Gameplay Constants value that should be dynamically
// loaded
angle = 270.0f;
} }
else { else {
angle = (float) Math.toDegrees(unit.getAngle()); portraitModel = model;
} }
final CUnit simulationUnit = this.simulation.createUnit(row.getAlias(), unit.getPlayer(), if (type == WorldEditorDataType.UNITS) {
unit.getLocation()[0], unit.getLocation()[1], angle); float angle;
final RenderUnit renderUnit = new RenderUnit(this, model, row, unit, soundset, portraitModel, if (this.simulation.getUnitData().isBuilding(row.getAlias())) {
simulationUnit); // TODO pretty sure 270 is a Gameplay Constants value that should be dynamically
this.units.add(renderUnit); // loaded
if (unitShadowSplat != null) { angle = 270.0f;
unitShadowSplat.unitMapping.add(new Consumer<SplatModel.SplatMover>() { }
@Override else {
public void accept(final SplatMover t) { angle = (float) Math.toDegrees(unit.getAngle());
renderUnit.shadow = t; }
} final CUnit simulationUnit = this.simulation.createUnit(row.getAlias(), unit.getPlayer(),
}); unit.getLocation()[0], unit.getLocation()[1], angle);
final RenderUnit renderUnit = new RenderUnit(this, model, row, unit, soundset, portraitModel,
simulationUnit);
this.units.add(renderUnit);
if (unitShadowSplat != null) {
unitShadowSplat.unitMapping.add(new Consumer<SplatModel.SplatMover>() {
@Override
public void accept(final SplatMover t) {
renderUnit.shadow = t;
}
});
}
}
else {
this.items.add(new RenderItem(this, model, row, unit, soundset, portraitModel)); // TODO store
// somewhere
if (unitShadowSplat != null) {
unitShadowSplat.unitMapping.add(new Consumer<SplatModel.SplatMover>() {
@Override
public void accept(final SplatMover t) {
}
});
}
} }
} }
else { else {
this.items.add(new RenderItem(this, model, row, unit, soundset, portraitModel)); // TODO store System.err.println("Unknown unit ID: " + unit.getId());
// somewhere
if (unitShadowSplat != null) {
unitShadowSplat.unitMapping.add(new Consumer<SplatModel.SplatMover>() {
@Override
public void accept(final SplatMover t) {
}
});
}
} }
} }
else {
System.err.println("Unknown unit ID: " + unit.getId());
}
} }
this.terrain.loadSplats(); this.terrain.loadSplats();

View File

@ -20,6 +20,9 @@ public class GroundTexture {
if (path.toLowerCase().endsWith(".blp")) { if (path.toLowerCase().endsWith(".blp")) {
try (InputStream stream = dataSource.getResourceAsStream(path)) { try (InputStream stream = dataSource.getResourceAsStream(path)) {
final BufferedImage image = ImageIO.read(stream); final BufferedImage image = ImageIO.read(stream);
if (image == null) {
throw new IllegalStateException("Missing ground texture: " + path);
}
final Buffer buffer = ImageUtils.getTextureBuffer(ImageUtils.forceBufferedImagesRGB(image)); final Buffer buffer = ImageUtils.getTextureBuffer(ImageUtils.forceBufferedImagesRGB(image));
final int width = image.getWidth(); final int width = image.getWidth();
final int height = image.getHeight(); final int height = image.getHeight();

View File

@ -157,7 +157,10 @@ public class PathingGrid {
} }
for (int i = -1; i <= 1; i++) { for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) { for (int j = -1; j <= 1; j++) {
if (!pathingType.isPathable(getPathing(unitX + (i * collisionSize), unitY + (j * collisionSize)))) { final float unitPathingX = unitX + (i * collisionSize);
final float unitPathingY = unitY + (j * collisionSize);
if (!contains(unitPathingX, unitPathingY)
|| !pathingType.isPathable(getPathing(unitPathingX, unitPathingY))) {
return false; return false;
} }
} }

View File

@ -15,7 +15,7 @@ public class Shapes {
float[][] quadVertices = { { 1, 1 }, { 0, 1 }, { 0, 0 }, { 1, 0 } }; float[][] quadVertices = { { 1, 1 }, { 0, 1 }, { 0, 0 }, { 1, 0 } };
int[][] quadIndices = { { 0, 3, 1 }, { 1, 3, 2 } }; int[][] quadIndices = { { 1, 3, 0 }, { 2, 3, 1 } };
public void init() { public void init() {
this.vertexBuffer = Gdx.gl30.glGenBuffer(); this.vertexBuffer = Gdx.gl30.glGenBuffer();

View File

@ -236,6 +236,9 @@ public class Terrain {
final String texFile = cliffInfo.getField("texFile"); final String texFile = cliffInfo.getField("texFile");
try (InputStream imageStream = dataSource.getResourceAsStream(texDir + "\\" + texFile + texturesExt)) { try (InputStream imageStream = dataSource.getResourceAsStream(texDir + "\\" + texFile + texturesExt)) {
final BufferedImage image = ImageIO.read(imageStream); final BufferedImage image = ImageIO.read(imageStream);
if (image == null) {
throw new IllegalStateException("Missing cliff texture: " + texDir + "\\" + texFile + texturesExt);
}
this.cliffTextures.add(new UnloadedTexture(image.getWidth(), image.getHeight(), this.cliffTextures.add(new UnloadedTexture(image.getWidth(), image.getHeight(),
ImageUtils.getTextureBuffer(ImageUtils.forceBufferedImagesRGB(image)), ImageUtils.getTextureBuffer(ImageUtils.forceBufferedImagesRGB(image)),
cliffInfo.getField("cliffModelDir"), cliffInfo.getField("rampModelDir"))); cliffInfo.getField("cliffModelDir"), cliffInfo.getField("rampModelDir")));
@ -811,8 +814,11 @@ public class Terrain {
this.webGL.useShaderProgram(this.groundShader); this.webGL.useShaderProgram(this.groundShader);
final GL30 gl = Gdx.gl30; final GL30 gl = Gdx.gl30;
gl.glDisable(GL30.GL_CULL_FACE); gl.glEnable(GL20.GL_CULL_FACE);
gl.glDisable(GL30.GL_BLEND); gl.glDisable(GL30.GL_BLEND);
gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL20.GL_DEPTH_TEST);
gl.glDepthMask(true);
gl.glUniformMatrix4fv(this.groundShader.getUniformLocation("MVP"), 1, false, gl.glUniformMatrix4fv(this.groundShader.getUniformLocation("MVP"), 1, false,
this.camera.viewProjectionMatrix.val, 0); this.camera.viewProjectionMatrix.val, 0);

View File

@ -60,6 +60,8 @@ public class RenderUnit {
private boolean swimming; private boolean swimming;
private boolean alreadyPlayedDeath = false;
private final EnumSet<AnimationTokens.SecondaryTag> secondaryAnimationTags = EnumSet private final EnumSet<AnimationTokens.SecondaryTag> secondaryAnimationTags = EnumSet
.noneOf(AnimationTokens.SecondaryTag.class); .noneOf(AnimationTokens.SecondaryTag.class);
@ -217,9 +219,16 @@ public class RenderUnit {
if (this.simulationUnit.getLife() <= 0) { if (this.simulationUnit.getLife() <= 0) {
final MdxModel model = (MdxModel) mdxComplexInstance.model; final MdxModel model = (MdxModel) mdxComplexInstance.model;
final List<Sequence> sequences = model.getSequences(); final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = StandSequence.selectSequence("death", sequences); IndexedSequence sequence = StandSequence.selectSequence("death", sequences);
if ((sequence != null) && (mdxComplexInstance.sequence != sequence.index)) { if (!this.alreadyPlayedDeath && (sequence != null) && (mdxComplexInstance.sequence != sequence.index)) {
mdxComplexInstance.setSequence(sequence.index); mdxComplexInstance.setSequence(sequence.index);
this.alreadyPlayedDeath = true;
}
else if (mdxComplexInstance.sequenceEnded && this.alreadyPlayedDeath) {
sequence = StandSequence.selectSequence("dissipate", sequences);
if ((sequence != null) && (mdxComplexInstance.sequence != sequence.index)) {
mdxComplexInstance.setSequence(sequence.index);
}
} }
} }
else if (mdxComplexInstance.sequenceEnded || (mdxComplexInstance.sequence == -1) else if (mdxComplexInstance.sequenceEnded || (mdxComplexInstance.sequence == -1)

View File

@ -45,7 +45,7 @@ public class CMoveOrder implements COrder {
final float startFloatingY = prevY; final float startFloatingY = prevY;
if (this.path == null) { if (this.path == null) {
this.path = simulation.findNaiveSlowPath(this.unit, startFloatingX, startFloatingY, this.target, this.path = simulation.findNaiveSlowPath(this.unit, startFloatingX, startFloatingY, this.target,
movementType, collisionSize); movementType == null ? MovementType.FOOT : movementType, collisionSize);
System.out.println("init path " + this.path); System.out.println("init path " + this.path);
// check for smoothing // check for smoothing
if (!this.path.isEmpty()) { if (!this.path.isEmpty()) {
@ -65,7 +65,8 @@ public class CMoveOrder implements COrder {
if ((totalPathDistance < (1.15 if ((totalPathDistance < (1.15
* nextPossiblePathElement.distance(smoothingGroupStartX, smoothingGroupStartY))) * nextPossiblePathElement.distance(smoothingGroupStartX, smoothingGroupStartY)))
&& pathingGrid.isPathable((smoothingGroupStartX + nextPossiblePathElement.x) / 2, && pathingGrid.isPathable((smoothingGroupStartX + nextPossiblePathElement.x) / 2,
(smoothingGroupStartY + nextPossiblePathElement.y) / 2, movementType)) { (smoothingGroupStartY + nextPossiblePathElement.y) / 2,
movementType == null ? MovementType.DISABLED : movementType)) {
if (smoothingStartIndex == -1) { if (smoothingStartIndex == -1) {
smoothingStartIndex = i; smoothingStartIndex = i;
} }
@ -163,8 +164,11 @@ public class CMoveOrder implements COrder {
} }
tempRect.set(this.unit.getCollisionRectangle()); tempRect.set(this.unit.getCollisionRectangle());
tempRect.setCenter(nextX, nextY); tempRect.setCenter(nextX, nextY);
if (pathingGrid.isPathable(nextX, nextY, movementType, collisionSize)// ((int) collisionSize / 16) * 16 if ((movementType == null) || (pathingGrid.isPathable(nextX, nextY, movementType, collisionSize)// ((int)
&& !worldCollision.intersectsAnythingOtherThan(tempRect, this.unit, movementType)) { // collisionSize
// / 16)
// * 16
&& !worldCollision.intersectsAnythingOtherThan(tempRect, this.unit, movementType))) {
this.unit.setPoint(nextX, nextY, worldCollision); this.unit.setPoint(nextX, nextY, worldCollision);
if (done) { if (done) {
if (this.path.isEmpty()) { if (this.path.isEmpty()) {
@ -211,7 +215,7 @@ public class CMoveOrder implements COrder {
} }
else { else {
this.path = simulation.findNaiveSlowPath(this.unit, startFloatingX, startFloatingY, this.target, this.path = simulation.findNaiveSlowPath(this.unit, startFloatingX, startFloatingY, this.target,
movementType, collisionSize); movementType == null ? MovementType.FOOT : movementType, collisionSize);
System.out.println("new path " + this.path); System.out.println("new path " + this.path);
if (this.path.isEmpty()) { if (this.path.isEmpty()) {
return true; return true;

View File

@ -57,7 +57,8 @@ public class CPathfindingProcessor {
final float collisionSize) { final float collisionSize) {
final float goalX = goal.x; final float goalX = goal.x;
final float goalY = goal.y; final float goalY = goal.y;
if (!this.pathingGrid.isPathable(goalX, goalY, movementType, collisionSize)) { if (!this.pathingGrid.isPathable(goalX, goalY, movementType, collisionSize)
|| !isPathableDynamically(goalX, goalY, ignoreIntersectionsWithThisUnit, movementType)) {
return Collections.emptyList(); return Collections.emptyList();
} }
System.out.println("beginning findNaiveSlowPath for " + startX + "," + startY + "," + goalX + "," + goalY); System.out.println("beginning findNaiveSlowPath for " + startX + "," + startY + "," + goalX + "," + goalY);

View File

@ -1,5 +1,9 @@
package com.etheller.warsmash.desktop; package com.etheller.warsmash.desktop;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL31; import org.lwjgl.opengl.GL31;
import org.lwjgl.opengl.GL32; import org.lwjgl.opengl.GL32;
@ -11,6 +15,8 @@ import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration; import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl.audio.OpenALSound; import com.badlogic.gdx.backends.lwjgl.audio.OpenALSound;
import com.etheller.warsmash.WarsmashGdxMapGame; import com.etheller.warsmash.WarsmashGdxMapGame;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.util.StringBundle;
import com.etheller.warsmash.viewer5.gl.ANGLEInstancedArrays; import com.etheller.warsmash.viewer5.gl.ANGLEInstancedArrays;
import com.etheller.warsmash.viewer5.gl.DynamicShadowExtension; import com.etheller.warsmash.viewer5.gl.DynamicShadowExtension;
import com.etheller.warsmash.viewer5.gl.Extensions; import com.etheller.warsmash.viewer5.gl.Extensions;
@ -61,6 +67,16 @@ public class DesktopLauncher {
return ((OpenALSound) sound).duration(); return ((OpenALSound) sound).duration();
} }
}; };
final DataTable warsmashIni = new DataTable(StringBundle.EMPTY);
try (FileInputStream warsmashIniInputStream = new FileInputStream("warsmash.ini")) {
warsmashIni.readTXT(warsmashIniInputStream, true);
}
catch (final FileNotFoundException e) {
throw new RuntimeException(e);
}
catch (final IOException e) {
throw new RuntimeException(e);
}
Extensions.GL_LINE = GL11.GL_LINE; Extensions.GL_LINE = GL11.GL_LINE;
Extensions.GL_FILL = GL11.GL_FILL; Extensions.GL_FILL = GL11.GL_FILL;
final LwjglApplicationConfiguration config = new LwjglApplicationConfiguration(); final LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
@ -72,6 +88,6 @@ public class DesktopLauncher {
final DisplayMode desktopDisplayMode = LwjglApplicationConfiguration.getDesktopDisplayMode(); final DisplayMode desktopDisplayMode = LwjglApplicationConfiguration.getDesktopDisplayMode();
config.width = desktopDisplayMode.width; config.width = desktopDisplayMode.width;
config.height = desktopDisplayMode.height; config.height = desktopDisplayMode.height;
new LwjglApplication(new WarsmashGdxMapGame(), config); new LwjglApplication(new WarsmashGdxMapGame(warsmashIni), config);
} }
} }

View File

@ -0,0 +1,317 @@
// Generated from Jass.g4 by ANTLR 4.7
package com.etheller.interpreter;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
/**
* This class provides an empty implementation of {@link JassVisitor},
* which can be extended to create a visitor which only needs to handle a subset
* of the available methods.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public class JassBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements JassVisitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitProgram(JassParser.ProgramContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeDefinition(JassParser.TypeDefinitionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBasicType(JassParser.BasicTypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitArrayType(JassParser.ArrayTypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNothingType(JassParser.NothingTypeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBasicGlobal(JassParser.BasicGlobalContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitDefinitionGlobal(JassParser.DefinitionGlobalContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAssignTail(JassParser.AssignTailContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitReferenceExpression(JassParser.ReferenceExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitStringLiteralExpression(JassParser.StringLiteralExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIntegerLiteralExpression(JassParser.IntegerLiteralExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFunctionReferenceExpression(JassParser.FunctionReferenceExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNullExpression(JassParser.NullExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTrueExpression(JassParser.TrueExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFalseExpression(JassParser.FalseExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitArrayReferenceExpression(JassParser.ArrayReferenceExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFunctionCallExpression(JassParser.FunctionCallExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParentheticalExpression(JassParser.ParentheticalExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNotExpression(JassParser.NotExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFunctionExpression(JassParser.FunctionExpressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSingleArgument(JassParser.SingleArgumentContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitListArgument(JassParser.ListArgumentContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitCallStatement(JassParser.CallStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSetStatement(JassParser.SetStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitArrayedAssignmentStatement(JassParser.ArrayedAssignmentStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitReturnStatement(JassParser.ReturnStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIfStatement(JassParser.IfStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSimpleIfStatement(JassParser.SimpleIfStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIfElseStatement(JassParser.IfElseStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIfElseIfStatement(JassParser.IfElseIfStatementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitParam(JassParser.ParamContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSingleParameter(JassParser.SingleParameterContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitListParameter(JassParser.ListParameterContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNothingParameter(JassParser.NothingParameterContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitGlobalsBlock(JassParser.GlobalsBlockContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitTypeDefinitionBlock(JassParser.TypeDefinitionBlockContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNativeBlock(JassParser.NativeBlockContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBlock(JassParser.BlockContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFunctionBlock(JassParser.FunctionBlockContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitStatements(JassParser.StatementsContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNewlines(JassParser.NewlinesContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNewlines_opt(JassParser.Newlines_optContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitPnewlines(JassParser.PnewlinesContext ctx) { return visitChildren(ctx); }
}

View File

@ -0,0 +1,224 @@
// Generated from Jass.g4 by ANTLR 4.7
package com.etheller.interpreter;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class JassLexer extends Lexer {
static { RuntimeMetaData.checkVersion("4.7", RuntimeMetaData.VERSION); }
protected static final DFA[] _decisionToDFA;
protected static final PredictionContextCache _sharedContextCache =
new PredictionContextCache();
public static final int
T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, EQUALS=6, GLOBALS=7, ENDGLOBALS=8,
NATIVE=9, FUNCTION=10, TAKES=11, RETURNS=12, ENDFUNCTION=13, NOTHING=14,
CALL=15, SET=16, RETURN=17, ARRAY=18, TYPE=19, EXTENDS=20, IF=21, THEN=22,
ELSE=23, ENDIF=24, ELSEIF=25, CONSTANT=26, STRING_LITERAL=27, INTEGER=28,
NULL=29, TRUE=30, FALSE=31, NOT=32, ID=33, WS=34, NEWLINE=35;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
public static String[] modeNames = {
"DEFAULT_MODE"
};
public static final String[] ruleNames = {
"T__0", "T__1", "T__2", "T__3", "T__4", "EQUALS", "GLOBALS", "ENDGLOBALS",
"NATIVE", "FUNCTION", "TAKES", "RETURNS", "ENDFUNCTION", "NOTHING", "CALL",
"SET", "RETURN", "ARRAY", "TYPE", "EXTENDS", "IF", "THEN", "ELSE", "ENDIF",
"ELSEIF", "CONSTANT", "STRING_LITERAL", "INTEGER", "NULL", "TRUE", "FALSE",
"NOT", "ID", "WS", "NEWLINE"
};
private static final String[] _LITERAL_NAMES = {
null, "'['", "']'", "'('", "')'", "','", "'='", "'globals'", "'endglobals'",
"'native'", "'function'", "'takes'", "'returns'", "'endfunction'", "'nothing'",
"'call'", "'set'", "'return'", "'array'", "'type'", "'extends'", "'if'",
"'then'", "'else'", "'endif'", "'elseif'", "'constant'", null, null, "'null'",
"'true'", "'false'", "'not'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, "EQUALS", "GLOBALS", "ENDGLOBALS",
"NATIVE", "FUNCTION", "TAKES", "RETURNS", "ENDFUNCTION", "NOTHING", "CALL",
"SET", "RETURN", "ARRAY", "TYPE", "EXTENDS", "IF", "THEN", "ELSE", "ENDIF",
"ELSEIF", "CONSTANT", "STRING_LITERAL", "INTEGER", "NULL", "TRUE", "FALSE",
"NOT", "ID", "WS", "NEWLINE"
};
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
/**
* @deprecated Use {@link #VOCABULARY} instead.
*/
@Deprecated
public static final String[] tokenNames;
static {
tokenNames = new String[_SYMBOLIC_NAMES.length];
for (int i = 0; i < tokenNames.length; i++) {
tokenNames[i] = VOCABULARY.getLiteralName(i);
if (tokenNames[i] == null) {
tokenNames[i] = VOCABULARY.getSymbolicName(i);
}
if (tokenNames[i] == null) {
tokenNames[i] = "<INVALID>";
}
}
}
@Override
@Deprecated
public String[] getTokenNames() {
return tokenNames;
}
@Override
public Vocabulary getVocabulary() {
return VOCABULARY;
}
public JassLexer(CharStream input) {
super(input);
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
}
@Override
public String getGrammarFileName() { return "Jass.g4"; }
@Override
public String[] getRuleNames() { return ruleNames; }
@Override
public String getSerializedATN() { return _serializedATN; }
@Override
public String[] getChannelNames() { return channelNames; }
@Override
public String[] getModeNames() { return modeNames; }
@Override
public ATN getATN() { return _ATN; }
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2%\u0139\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
"\4\32\t\32\4\33\t\33\4\34\t\34\4\35\t\35\4\36\t\36\4\37\t\37\4 \t \4!"+
"\t!\4\"\t\"\4#\t#\4$\t$\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6\3\7\3"+
"\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t\3\t"+
"\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3\13\3\13\3\13"+
"\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\16"+
"\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17"+
"\3\17\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\21\3\21\3\21\3\21"+
"\3\22\3\22\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24"+
"\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\25\3\26\3\26"+
"\3\26\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31"+
"\3\31\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\33"+
"\3\33\3\33\3\33\3\33\3\33\3\34\3\34\7\34\u00e3\n\34\f\34\16\34\u00e6\13"+
"\34\3\34\3\34\3\35\3\35\3\35\7\35\u00ed\n\35\f\35\16\35\u00f0\13\35\5"+
"\35\u00f2\n\35\3\36\3\36\3\36\3\36\3\36\3\37\3\37\3\37\3\37\3\37\3 \3"+
" \3 \3 \3 \3 \3!\3!\3!\3!\3\"\3\"\7\"\u010a\n\"\f\"\16\"\u010d\13\"\3"+
"#\6#\u0110\n#\r#\16#\u0111\3#\3#\3$\3$\3$\3$\7$\u011a\n$\f$\16$\u011d"+
"\13$\3$\3$\3$\3$\3$\3$\7$\u0125\n$\f$\16$\u0128\13$\3$\3$\3$\3$\3$\7$"+
"\u012f\n$\f$\16$\u0132\13$\3$\3$\3$\3$\5$\u0138\n$\6\u00e4\u011b\u0126"+
"\u0130\2%\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33"+
"\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67"+
"\359\36;\37= ?!A\"C#E$G%\3\2\t\3\2\62\62\3\2\63;\3\2\62;\5\2C\\aac|\6"+
"\2\62;C\\aac|\4\2\13\13\"\"\4\2\f\f\17\17\2\u0144\2\3\3\2\2\2\2\5\3\2"+
"\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21"+
"\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2"+
"\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3"+
"\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3"+
"\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3"+
"\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\3I\3\2\2\2\5K\3\2\2"+
"\2\7M\3\2\2\2\tO\3\2\2\2\13Q\3\2\2\2\rS\3\2\2\2\17U\3\2\2\2\21]\3\2\2"+
"\2\23h\3\2\2\2\25o\3\2\2\2\27x\3\2\2\2\31~\3\2\2\2\33\u0086\3\2\2\2\35"+
"\u0092\3\2\2\2\37\u009a\3\2\2\2!\u009f\3\2\2\2#\u00a3\3\2\2\2%\u00aa\3"+
"\2\2\2\'\u00b0\3\2\2\2)\u00b5\3\2\2\2+\u00bd\3\2\2\2-\u00c0\3\2\2\2/\u00c5"+
"\3\2\2\2\61\u00ca\3\2\2\2\63\u00d0\3\2\2\2\65\u00d7\3\2\2\2\67\u00e0\3"+
"\2\2\29\u00f1\3\2\2\2;\u00f3\3\2\2\2=\u00f8\3\2\2\2?\u00fd\3\2\2\2A\u0103"+
"\3\2\2\2C\u0107\3\2\2\2E\u010f\3\2\2\2G\u0137\3\2\2\2IJ\7]\2\2J\4\3\2"+
"\2\2KL\7_\2\2L\6\3\2\2\2MN\7*\2\2N\b\3\2\2\2OP\7+\2\2P\n\3\2\2\2QR\7."+
"\2\2R\f\3\2\2\2ST\7?\2\2T\16\3\2\2\2UV\7i\2\2VW\7n\2\2WX\7q\2\2XY\7d\2"+
"\2YZ\7c\2\2Z[\7n\2\2[\\\7u\2\2\\\20\3\2\2\2]^\7g\2\2^_\7p\2\2_`\7f\2\2"+
"`a\7i\2\2ab\7n\2\2bc\7q\2\2cd\7d\2\2de\7c\2\2ef\7n\2\2fg\7u\2\2g\22\3"+
"\2\2\2hi\7p\2\2ij\7c\2\2jk\7v\2\2kl\7k\2\2lm\7x\2\2mn\7g\2\2n\24\3\2\2"+
"\2op\7h\2\2pq\7w\2\2qr\7p\2\2rs\7e\2\2st\7v\2\2tu\7k\2\2uv\7q\2\2vw\7"+
"p\2\2w\26\3\2\2\2xy\7v\2\2yz\7c\2\2z{\7m\2\2{|\7g\2\2|}\7u\2\2}\30\3\2"+
"\2\2~\177\7t\2\2\177\u0080\7g\2\2\u0080\u0081\7v\2\2\u0081\u0082\7w\2"+
"\2\u0082\u0083\7t\2\2\u0083\u0084\7p\2\2\u0084\u0085\7u\2\2\u0085\32\3"+
"\2\2\2\u0086\u0087\7g\2\2\u0087\u0088\7p\2\2\u0088\u0089\7f\2\2\u0089"+
"\u008a\7h\2\2\u008a\u008b\7w\2\2\u008b\u008c\7p\2\2\u008c\u008d\7e\2\2"+
"\u008d\u008e\7v\2\2\u008e\u008f\7k\2\2\u008f\u0090\7q\2\2\u0090\u0091"+
"\7p\2\2\u0091\34\3\2\2\2\u0092\u0093\7p\2\2\u0093\u0094\7q\2\2\u0094\u0095"+
"\7v\2\2\u0095\u0096\7j\2\2\u0096\u0097\7k\2\2\u0097\u0098\7p\2\2\u0098"+
"\u0099\7i\2\2\u0099\36\3\2\2\2\u009a\u009b\7e\2\2\u009b\u009c\7c\2\2\u009c"+
"\u009d\7n\2\2\u009d\u009e\7n\2\2\u009e \3\2\2\2\u009f\u00a0\7u\2\2\u00a0"+
"\u00a1\7g\2\2\u00a1\u00a2\7v\2\2\u00a2\"\3\2\2\2\u00a3\u00a4\7t\2\2\u00a4"+
"\u00a5\7g\2\2\u00a5\u00a6\7v\2\2\u00a6\u00a7\7w\2\2\u00a7\u00a8\7t\2\2"+
"\u00a8\u00a9\7p\2\2\u00a9$\3\2\2\2\u00aa\u00ab\7c\2\2\u00ab\u00ac\7t\2"+
"\2\u00ac\u00ad\7t\2\2\u00ad\u00ae\7c\2\2\u00ae\u00af\7{\2\2\u00af&\3\2"+
"\2\2\u00b0\u00b1\7v\2\2\u00b1\u00b2\7{\2\2\u00b2\u00b3\7r\2\2\u00b3\u00b4"+
"\7g\2\2\u00b4(\3\2\2\2\u00b5\u00b6\7g\2\2\u00b6\u00b7\7z\2\2\u00b7\u00b8"+
"\7v\2\2\u00b8\u00b9\7g\2\2\u00b9\u00ba\7p\2\2\u00ba\u00bb\7f\2\2\u00bb"+
"\u00bc\7u\2\2\u00bc*\3\2\2\2\u00bd\u00be\7k\2\2\u00be\u00bf\7h\2\2\u00bf"+
",\3\2\2\2\u00c0\u00c1\7v\2\2\u00c1\u00c2\7j\2\2\u00c2\u00c3\7g\2\2\u00c3"+
"\u00c4\7p\2\2\u00c4.\3\2\2\2\u00c5\u00c6\7g\2\2\u00c6\u00c7\7n\2\2\u00c7"+
"\u00c8\7u\2\2\u00c8\u00c9\7g\2\2\u00c9\60\3\2\2\2\u00ca\u00cb\7g\2\2\u00cb"+
"\u00cc\7p\2\2\u00cc\u00cd\7f\2\2\u00cd\u00ce\7k\2\2\u00ce\u00cf\7h\2\2"+
"\u00cf\62\3\2\2\2\u00d0\u00d1\7g\2\2\u00d1\u00d2\7n\2\2\u00d2\u00d3\7"+
"u\2\2\u00d3\u00d4\7g\2\2\u00d4\u00d5\7k\2\2\u00d5\u00d6\7h\2\2\u00d6\64"+
"\3\2\2\2\u00d7\u00d8\7e\2\2\u00d8\u00d9\7q\2\2\u00d9\u00da\7p\2\2\u00da"+
"\u00db\7u\2\2\u00db\u00dc\7v\2\2\u00dc\u00dd\7c\2\2\u00dd\u00de\7p\2\2"+
"\u00de\u00df\7v\2\2\u00df\66\3\2\2\2\u00e0\u00e4\7$\2\2\u00e1\u00e3\13"+
"\2\2\2\u00e2\u00e1\3\2\2\2\u00e3\u00e6\3\2\2\2\u00e4\u00e5\3\2\2\2\u00e4"+
"\u00e2\3\2\2\2\u00e5\u00e7\3\2\2\2\u00e6\u00e4\3\2\2\2\u00e7\u00e8\7$"+
"\2\2\u00e88\3\2\2\2\u00e9\u00f2\t\2\2\2\u00ea\u00ee\t\3\2\2\u00eb\u00ed"+
"\t\4\2\2\u00ec\u00eb\3\2\2\2\u00ed\u00f0\3\2\2\2\u00ee\u00ec\3\2\2\2\u00ee"+
"\u00ef\3\2\2\2\u00ef\u00f2\3\2\2\2\u00f0\u00ee\3\2\2\2\u00f1\u00e9\3\2"+
"\2\2\u00f1\u00ea\3\2\2\2\u00f2:\3\2\2\2\u00f3\u00f4\7p\2\2\u00f4\u00f5"+
"\7w\2\2\u00f5\u00f6\7n\2\2\u00f6\u00f7\7n\2\2\u00f7<\3\2\2\2\u00f8\u00f9"+
"\7v\2\2\u00f9\u00fa\7t\2\2\u00fa\u00fb\7w\2\2\u00fb\u00fc\7g\2\2\u00fc"+
">\3\2\2\2\u00fd\u00fe\7h\2\2\u00fe\u00ff\7c\2\2\u00ff\u0100\7n\2\2\u0100"+
"\u0101\7u\2\2\u0101\u0102\7g\2\2\u0102@\3\2\2\2\u0103\u0104\7p\2\2\u0104"+
"\u0105\7q\2\2\u0105\u0106\7v\2\2\u0106B\3\2\2\2\u0107\u010b\t\5\2\2\u0108"+
"\u010a\t\6\2\2\u0109\u0108\3\2\2\2\u010a\u010d\3\2\2\2\u010b\u0109\3\2"+
"\2\2\u010b\u010c\3\2\2\2\u010cD\3\2\2\2\u010d\u010b\3\2\2\2\u010e\u0110"+
"\t\7\2\2\u010f\u010e\3\2\2\2\u0110\u0111\3\2\2\2\u0111\u010f\3\2\2\2\u0111"+
"\u0112\3\2\2\2\u0112\u0113\3\2\2\2\u0113\u0114\b#\2\2\u0114F\3\2\2\2\u0115"+
"\u0116\7\61\2\2\u0116\u0117\7\61\2\2\u0117\u011b\3\2\2\2\u0118\u011a\13"+
"\2\2\2\u0119\u0118\3\2\2\2\u011a\u011d\3\2\2\2\u011b\u011c\3\2\2\2\u011b"+
"\u0119\3\2\2\2\u011c\u011e\3\2\2\2\u011d\u011b\3\2\2\2\u011e\u011f\7\17"+
"\2\2\u011f\u0138\7\f\2\2\u0120\u0121\7\61\2\2\u0121\u0122\7\61\2\2\u0122"+
"\u0126\3\2\2\2\u0123\u0125\13\2\2\2\u0124\u0123\3\2\2\2\u0125\u0128\3"+
"\2\2\2\u0126\u0127\3\2\2\2\u0126\u0124\3\2\2\2\u0127\u0129\3\2\2\2\u0128"+
"\u0126\3\2\2\2\u0129\u0138\7\f\2\2\u012a\u012b\7\61\2\2\u012b\u012c\7"+
"\61\2\2\u012c\u0130\3\2\2\2\u012d\u012f\13\2\2\2\u012e\u012d\3\2\2\2\u012f"+
"\u0132\3\2\2\2\u0130\u0131\3\2\2\2\u0130\u012e\3\2\2\2\u0131\u0133\3\2"+
"\2\2\u0132\u0130\3\2\2\2\u0133\u0138\7\17\2\2\u0134\u0135\7\17\2\2\u0135"+
"\u0138\7\f\2\2\u0136\u0138\t\b\2\2\u0137\u0115\3\2\2\2\u0137\u0120\3\2"+
"\2\2\u0137\u012a\3\2\2\2\u0137\u0134\3\2\2\2\u0137\u0136\3\2\2\2\u0138"+
"H\3\2\2\2\f\2\u00e4\u00ee\u00f1\u010b\u0111\u011b\u0126\u0130\u0137\3"+
"\b\2\2";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,302 @@
// Generated from Jass.g4 by ANTLR 4.7
package com.etheller.interpreter;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
/**
* This interface defines a complete generic visitor for a parse tree produced
* by {@link JassParser}.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public interface JassVisitor<T> extends ParseTreeVisitor<T> {
/**
* Visit a parse tree produced by {@link JassParser#program}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitProgram(JassParser.ProgramContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#typeDefinition}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeDefinition(JassParser.TypeDefinitionContext ctx);
/**
* Visit a parse tree produced by the {@code BasicType}
* labeled alternative in {@link JassParser#type}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitBasicType(JassParser.BasicTypeContext ctx);
/**
* Visit a parse tree produced by the {@code ArrayType}
* labeled alternative in {@link JassParser#type}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitArrayType(JassParser.ArrayTypeContext ctx);
/**
* Visit a parse tree produced by the {@code NothingType}
* labeled alternative in {@link JassParser#type}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNothingType(JassParser.NothingTypeContext ctx);
/**
* Visit a parse tree produced by the {@code BasicGlobal}
* labeled alternative in {@link JassParser#global}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitBasicGlobal(JassParser.BasicGlobalContext ctx);
/**
* Visit a parse tree produced by the {@code DefinitionGlobal}
* labeled alternative in {@link JassParser#global}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitDefinitionGlobal(JassParser.DefinitionGlobalContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#assignTail}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitAssignTail(JassParser.AssignTailContext ctx);
/**
* Visit a parse tree produced by the {@code ReferenceExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitReferenceExpression(JassParser.ReferenceExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code StringLiteralExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitStringLiteralExpression(JassParser.StringLiteralExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code IntegerLiteralExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitIntegerLiteralExpression(JassParser.IntegerLiteralExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code FunctionReferenceExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitFunctionReferenceExpression(JassParser.FunctionReferenceExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code NullExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNullExpression(JassParser.NullExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code TrueExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTrueExpression(JassParser.TrueExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code FalseExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitFalseExpression(JassParser.FalseExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code ArrayReferenceExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitArrayReferenceExpression(JassParser.ArrayReferenceExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code FunctionCallExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitFunctionCallExpression(JassParser.FunctionCallExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code ParentheticalExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParentheticalExpression(JassParser.ParentheticalExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code NotExpression}
* labeled alternative in {@link JassParser#expression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNotExpression(JassParser.NotExpressionContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#functionExpression}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitFunctionExpression(JassParser.FunctionExpressionContext ctx);
/**
* Visit a parse tree produced by the {@code SingleArgument}
* labeled alternative in {@link JassParser#argsList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitSingleArgument(JassParser.SingleArgumentContext ctx);
/**
* Visit a parse tree produced by the {@code ListArgument}
* labeled alternative in {@link JassParser#argsList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitListArgument(JassParser.ListArgumentContext ctx);
/**
* Visit a parse tree produced by the {@code CallStatement}
* labeled alternative in {@link JassParser#statement}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitCallStatement(JassParser.CallStatementContext ctx);
/**
* Visit a parse tree produced by the {@code SetStatement}
* labeled alternative in {@link JassParser#statement}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitSetStatement(JassParser.SetStatementContext ctx);
/**
* Visit a parse tree produced by the {@code ArrayedAssignmentStatement}
* labeled alternative in {@link JassParser#statement}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitArrayedAssignmentStatement(JassParser.ArrayedAssignmentStatementContext ctx);
/**
* Visit a parse tree produced by the {@code ReturnStatement}
* labeled alternative in {@link JassParser#statement}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitReturnStatement(JassParser.ReturnStatementContext ctx);
/**
* Visit a parse tree produced by the {@code IfStatement}
* labeled alternative in {@link JassParser#statement}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitIfStatement(JassParser.IfStatementContext ctx);
/**
* Visit a parse tree produced by the {@code SimpleIfStatement}
* labeled alternative in {@link JassParser#ifStatementPartial}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitSimpleIfStatement(JassParser.SimpleIfStatementContext ctx);
/**
* Visit a parse tree produced by the {@code IfElseStatement}
* labeled alternative in {@link JassParser#ifStatementPartial}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitIfElseStatement(JassParser.IfElseStatementContext ctx);
/**
* Visit a parse tree produced by the {@code IfElseIfStatement}
* labeled alternative in {@link JassParser#ifStatementPartial}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitIfElseIfStatement(JassParser.IfElseIfStatementContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#param}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitParam(JassParser.ParamContext ctx);
/**
* Visit a parse tree produced by the {@code SingleParameter}
* labeled alternative in {@link JassParser#paramList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitSingleParameter(JassParser.SingleParameterContext ctx);
/**
* Visit a parse tree produced by the {@code ListParameter}
* labeled alternative in {@link JassParser#paramList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitListParameter(JassParser.ListParameterContext ctx);
/**
* Visit a parse tree produced by the {@code NothingParameter}
* labeled alternative in {@link JassParser#paramList}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNothingParameter(JassParser.NothingParameterContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#globalsBlock}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitGlobalsBlock(JassParser.GlobalsBlockContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#typeDefinitionBlock}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitTypeDefinitionBlock(JassParser.TypeDefinitionBlockContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#nativeBlock}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNativeBlock(JassParser.NativeBlockContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#block}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitBlock(JassParser.BlockContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#functionBlock}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitFunctionBlock(JassParser.FunctionBlockContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#statements}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitStatements(JassParser.StatementsContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#newlines}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNewlines(JassParser.NewlinesContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#newlines_opt}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitNewlines_opt(JassParser.Newlines_optContext ctx);
/**
* Visit a parse tree produced by {@link JassParser#pnewlines}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitPnewlines(JassParser.PnewlinesContext ctx);
}

View File

@ -46,8 +46,9 @@ public class JassExpressionVisitor extends JassBaseVisitor<JassExpression> {
@Override @Override
public JassExpression visitStringLiteralExpression(final StringLiteralExpressionContext ctx) { public JassExpression visitStringLiteralExpression(final StringLiteralExpressionContext ctx) {
final String stringLiteralText = ctx.STRING_LITERAL().getText(); final String stringLiteralText = ctx.STRING_LITERAL().getText();
return new LiteralJassExpression( final String parsedString = stringLiteralText.substring(1, stringLiteralText.length() - 1).replace("\\\\",
new StringJassValue(stringLiteralText.substring(1, stringLiteralText.length() - 1))); "\\");
return new LiteralJassExpression(new StringJassValue(parsedString));
} }
@Override @Override

View File

@ -115,4 +115,17 @@ native TriggerAddAction takes trigger whichTrigger, code actionFunc returns
native TriggerRemoveAction takes trigger whichTrigger, triggeraction whichAction returns nothing native TriggerRemoveAction takes trigger whichTrigger, triggeraction whichAction returns nothing
native TriggerClearActions takes trigger whichTrigger returns nothing native TriggerClearActions takes trigger whichTrigger returns nothing
native TriggerEvaluate takes trigger whichTrigger returns boolean native TriggerEvaluate takes trigger whichTrigger returns boolean
native TriggerExecute takes trigger whichTrigger returns nothing native TriggerExecute takes trigger whichTrigger returns nothing
//============================================================================
// Boolean Expr API ( for compositing trigger conditions and unit filter funcs...)
//============================================================================
native And takes boolexpr operandA, boolexpr operandB returns boolexpr
native Or takes boolexpr operandA, boolexpr operandB returns boolexpr
native Not takes boolexpr operand returns boolexpr
native Condition takes code func returns conditionfunc
native DestroyCondition takes conditionfunc c returns nothing
native Filter takes code func returns filterfunc
native DestroyFilter takes filterfunc f returns nothing
native DestroyBoolExpr takes boolexpr e returns nothing