global light field in GameMap, CSV tile prop importer, coloured light attenuation (blue lighting for sea floor!) using both 'opacity' and 'lumcolor'

Former-commit-id: c592f661c1dae3c9dc9c9130a06f77a8f082ae79
Former-commit-id: 0df9489aa02393f25eb4b0e8262bc2d9a54dd2e4
This commit is contained in:
Song Minjae
2016-02-17 01:34:35 +09:00
parent e225056b09
commit dbce32086f
40 changed files with 691 additions and 162 deletions

View File

@@ -1,10 +1,10 @@
* Weapon tier
Natural / Common Stone > Copper > Iron > Silver > Titanium
Forging ------------> Steel -------^
Exotic ('elven') Glass Aurichalcum
Special (something 'adamant') ??? (Use material spec of CNT, tensile strength 180 GPa)
Natural / Common Stone -> Copper -> Iron -> Silver -> Titanium
Forging --------------> Steel --------^
Exotic ('elven') Glass Aurichalcum
Special (something 'adamant') ??? (Use material spec of CNT, tensile strength 180 GPa)
* Metal graphics
@@ -25,4 +25,9 @@ If the size is bigger than tolerable, weapon speed severely slows down, tools be
if use time >= 0.75 second, the weapon/tool cannot be equipped.
Small weapons gains no (dis)advantage, tools become unusable
Crafted tool/weapon size is dependent on the baseRaceMass.
Crafted tool/weapon size is dependent on the baseRaceMass.
* Gemstone tier
Topaz -> R·G·B -> Diamond·Amethyst

View File

@@ -1,19 +1,46 @@
"type: excel";
"id";"name" ;"opacity";"strength";"isFluid";"viscosity";"isSolid";"isWall";"luminance";"drops" ;
"0";"TILE_AIR" ; "0"; "0"; "0"; "0"; "0"; "0"; "0";"NULL" ;
"1";"TILE_STONE" ; "8"; "25"; "0"; "0"; "1"; "1"; "0";"TILE_STONE" ;
"2";"TILE_DIRT" ; "8"; "6"; "0"; "0"; "1"; "1"; "0";"TILE_DIRT" ;
"3";"TILE_GRASS" ; "8"; "6"; "0"; "0"; "1"; "1"; "0";"TILE_DIRT" ;
"4";"TILE_PLANK_NORMAL" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_NORMAL" ;
"5";"TILE_PLANK_EBONY" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_EBONY" ;
"6";"TILE_PLANK_BIRCH" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_BIRCH" ;
"7";"TILE_PLANK_ROSEWOOD" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_ROSEWOOD" ;
"8";"TILE_TRUNK_NORMAL" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_NORMAL" ;
"9";"TILE_TRUNK_EBONY" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_EBONY" ;
"10";"TILE_TRUNK_BIRCH" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_BIRCH" ;
"11";"TILE_TRUNK_ROSEWOOD" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_ROSEWOOD" ;
"id";"name" ;"opacity";"strength";"fluid";"viscosity";"solid";"wall";"lumcolor";"drop";"fall";"friction"
# Friction: 0: frictionless, <16: slippery, 16: regular, >16: sticky
"0";"TILE_AIR" ; "4"; "0"; "0"; "N/A"; "0"; "0"; "0"; "0"; "0";"16"
"1";"TILE_STONE" ; "32"; "25"; "0"; "N/A"; "1"; "1"; "0"; "1"; "0";"16"
"2";"TILE_DIRT" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "2"; "0";"16"
"3";"TILE_GRASS" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "2"; "0";"16"
"4";"TILE_PLANK_NORMAL" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "4"; "0";"16"
"5";"TILE_PLANK_EBONY" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "5"; "0";"16"
"6";"TILE_PLANK_BIRCH" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "6"; "0";"16"
"7";"TILE_PLANK_BLOODROSE" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "7"; "0";"16"
"8";"TILE_TRUNK_NORMAL" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "8"; "0";"16"
"9";"TILE_TRUNK_EBONY" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "9"; "0";"16"
"10";"TILE_TRUNK_BIRCH" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "10"; "0";"16"
"11";"TILE_TRUNK_BLOODROSE" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "11"; "0";"16"
"12";"TILE_STONE" ; "32"; "25"; "0"; "N/A"; "1"; "1"; "0"; "12"; "0";"16"
"13";"TILE_SAND" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "13"; "1";"16"
"14";"TILE_GRAVEL" ; "32"; "6"; "0"; "N/A"; "1"; "0"; "0"; "14"; "1";"16"
"32";"TILE_SNOW" ; "8"; "6"; "0"; "0"; "1"; "1"; "0";"TILE_SNOW" ;
"33";"TILE_ICE_FRAGILE" ; "1"; "1"; "0"; "0"; "1"; "0"; "0";"NULL" ;
"34";"TILE_ICE_NATURAL" ; "6"; "25"; "0"; "0"; "1"; "1"; "0";"TILE_ICE_NATURAL" ;
"35";"TILE_ICE_CLEAR_MAGICAL"; "8"; "25"; "0"; "0"; "1"; "1"; "1";"TILE_ICE_CLEAR_MAGICAL";
"15";"TILE_ORE_MALACHITE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "15"; "0";"16"
"16";"TILE_ORE_HEMATITE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "16"; "0";"16"
"17";"TILE_ORE_NATURAL_GOLD" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "17"; "0";"16"
"18";"TILE_ORE_NATURAL_SILVER" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "18"; "0";"16"
"19";"TILE_ORE_RUTILE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "19"; "0";"16"
"20";"TILE_ORE_NATURAL_AURICHALCUM"; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "20"; "0";"16"
"21";"TILE_GEM_RUBY" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "21"; "0";"16"
"22";"TILE_GEM_EMERALD" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "22"; "0";"16"
"23";"TILE_GEM_SAPPHIRE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "23"; "0";"16"
"24";"TILE_GEM_TOPAZ" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "24"; "0";"16"
"25";"TILE_GEM_DIAMOND" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "25"; "0";"16"
"26";"TILE_GEM_AMETHYST" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "26"; "0";"16"
"27";"TILE_SNOW" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "27"; "0";"16"
"28";"TILE_ICE_FRAGILE" ; "8"; "1"; "0"; "N/A"; "1"; "0"; "0"; "28"; "0";"16"
"29";"TILE_ICE_NATURAL" ; "24"; "25"; "0"; "N/A"; "1"; "1"; "0"; "29"; "0"; "8"
"30";"TILE_ICE_CLEAR_MAGICAL" ; "32"; "25"; "0"; "N/A"; "1"; "1"; "855567"; "30"; "0"; "8"
# see scandinavian name set female of this tile id!
"31";"TILE_PLATFORM_STONE" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "31"; "0";"16"
"32";"TILE_PLATFORM_WOODEN" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "32"; "0";"16"
"33";"TILE_PLATFORM_EBONY" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "33"; "0";"16"
"34";"TILE_PLATFORM_BIRCH" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "34"; "0";"16"
"35";"TILE_PLATFORM_BLOODROSE" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "35"; "0";"16"
"36";"TILE_TORCH" ; "0"; "0"; "0"; "N/A"; "0"; "0";"16777215"; "36"; "0";"16"
"239";"TILE_WATER" ; "16"; "100"; "1"; "2"; "0"; "0";"15464447"; "239"; "0";"16"
"255";"TILE_LAVA" ; "0"; "100"; "1"; "2"; "0"; "0"; "8397312"; "239"; "0";"16"
Can't render this file because it contains an unexpected character in line 2 and column 12.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

@@ -0,0 +1,40 @@
package com.Torvald;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.util.List;
/**
* Created by minjaesong on 16-02-16.
*/
public class CSVFetcher {
private static StringBuffer csvString = new StringBuffer();
public static List<CSVRecord> readCSV(String csvFilePath) throws IOException {
readCsvFileAsString(csvFilePath);
CSVParser csvParser = CSVParser.parse(csvString.toString()
, CSVFormat.DEFAULT.withIgnoreSurroundingSpaces().withHeader()
.withIgnoreEmptyLines().withDelimiter(';')
.withCommentMarker('#').withNullString("N/A")
.withRecordSeparator('\n')
);
List<CSVRecord> csvRecordList = csvParser.getRecords();
csvParser.close();
return csvRecordList;
}
private static void readCsvFileAsString(String path) throws IOException {
Files.lines(
FileSystems.getDefault().getPath(path)
).forEach(s -> csvString.append(s += "\n"));
}
}

View File

@@ -10,15 +10,15 @@ import java.nio.file.Files;
/**
* Created by minjaesong on 16-02-15.
*/
public class JsonGetter {
public class JsonFetcher {
private static String jsonString = new String();
private static StringBuffer jsonString = new StringBuffer();
public static JsonObject readJson(String jsonFileName) throws IOException {
readJsonFileAsString(jsonFileName);
public static JsonObject readJson(String jsonFilePath) throws IOException {
readJsonFileAsString(jsonFilePath);
JsonParser jsonParser = new JsonParser();
JsonObject jsonObj = jsonParser.parse(jsonString).getAsJsonObject();
JsonObject jsonObj = jsonParser.parse(jsonString.toString()).getAsJsonObject();
return jsonObj;
}
@@ -26,11 +26,6 @@ public class JsonGetter {
private static void readJsonFileAsString(String path) throws IOException {
Files.lines(
FileSystems.getDefault().getPath(path)
).forEach(JsonGetter::strAppend);
).forEach(jsonString::append); // JSON does not require line break
}
private static void strAppend( String s) {
jsonString += s;
}
}

View File

@@ -32,7 +32,7 @@ public class ActorWithBody implements Actor, Visible, Glowing {
* veloY += 3.0
* +3.0 is acceleration. You __accumulate__ acceleration to the velocity.
*/
private @NotNull float veloX, veloY;
private volatile @NotNull float veloX, veloY;
private final float VELO_HARD_LIMIT = 10000;
boolean grounded = false;
@@ -49,13 +49,13 @@ public class ActorWithBody implements Actor, Visible, Glowing {
/**
* Positions: top-left point
*/
private @NotNull Hitbox hitbox, nextHitbox;
private volatile @NotNull Hitbox hitbox, nextHitbox;
/**
* Physical properties
*/
private float scale = 1;
private float mass = 1f;
private volatile float scale = 1;
private volatile float mass = 1f;
private static final int TSIZE = MapDrawer.TILE_SIZE;
private static final int AUTO_CLIMB_RATE = TSIZE / 4;

View File

@@ -1,16 +1,13 @@
package com.Torvald.Terrarum.Actors;
import com.Torvald.JsonGetter;
import com.Torvald.JsonFetcher;
import com.Torvald.Rand.Fudge3;
import com.Torvald.Rand.HQRNG;
import com.Torvald.Terrarum.LangPack.Lang;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.newdawn.slick.SlickException;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
/**
* Created by minjaesong on 16-02-05.
@@ -20,7 +17,7 @@ public class CreatureBuildFactory {
private static final String JSONPATH = "./res/raw/";
public ActorWithBody build(String jsonFileName) throws IOException, SlickException {
JsonObject jsonObj = JsonGetter.readJson(JSONPATH + jsonFileName);
JsonObject jsonObj = JsonFetcher.readJson(JSONPATH + jsonFileName);
ActorWithBody actor = new ActorWithBody();

View File

@@ -1,11 +1,9 @@
package com.Torvald.Terrarum.Actors.Faction;
import com.Torvald.JsonGetter;
import com.google.gson.JsonElement;
import com.Torvald.JsonFetcher;
import com.google.gson.JsonObject;
import java.io.IOException;
import java.util.HashSet;
/**
* Created by minjaesong on 16-02-15.
@@ -15,7 +13,7 @@ public class FactionRelatorFactory {
private static final String JSONPATH = "./res/raw/";
public Faction build(String filename) throws IOException {
JsonObject jsonObj = JsonGetter.readJson(JSONPATH + filename);
JsonObject jsonObj = JsonFetcher.readJson(JSONPATH + filename);
Faction factionObj = new Faction(jsonObj.get("factionname").getAsString());

View File

@@ -34,11 +34,11 @@ public class ExportMap implements ConsoleCommand {
private static final byte ILMENITE = 19;
private static final byte AURICHALCUM = 20;
private static final byte DIAMOND = 21;
private static final byte RUBY = 22;
private static final byte EMERALD = 23;
private static final byte SAPPHIRE = 24;
private static final byte TOPAZ = 25;
private static final byte DIAMOND = 25;
private static final byte RUBY = 21;
private static final byte EMERALD = 22;
private static final byte SAPPHIRE = 23;
private static final byte TOPAZ = 24;
private static final byte AMETHYST = 26;
private static final byte SNOW = 27;
@@ -130,6 +130,7 @@ public class ExportMap implements ConsoleCommand {
colorTable.put(GOLD, new Col4096(0xCB6));
colorTable.put(ILMENITE, new Col4096(0x8AB));
colorTable.put(AURICHALCUM, new Col4096(0xD92));
colorTable.put(SILVER, new Col4096(0xDDD));
colorTable.put(DIAMOND, new Col4096(0x9CE));
colorTable.put(RUBY, new Col4096(0xB10));

View File

@@ -6,10 +6,12 @@ import com.Torvald.Terrarum.GameControl.GameController;
import com.Torvald.Terrarum.GameControl.KeyMap;
import com.Torvald.Terrarum.GameControl.KeyToggler;
import com.Torvald.Terrarum.GameMap.GameMap;
import com.Torvald.Terrarum.GameMap.WorldTime;
import com.Torvald.Terrarum.MapDrawer.LightmapRenderer;
import com.Torvald.Terrarum.MapDrawer.MapCamera;
import com.Torvald.Terrarum.MapDrawer.MapDrawer;
import com.Torvald.Terrarum.MapGenerator.MapGenerator;
import com.Torvald.Terrarum.TileProperties.TilePropCodex;
import com.Torvald.Terrarum.TileStat.TileStat;
import com.Torvald.Terrarum.UserInterface.*;
import com.sun.istack.internal.NotNull;
@@ -81,6 +83,7 @@ public class Game extends BasicGameState {
skyBox = new Rectangle(0, 0, Terrarum.WIDTH, Terrarum.HEIGHT);
new WorldTime();
new TilePropCodex();
map = new GameMap(8192, 2048);
map.setGravitation(9.8f);
@@ -267,7 +270,7 @@ public class Game extends BasicGameState {
}
private void drawSkybox(Graphics g) {
Color[] colourTable = getGradientColour(WorldTime.elapsedSeconds());
Color[] colourTable = getGradientColour(Terrarum.game.map.getWorldTime().elapsedSeconds());
GradientFill skyColourFill = new GradientFill(0, 0, colourTable[0], 0, Terrarum.HEIGHT, colourTable[1]);
g.fill(skyBox, skyColourFill);
}

View File

@@ -20,18 +20,18 @@ import java.util.function.Consumer;
public class GameMap {
//layers
private MapLayer layerWall;
private MapLayer layerTerrain;
private MapLayer layerWire;
private volatile MapLayer layerWall;
private volatile MapLayer layerTerrain;
private volatile MapLayer layerWire;
private volatile PairedMapLayer terrainDamageCode;
//properties
public int width;
public int height;
public int spawnX;
public int spawnY;
int offset;
public LinkedList<MapPoint> houseDesignation;
private LinkedList<MapPoint> houseDesignation;
public static final int WALL = 0;
public static final int TERRAIN = 1;
@@ -39,8 +39,9 @@ public class GameMap {
//public World physWorld = new World( new Vec2(0, -TerrarumMain.game.gravitationalAccel) );
//physics
@NotNull
private float gravitation;
private int globalLight;
private WorldTime worldTime;
/**
* @param width
@@ -56,6 +57,10 @@ public class GameMap {
layerTerrain = new MapLayer(width, height);
layerWall = new MapLayer(width, height);
layerWire = new MapLayer(width, height);
terrainDamageCode = new PairedMapLayer(width, height);
globalLight = 0xFFFFFF;
worldTime = new WorldTime();
}
public void setGravitation(float g) {
@@ -89,6 +94,15 @@ public class GameMap {
return layerWire.data;
}
/**
* Get paired array data of damage codes.
* Format: 0baaaabbbb, aaaa for x = 0, 2, 4, ..., bbbb for x = 1, 3, 5, ...
* @return byte[][] damage code pair
*/
public byte[][] getDamageDataArray() {
return terrainDamageCode.dataPair;
}
/**
* Get MapLayer object of terrain
*
@@ -106,6 +120,10 @@ public class GameMap {
return layerWire;
}
public PairedMapLayer getTerrainDamageCode() {
return terrainDamageCode;
}
public int getTileFromWall(int x, int y) {
return uint8ToInt32(layerWall.data[y][x]);
}
@@ -118,6 +136,10 @@ public class GameMap {
return uint8ToInt32(layerWire.data[y][x]);
}
public int getDamageData(int x, int y) {
return terrainDamageCode.getData(x, y);
}
public int getTileFrom(int mode, int x, int y) {
if (mode == TERRAIN) { return getTileFromTerrain(x, y); }
else if (mode == WALL) { return getTileFromWall(x, y); }
@@ -128,7 +150,7 @@ public class GameMap {
private int uint8ToInt32(byte x) {
int ret;
if ((x & 0b1000_0000) != 0) {
ret = (x & 0b0111_1111) | (x & 0b1000_0000);
ret = x & 0b1111_1111;
} else {
ret = x;
}
@@ -138,4 +160,16 @@ public class GameMap {
public float getGravitation() {
return gravitation;
}
public int getGlobalLight() {
return globalLight;
}
public void setGlobalLight(int globalLight) {
this.globalLight = globalLight;
}
public WorldTime getWorldTime() {
return worldTime;
}
}

View File

@@ -109,7 +109,6 @@ public class MapLayer implements Iterable<Byte> {
return uint8ToInt32(data[y][x]);
}
private int uint8ToInt32(byte x) {
int ret;
if ((x & 0b1000_0000) != 0) {

View File

@@ -0,0 +1,122 @@
package com.Torvald.Terrarum.GameMap;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.function.Consumer;
/**
* Created by minjaesong on 16-02-15.
*/
public class PairedMapLayer implements Iterable<Integer> {
/**
* 0b_xxxx_yyyy, x for lower index, y for higher index
*
* e.g.
*
* 0110 1101 is interpreted as
* 6 for tile 0, 13 for tile 1.
*/
byte[][] dataPair;
public int width;
public int height;
public static final int MAX_VALUE = 16;
public PairedMapLayer(int width, int height) {
this.width = width / 2;
this.height = height;
dataPair = new byte[height][width / 2];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width / 2; j++) {
dataPair[i][j] = 0;
}
}
}
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
@Override
public Iterator<Integer> iterator() {
Iterator<Integer> it = new Iterator<Integer>() {
private int iteratorCount = 0;
@Override
public boolean hasNext() {
return iteratorCount < width * height * 2;
}
@Override
public Integer next() {
int y = iteratorCount / (width * 2);
int x = iteratorCount % (width * 2);
// advance counter
iteratorCount += 1;
return getData(x, y);
}
};
return it;
}
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @implSpec <p>The default implementation behaves as if:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
* @since 1.8
*/
@Override
public void forEach(Consumer<? super Integer> action) {
throw new UnsupportedOperationException();
}
/**
* Creates a {@link Spliterator} over the elements described by this
* {@code Iterable}.
*
* @return a {@code Spliterator} over the elements described by this
* {@code Iterable}.
* @implSpec The default implementation creates an
* <em><a href="Spliterator.html#binding">early-binding</a></em>
* spliterator from the iterable's {@code Iterator}. The spliterator
* inherits the <em>fail-fast</em> properties of the iterable's iterator.
* @implNote The default implementation should usually be overridden. The
* spliterator returned by the default implementation has poor splitting
* capabilities, is unsized, and does not report any spliterator
* characteristics. Implementing classes can nearly always provide a
* better implementation.
* @since 1.8
*/
@Override
public Spliterator<Integer> spliterator() {
throw new UnsupportedOperationException();
}
public int getData(int x, int y) {
if ((x & 0x1) == 0)
// higher four bits for i = 0, 2, 4, ...
return (dataPair[y][x / 2] & 0xF0) >>> 4;
else
// lower four bits for i = 1, 3, 5, ...
return dataPair[y][x / 2] & 0x0F;
}
}

View File

@@ -1,27 +1,27 @@
package com.Torvald.Terrarum;
package com.Torvald.Terrarum.GameMap;
/**
* Created by minjaesong on 16-01-24.
*/
public class WorldTime {
public static int seconds = 0;
public static int minutes = 0;
public static int hours = 0;
public int seconds = 0;
public int minutes = 0;
public int hours = 0;
public static int daysCount = 0; //NOT a calendar day
public int daysCount = 0; //NOT a calendar day
public static int days = 1;
public static int months = 1;
public static int years = 1;
public int days = 1;
public int months = 1;
public int years = 1;
public static int weeks = 1;
public static int dayOfWeek = 0; //0: Mondag-The first day of weekday
public int weeks = 1;
public int dayOfWeek = 0; //0: Mondag-The first day of weekday
public static final int DAY_LENGTH = 79200; //must be the multiple of 3600
public static int timeDelta = 1;
public int timeDelta = 1;
public static final String[] DAYNAMES = { //daynames are taken from Nynorsk (å -> o)
public final String[] DAYNAMES = { //daynames are taken from Nynorsk (å -> o)
"Mondag"
,"Tysdag"
,"Midtedag" //From Islenska Miðvikudagur
@@ -31,7 +31,7 @@ public class WorldTime {
,"Sundag"
,"Verdag" //From Norsk word 'verd'
};
public static final String[] DAYNAMES_SHORT = {
public final String[] DAYNAMES_SHORT = {
"Mon"
,"Tys"
,"Mid"
@@ -42,10 +42,13 @@ public class WorldTime {
,"Ver"
};
public WorldTime() {
}
/**
* Note: Target FPS must be 60.
*/
public static void update(){
public void update(){
//time
seconds += timeDelta;
@@ -94,15 +97,15 @@ public class WorldTime {
}
}
public static int elapsedSeconds(){
public int elapsedSeconds(){
return (3600 * hours + 60 * minutes + seconds) % DAY_LENGTH;
}
public static long totalSeconds(){
public long totalSeconds(){
return (long)(DAY_LENGTH) * daysCount + 3600 * hours + 60 * minutes + seconds;
}
public static boolean isLeapYear(){
public boolean isLeapYear(){
boolean ret = false;
if (years % 4 == 0){
@@ -120,22 +123,22 @@ public class WorldTime {
return ret;
}
public static void setTime(int t){
public void setTime(int t){
days += t / DAY_LENGTH;
hours = t / 3600;
minutes = (t - 3600 * hours) / 60;
seconds = t - minutes * 60;
}
public static void addTime(int t){
public void addTime(int t){
setTime(elapsedSeconds() + t);
}
public static void setTimeDelta(int d){
public void setTimeDelta(int d){
timeDelta = (d == 0) ? 1 : d;
}
public static String getDayName(){
public String getDayName(){
return DAYNAMES[dayOfWeek];
}
}

View File

@@ -1,10 +1,10 @@
* Weapon tier
Natural / Common Stone > Copper > Iron > Silver > Titanium
Forging ------------> Steel -------^
Exotic ('elven') Glass Aurichalcum
Special (something 'adamant') ??? (Use material spec of CNT, tensile strength 180 GPa)
Natural / Common Stone -> Copper -> Iron -> Silver -> Titanium
Forging --------------> Steel --------^
Exotic ('elven') Glass Aurichalcum
Special (something 'adamant') ??? (Use material spec of CNT, tensile strength 180 GPa)
* Metal graphics
@@ -25,4 +25,9 @@ If the size is bigger than tolerable, weapon speed severely slows down, tools be
if use time >= 0.75 second, the weapon/tool cannot be equipped.
Small weapons gains no (dis)advantage, tools become unusable
Crafted tool/weapon size is dependent on the baseRaceMass.
Crafted tool/weapon size is dependent on the baseRaceMass.
* Gemstone tier
Topaz -> R·G·B -> Diamond·Amethyst

View File

@@ -1,12 +1,13 @@
package com.Torvald.Terrarum.MapDrawer;
import com.Torvald.Terrarum.Game;
import com.Torvald.Terrarum.Terrarum;
import com.Torvald.Terrarum.TileProperties.TilePropCodex;
import com.jme3.math.FastMath;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import java.util.ArrayList;
import java.util.Arrays;
/**
* Created by minjaesong on 16-01-25.
@@ -16,7 +17,7 @@ public class LightmapRenderer {
/**
* 8-Bit RGB values
*/
private static int[][] staticLightMap;
private static volatile int[][] staticLightMap;
private static boolean lightMapInitialised = false;
/**
@@ -24,9 +25,6 @@ public class LightmapRenderer {
*/
private static ArrayList<LightmapLantern> lanterns = new ArrayList<>();
private static final int AIR_OPACITY = 8;
private static final int NON_AIR_OPACITY = 32;
private static final int AIR = 0;
@@ -53,7 +51,12 @@ public class LightmapRenderer {
}
public static void removeLantern(int x, int y) {
for (int i = lanterns.size() - 1; i >= 0; i--) {
LightmapLantern lantern = lanterns.get(i);
if (lantern.getX() == x && lantern.getY() == y) {
lanterns.remove(i);
}
}
}
public static void renderLightMap() {
@@ -93,28 +96,28 @@ public class LightmapRenderer {
for (int y = for_y_start; y < for_y_end; y++) {
for (int x = for_x_start; x < for_x_end; x++) {
calculateAndSet(x, y);
staticLightMap[y][x] = calculate(x, y);
}
}
// Round 2
for (int y = for_y_start; y < for_y_end; y++) {
for (int x = for_x_end - 1; x >= for_x_start; x--) {
calculateAndSet(x, y);
staticLightMap[y][x] = calculate(x, y);
}
}
// Round 3
for (int y = for_y_end - 1; y > for_y_start; y--) {
for (int x = for_x_end - 1; x >= for_x_start; x--) {
calculateAndSet(x, y);
staticLightMap[y][x] = calculate(x, y);
}
}
// Round 4
for (int y = for_y_end - 1; y > for_y_start; y--) {
for (int x = for_x_start; x < for_x_end; x++) {
calculateAndSet(x, y);
staticLightMap[y][x] = calculate(x, y);
}
}
}
@@ -222,26 +225,42 @@ public class LightmapRenderer {
}
}
private static void calculateAndSet(int x, int y){
private static int calculate(int x, int y){
if (!outOfBounds(x, y)){
byte[][] layerTerrain = Terrarum.game.map.getTerrainArray();
byte[][] layerWall = Terrarum.game.map.getWallArray();
int lightColor;
float lightColorR = 1f;
float lightColorG = 1f;
float lightColorB = 1f;
int lightColorInt;
int thisTerrain = layerTerrain[y][x];
int thisWall = layerWall[y][x];
int thisTerrain = Terrarum.game.map.getTileFromTerrain(x, y);
int thisWall = Terrarum.game.map.getTileFromWall(x, y);
// open air. TODO replace with globalLightLevel
// open air
if (thisTerrain == AIR && thisWall == AIR) {
lightColor = 0xffffff; //0xe8fbff;
lightColorInt = Terrarum.game.map.getGlobalLight();
}
//else if (thisTerrain == 1) {
// lightColor = 0xff0000;
//}
// TODO lantern + light-emitter, light-emitter, lantern
else {
int[] bgrVal = new int[3]; // {B, G, R}
// mix light emitter
if (TilePropCodex.getProp(thisTerrain).getLuminosity() != 0) {
int lum = TilePropCodex.getProp(thisTerrain).getLuminosity();
lightColorR = getR(lum);
lightColorG = getG(lum);
lightColorB = getB(lum);
}
// mix lantern
for (LightmapLantern lantern : lanterns) {
if (lantern.getX() == x && lantern.getY() == y) {
int lum = lantern.getIntensity();
lightColorR = getR(lum);
lightColorG = getG(lum);
lightColorB = getB(lum);
break;
}
}
float[] bgrVal = new float[3]; // {B, G, R}
// test for each R, G, B channel
for (int i = 0; i < 3; i++) {
@@ -277,45 +296,44 @@ public class LightmapRenderer {
}
//return: brightest - opacity
if (thisTerrain == AIR) {
bgrVal[i] = darken(brightest, AIR_OPACITY);
}
else {
bgrVal[i] = darken(brightest, NON_AIR_OPACITY);
}
bgrVal[i] = darkenFloat(
brightest
, TilePropCodex.getProp(thisTerrain).getOpacity()
);
}
// construct lightColor from bgrVal
lightColor = constructRGB(
bgrVal[OFFSET_R]
, bgrVal[OFFSET_G]
, bgrVal[OFFSET_B]
lightColorInt = constructRGBFromFloat(
bgrVal[OFFSET_R] * lightColorR
, bgrVal[OFFSET_G] * lightColorG
, bgrVal[OFFSET_B] * lightColorB
);
}
//return lightColor;
staticLightMap[y][x] = lightColor;
return lightColorInt;
}
else {
throw new IllegalArgumentException("Out of bounds of lightMap");
}
}
//public Graphics getGraphics() {
// return lightMapGraphicsInstance;
//}
/*private static int darken(int RGB, int darken) {
if (darken < 0 || darken > 0xFF) { throw new IllegalArgumentException("darken: out of range"); }
float r = getR(RGB) * ((0xFF - darken) / 0xFFf);
float g = getG(RGB) * ((0xFF - darken) / 0xFFf);
float b = getB(RGB) * ((0xFF - darken) / 0xFFf);
return constructRGB(r, g, b);
}*/
/**
*
* @param data Raw channel value [0-255]
* @param darken [0-255]
* @return darkened data [0-1]
*/
private static float darkenFloat(int data, int darken) {
return (darken(data, darken) / 255f);
}
/**
*
* @param data Raw channel value [0-255]
* @param darken [0-255]
* @return darkened data [0-255]
*/
private static int darken(int data, int darken) {
if (darken < 0 || darken > 0xFF) { throw new IllegalArgumentException("darken: out of range"); }
@@ -357,14 +375,14 @@ public class LightmapRenderer {
return getRawB(rgb) / 255f;
}
private static int constructRGB(int r, int g, int b) {
private static int constructRGBFromFloat(int r, int g, int b) {
if (r < 0 || r > 0xFF) { throw new IllegalArgumentException("Red: out of range"); }
if (g < 0 || g > 0xFF) { throw new IllegalArgumentException("Green: out of range"); }
if (b < 0 || b > 0xFF) { throw new IllegalArgumentException("Blue: out of range"); }
return (r << 16) | (g << 8) | b;
}
private static int constructRGB(float r, float g, float b) {
private static int constructRGBFromFloat(float r, float g, float b) {
if (r < 0 || r > 1.0f) { throw new IllegalArgumentException("Red: out of range"); }
if (g < 0 || g > 1.0f) { throw new IllegalArgumentException("Green: out of range"); }
if (b < 0 || b > 1.0f) { throw new IllegalArgumentException("Blue: out of range"); }
@@ -373,14 +391,33 @@ public class LightmapRenderer {
int intG = Math.round(g * 0xFF);
int intB = Math.round(b * 0xFF);
return constructRGB(intR, intG, intB);
return constructRGBFromFloat(intR, intG, intB);
}
private static int colourLinearMix(int colA, int colB) {
int r = (getRawR(colA) + getRawR(colB)) >> 1;
int g = (getRawG(colA) + getRawG(colB)) >> 1;
int b = (getRawB(colA) + getRawB(colB)) >> 1;
return constructRGB(r, g, b);
return constructRGBFromFloat(r, g, b);
}
/**
*
* @param thisTile
* @param side1
* @param side2
* @param corner
* @return
*/
private static int colourQuadraticMix(int thisTile, int side1, int side2, int corner) {
int rSide = max(getRawR(side1), getRawR(side2), getRawR(corner) / 2);
int r = arithmeticAverage(rSide, getRawR(thisTile));
int gSide = max(getRawG(side1), getRawG(side2), getRawG(corner) / 2);
int g = arithmeticAverage(gSide, getRawG(thisTile));
int bSide = max(getRawG(side1), getRawG(side2), getRawG(corner) / 2);
int b = arithmeticAverage(bSide, getRawG(thisTile));
return constructRGBFromFloat(r, g, b);
}
private static int quantise16(int x) {
@@ -398,6 +435,16 @@ public class LightmapRenderer {
return (x << 4);
}
private static int max(int... i) {
Arrays.sort(i);
return i[i.length - 1];
}
private static int min(int... i) {
Arrays.sort(i);
return i[0];
}
private static boolean outOfBounds(int x, int y){
return ( x < 0 || y < 0 || x >= Terrarum.game.map.width || y >= Terrarum.game.map.height);
}
@@ -411,6 +458,11 @@ public class LightmapRenderer {
else return i;
}
private static float clampZero(float i) {
if (i < 0) return 0;
else return i;
}
public static int[][] getStaticLightMap() {
return staticLightMap;
}
@@ -452,6 +504,14 @@ public class LightmapRenderer {
return x;
}
}
private static int arithmeticAverage(int... i) {
int sum = 0;
for (int k = 0; k < i.length; k++) {
sum += i[k];
}
return Math.round(sum / (float) i.length);
}
}
class LightmapLantern {

View File

@@ -50,11 +50,11 @@ public class MapGenerator {
private static final byte ILMENITE = 19;
private static final byte AURICHALCUM = 20;
private static final byte DIAMOND = 21;
private static final byte RUBY = 22;
private static final byte EMERALD = 23;
private static final byte SAPPHIRE = 24;
private static final byte TOPAZ = 25;
private static final byte DIAMOND = 25;
private static final byte RUBY = 21;
private static final byte EMERALD = 22;
private static final byte SAPPHIRE = 23;
private static final byte TOPAZ = 24;
private static final byte AMETHYST = 26;
private static final byte SNOW = 27;

View File

@@ -0,0 +1,132 @@
package com.Torvald.Terrarum.TileProperties;
/**
* Created by minjaesong on 16-02-16.
*/
public class TileProp {
private int id;
private String name;
private int opacity;
private int strength;
private boolean fluid;
private int viscocity;
private boolean solid; // transparent or not
private boolean wallable;
private int luminosity;
private int drop;
private boolean fallable;
private int friction;
public int getId() {
return id;
}
void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
void setName(String name) {
this.name = name;
}
public int getOpacity() {
return opacity;
}
void setOpacity(int opacity) {
this.opacity = opacity;
}
public int getStrength() {
return strength;
}
void setStrength(int strength) {
this.strength = strength;
}
public boolean isFluid() {
return fluid;
}
void setFluid(boolean fluid) {
this.fluid = fluid;
}
public int getViscocity() {
return viscocity;
}
void setViscocity(int viscocity) {
this.viscocity = viscocity;
}
public boolean isSolid() {
return solid;
}
void setSolid(boolean solid) {
this.solid = solid;
}
public boolean isWallable() {
return wallable;
}
void setWallable(boolean wallable) {
this.wallable = wallable;
}
/**
* Raw RGB value, without alpha
* @return
*/
public int getLuminosity() {
return luminosity;
}
/**
*
* @param luminosity Raw RGB value, without alpha
*/
void setLuminosity(int luminosity) {
this.luminosity = luminosity;
}
public int getDrop() {
return drop;
}
void setDrop(int drop) {
this.drop = drop;
}
public boolean isFallable() {
return fallable;
}
void setFallable(boolean fallable) {
this.fallable = fallable;
}
public int getFriction() {
return friction;
}
void setFriction(int friction) {
this.friction = friction;
}
}

View File

@@ -0,0 +1,81 @@
package com.Torvald.Terrarum.TileProperties;
import com.Torvald.CSVFetcher;
import com.Torvald.Terrarum.GameMap.MapLayer;
import org.apache.commons.csv.CSVRecord;
import java.io.IOException;
import java.util.List;
/**
* Created by minjaesong on 16-02-16.
*/
public class TilePropCodex {
private static TileProp[] tileProps;
public TilePropCodex() {
tileProps = new TileProp[MapLayer.TILES_SUPPORTED];
for (int i = 0; i < tileProps.length; i++) {
tileProps[i] = new TileProp();
}
try {
List<CSVRecord> records = CSVFetcher.readCSV("" +
"./src/com/Torvald/Terrarum/TileProperties/propdata" +
".csv");
System.out.println("[TilePropCodex] Building tile properties table");
records.forEach(record ->
setProp(tileProps[intVal(record, "id")], record
));
}
catch (IOException e) {
e.printStackTrace();
}
}
public static TileProp getProp(int index) {
try {
tileProps[index].getId();
}
catch (NullPointerException e) {
throw new NullPointerException("Tile prop with id " + String.valueOf(index)
+ " does not exist.");
}
return tileProps[index];
}
private void setProp(TileProp prop, CSVRecord record) {
prop.setName(record.get("name"));
prop.setId(intVal(record, "id"));
prop.setOpacity(intVal(record, "opacity"));
prop.setStrength(intVal(record, "strength"));
prop.setLuminosity(intVal(record, "lumcolor"));
prop.setDrop(intVal(record, "drop"));
prop.setFriction(intVal(record, "friction"));
prop.setFluid(boolVal(record, "fluid"));
prop.setSolid(boolVal(record, "solid"));
prop.setWallable(boolVal(record, "wall"));
prop.setFallable(boolVal(record, "fall"));
if (prop.isFluid()) prop.setOpacity(intVal(record, "opacity"));
System.out.print(prop.getId());
System.out.println("\t" + prop.getName());
}
private int intVal(CSVRecord rec, String s) {
return Integer.decode(rec.get(s));
}
private boolean boolVal(CSVRecord rec, String s) {
return !(intVal(rec, s) == 0);
}
}

View File

@@ -1,19 +1,46 @@
"type: excel";
"id";"name" ;"opacity";"strength";"isFluid";"viscosity";"isSolid";"isWall";"luminance";"drops" ;
"0";"TILE_AIR" ; "0"; "0"; "0"; "0"; "0"; "0"; "0";"NULL" ;
"1";"TILE_STONE" ; "8"; "25"; "0"; "0"; "1"; "1"; "0";"TILE_STONE" ;
"2";"TILE_DIRT" ; "8"; "6"; "0"; "0"; "1"; "1"; "0";"TILE_DIRT" ;
"3";"TILE_GRASS" ; "8"; "6"; "0"; "0"; "1"; "1"; "0";"TILE_DIRT" ;
"4";"TILE_PLANK_NORMAL" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_NORMAL" ;
"5";"TILE_PLANK_EBONY" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_EBONY" ;
"6";"TILE_PLANK_BIRCH" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_BIRCH" ;
"7";"TILE_PLANK_ROSEWOOD" ; "8"; "12"; "0"; "0"; "1"; "1"; "0";"TILE_PLANK_ROSEWOOD" ;
"8";"TILE_TRUNK_NORMAL" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_NORMAL" ;
"9";"TILE_TRUNK_EBONY" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_EBONY" ;
"10";"TILE_TRUNK_BIRCH" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_BIRCH" ;
"11";"TILE_TRUNK_ROSEWOOD" ; "8"; "12"; "0"; "0"; "1"; "0"; "0";"TILE_PLANK_ROSEWOOD" ;
"id";"name" ;"opacity";"strength";"fluid";"viscosity";"solid";"wall";"lumcolor";"drop";"fall";"friction"
# Friction: 0: frictionless, <16: slippery, 16: regular, >16: sticky
"0";"TILE_AIR" ; "4"; "0"; "0"; "N/A"; "0"; "0"; "0"; "0"; "0";"16"
"1";"TILE_STONE" ; "32"; "25"; "0"; "N/A"; "1"; "1"; "0"; "1"; "0";"16"
"2";"TILE_DIRT" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "2"; "0";"16"
"3";"TILE_GRASS" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "2"; "0";"16"
"4";"TILE_PLANK_NORMAL" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "4"; "0";"16"
"5";"TILE_PLANK_EBONY" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "5"; "0";"16"
"6";"TILE_PLANK_BIRCH" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "6"; "0";"16"
"7";"TILE_PLANK_BLOODROSE" ; "32"; "12"; "0"; "N/A"; "1"; "1"; "0"; "7"; "0";"16"
"8";"TILE_TRUNK_NORMAL" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "8"; "0";"16"
"9";"TILE_TRUNK_EBONY" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "9"; "0";"16"
"10";"TILE_TRUNK_BIRCH" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "10"; "0";"16"
"11";"TILE_TRUNK_BLOODROSE" ; "32"; "12"; "0"; "N/A"; "1"; "0"; "0"; "11"; "0";"16"
"12";"TILE_STONE" ; "32"; "25"; "0"; "N/A"; "1"; "1"; "0"; "12"; "0";"16"
"13";"TILE_SAND" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "13"; "1";"16"
"14";"TILE_GRAVEL" ; "32"; "6"; "0"; "N/A"; "1"; "0"; "0"; "14"; "1";"16"
"32";"TILE_SNOW" ; "8"; "6"; "0"; "0"; "1"; "1"; "0";"TILE_SNOW" ;
"33";"TILE_ICE_FRAGILE" ; "1"; "1"; "0"; "0"; "1"; "0"; "0";"NULL" ;
"34";"TILE_ICE_NATURAL" ; "6"; "25"; "0"; "0"; "1"; "1"; "0";"TILE_ICE_NATURAL" ;
"35";"TILE_ICE_CLEAR_MAGICAL"; "8"; "25"; "0"; "0"; "1"; "1"; "1";"TILE_ICE_CLEAR_MAGICAL";
"15";"TILE_ORE_MALACHITE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "15"; "0";"16"
"16";"TILE_ORE_HEMATITE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "16"; "0";"16"
"17";"TILE_ORE_NATURAL_GOLD" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "17"; "0";"16"
"18";"TILE_ORE_NATURAL_SILVER" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "18"; "0";"16"
"19";"TILE_ORE_RUTILE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "19"; "0";"16"
"20";"TILE_ORE_NATURAL_AURICHALCUM"; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "20"; "0";"16"
"21";"TILE_GEM_RUBY" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "21"; "0";"16"
"22";"TILE_GEM_EMERALD" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "22"; "0";"16"
"23";"TILE_GEM_SAPPHIRE" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "23"; "0";"16"
"24";"TILE_GEM_TOPAZ" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "24"; "0";"16"
"25";"TILE_GEM_DIAMOND" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "25"; "0";"16"
"26";"TILE_GEM_AMETHYST" ; "32"; "25"; "0"; "N/A"; "1"; "0"; "0"; "26"; "0";"16"
"27";"TILE_SNOW" ; "32"; "6"; "0"; "N/A"; "1"; "1"; "0"; "27"; "0";"16"
"28";"TILE_ICE_FRAGILE" ; "8"; "1"; "0"; "N/A"; "1"; "0"; "0"; "28"; "0";"16"
"29";"TILE_ICE_NATURAL" ; "24"; "25"; "0"; "N/A"; "1"; "1"; "0"; "29"; "0"; "8"
"30";"TILE_ICE_CLEAR_MAGICAL" ; "32"; "25"; "0"; "N/A"; "1"; "1"; "855567"; "30"; "0"; "8"
# see scandinavian name set female of this tile id!
"31";"TILE_PLATFORM_STONE" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "31"; "0";"16"
"32";"TILE_PLATFORM_WOODEN" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "32"; "0";"16"
"33";"TILE_PLATFORM_EBONY" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "33"; "0";"16"
"34";"TILE_PLATFORM_BIRCH" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "34"; "0";"16"
"35";"TILE_PLATFORM_BLOODROSE" ; "2"; "0"; "0"; "N/A"; "0"; "0"; "0"; "35"; "0";"16"
"36";"TILE_TORCH" ; "0"; "0"; "0"; "N/A"; "0"; "0";"16777215"; "36"; "0";"16"
"239";"TILE_WATER" ; "16"; "100"; "1"; "2"; "0"; "0";"15464447"; "239"; "0";"16"
"255";"TILE_LAVA" ; "0"; "100"; "1"; "2"; "0"; "0"; "8397312"; "239"; "0";"16"
Can't render this file because it contains an unexpected character in line 2 and column 12.