Some work on terrain rendering
This commit is contained in:
@@ -55,8 +55,8 @@ public class HeightMapDumper
|
||||
|
||||
public void load() throws IOException
|
||||
{
|
||||
regionLoader = new RegionLoader();
|
||||
regionLoader.loadRegions(store);
|
||||
regionLoader = new RegionLoader(store);
|
||||
regionLoader.loadRegions();
|
||||
regionLoader.calculateBounds();
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,8 @@ public class MapImageDumper
|
||||
if (labelRegions)
|
||||
{
|
||||
graphics.setColor(Color.WHITE);
|
||||
graphics.drawString(baseX + "," + baseY, drawBaseX * MAP_SCALE, drawBaseY * MAP_SCALE + graphics.getFontMetrics().getHeight());
|
||||
String str = baseX + "," + baseY + " (" + region.getRegionX() + "," + region.getRegionY() + ")";
|
||||
graphics.drawString(str, drawBaseX * MAP_SCALE, drawBaseY * MAP_SCALE + graphics.getFontMetrics().getHeight());
|
||||
}
|
||||
|
||||
if (outlineRegions)
|
||||
@@ -351,8 +352,8 @@ public class MapImageDumper
|
||||
|
||||
private void loadRegions(Store store) throws IOException
|
||||
{
|
||||
regionLoader = new RegionLoader();
|
||||
regionLoader.loadRegions(store);
|
||||
regionLoader = new RegionLoader(store);
|
||||
regionLoader.loadRegions();
|
||||
regionLoader.calculateBounds();
|
||||
|
||||
logger.info("North most region: {}", regionLoader.getLowestY().getBaseY());
|
||||
|
||||
@@ -5,4 +5,99 @@ public class Vector3f
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
|
||||
public Vector3f()
|
||||
{
|
||||
}
|
||||
|
||||
public Vector3f(float x, float y, float z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public Vector3f(Vector3f other)
|
||||
{
|
||||
this.x = other.x;
|
||||
this.y = other.y;
|
||||
this.z = other.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Vector3f{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int hash = 7;
|
||||
hash = 23 * hash + Float.floatToIntBits(this.x);
|
||||
hash = 23 * hash + Float.floatToIntBits(this.y);
|
||||
hash = 23 * hash + Float.floatToIntBits(this.z);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (obj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
final Vector3f other = (Vector3f) obj;
|
||||
if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Float.floatToIntBits(this.y) != Float.floatToIntBits(other.y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (Float.floatToIntBits(this.z) != Float.floatToIntBits(other.z))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public float getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public void setX(float x)
|
||||
{
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
public float getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public void setY(float y)
|
||||
{
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public float getZ()
|
||||
{
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setZ(float z)
|
||||
{
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,13 @@ public class Region
|
||||
this.baseY = (id & 0xFF) << 6;
|
||||
}
|
||||
|
||||
public Region(int x, int y)
|
||||
{
|
||||
this.regionID = x << 8 | y;
|
||||
this.baseX = x << 6;
|
||||
this.baseY = y << 6;
|
||||
}
|
||||
|
||||
public void loadTerrain(byte[] buf)
|
||||
{
|
||||
InputStream in = new InputStream(buf);
|
||||
@@ -202,4 +209,14 @@ public class Region
|
||||
{
|
||||
return locations;
|
||||
}
|
||||
|
||||
public int getRegionX()
|
||||
{
|
||||
return baseX >> 6;
|
||||
}
|
||||
|
||||
public int getRegionY()
|
||||
{
|
||||
return baseY >> 6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,60 +46,75 @@ public class RegionLoader
|
||||
|
||||
private static final int MAX_REGION = 32768;
|
||||
|
||||
private final Store store;
|
||||
private final Index index;
|
||||
private final XteaKeyManager keyManager;
|
||||
|
||||
private final List<Region> regions = new ArrayList<>();
|
||||
private Region lowestX = null, lowestY = null;
|
||||
private Region highestX = null, highestY = null;
|
||||
|
||||
public void loadRegions(Store store) throws IOException
|
||||
public RegionLoader(Store store)
|
||||
{
|
||||
Index index = store.getIndex(IndexType.MAPS);
|
||||
XteaKeyManager keyManager = index.getXteaManager();
|
||||
this.store = store;
|
||||
index = store.getIndex(IndexType.MAPS);
|
||||
keyManager = index.getXteaManager();
|
||||
}
|
||||
|
||||
public void loadRegions() throws IOException
|
||||
{
|
||||
for (int i = 0; i < MAX_REGION; ++i)
|
||||
{
|
||||
int x = i >> 8;
|
||||
int y = i & 0xFF;
|
||||
|
||||
Archive map = index.findArchiveByName("m" + x + "_" + y);
|
||||
Archive land = index.findArchiveByName("l" + x + "_" + y);
|
||||
|
||||
assert (map == null) == (land == null);
|
||||
|
||||
if (map == null || land == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
assert map.getFiles().size() == 1;
|
||||
assert land.getFiles().size() == 1;
|
||||
|
||||
map.decompressAndLoad(null);
|
||||
|
||||
byte[] data = map.getFiles().get(0).getContents();
|
||||
|
||||
Region region = new Region(i);
|
||||
region.loadTerrain(data);
|
||||
|
||||
int[] keys = keyManager.getKeys(i);
|
||||
if (keys != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
land.decompressAndLoad(keys);
|
||||
|
||||
data = land.getFiles().get(0).getContents();
|
||||
region.loadLocations(data);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.debug("Can't decrypt region " + i, ex);
|
||||
}
|
||||
}
|
||||
|
||||
regions.add(region);
|
||||
Region region = this.loadRegionFromArchive(i);
|
||||
if (region != null)
|
||||
regions.add(region);
|
||||
}
|
||||
}
|
||||
|
||||
public Region loadRegionFromArchive(int i) throws IOException
|
||||
{
|
||||
int x = i >> 8;
|
||||
int y = i & 0xFF;
|
||||
|
||||
Archive map = index.findArchiveByName("m" + x + "_" + y);
|
||||
Archive land = index.findArchiveByName("l" + x + "_" + y);
|
||||
|
||||
assert (map == null) == (land == null);
|
||||
|
||||
if (map == null || land == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
assert map.getFiles().size() == 1;
|
||||
assert land.getFiles().size() == 1;
|
||||
|
||||
map.decompressAndLoad(null);
|
||||
|
||||
byte[] data = map.getFiles().get(0).getContents();
|
||||
|
||||
Region region = new Region(i);
|
||||
region.loadTerrain(data);
|
||||
|
||||
int[] keys = keyManager.getKeys(i);
|
||||
if (keys != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
land.decompressAndLoad(keys);
|
||||
|
||||
data = land.getFiles().get(0).getContents();
|
||||
region.loadLocations(data);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
logger.debug("Can't decrypt region " + i, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
public void calculateBounds()
|
||||
{
|
||||
for (Region region : regions)
|
||||
|
||||
@@ -27,23 +27,59 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.cache;
|
||||
|
||||
package net.runelite.modelviewer;
|
||||
import com.google.common.io.Files;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import net.runelite.cache.definitions.OverlayDefinition;
|
||||
import net.runelite.cache.definitions.loaders.OverlayLoader;
|
||||
import net.runelite.cache.fs.Archive;
|
||||
import net.runelite.cache.fs.File;
|
||||
import net.runelite.cache.fs.Index;
|
||||
import net.runelite.cache.fs.Store;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Vector3f
|
||||
public class OverlayDumper
|
||||
{
|
||||
public float x, y, z;
|
||||
private static final Logger logger = LoggerFactory.getLogger(OverlayDumper.class);
|
||||
|
||||
public Vector3f(float x, float y, float z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
@Rule
|
||||
public TemporaryFolder folder = StoreLocation.getTemporaryFolder();
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
||||
|
||||
@Test
|
||||
public void extract() throws IOException
|
||||
{
|
||||
return "Vector3f{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
|
||||
java.io.File base = StoreLocation.LOCATION,
|
||||
outDir = folder.newFile();
|
||||
|
||||
int count = 0;
|
||||
|
||||
try (Store store = new Store(base))
|
||||
{
|
||||
store.load();
|
||||
|
||||
Index index = store.getIndex(IndexType.CONFIGS);
|
||||
Archive archive = index.getArchive(ConfigType.OVERLAY.getId());
|
||||
|
||||
for (File file : archive.getFiles())
|
||||
{
|
||||
OverlayLoader loader = new OverlayLoader();
|
||||
OverlayDefinition overlay = loader.load(file.getFileId(), file.getContents());
|
||||
|
||||
Files.write(gson.toJson(overlay), new java.io.File(outDir, file.getFileId() + ".json"), Charset.defaultCharset());
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Dumped {} overlays to {}", count, outDir);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@
|
||||
*/
|
||||
package net.runelite.modelviewer;
|
||||
|
||||
import net.runelite.cache.models.Vector3f;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -39,7 +40,7 @@ public class Camera
|
||||
{
|
||||
private static final float MAX_X = 89;
|
||||
|
||||
public float moveSpeed = 0.20f;
|
||||
public float moveSpeed = 0.60f;
|
||||
|
||||
private float mouseSensitivity = 0.05f;
|
||||
|
||||
@@ -196,104 +197,14 @@ public class Camera
|
||||
return pos;
|
||||
}
|
||||
|
||||
public void setX(float x)
|
||||
{
|
||||
pos.x = x;
|
||||
}
|
||||
|
||||
public float getX()
|
||||
{
|
||||
return pos.x;
|
||||
}
|
||||
|
||||
public void addToX(float x)
|
||||
{
|
||||
pos.x += x;
|
||||
}
|
||||
|
||||
public void setY(float y)
|
||||
{
|
||||
pos.y = y;
|
||||
}
|
||||
|
||||
public float getY()
|
||||
{
|
||||
return pos.y;
|
||||
}
|
||||
|
||||
public void addToY(float y)
|
||||
{
|
||||
pos.y += y;
|
||||
}
|
||||
|
||||
public void setZ(float z)
|
||||
{
|
||||
pos.z = z;
|
||||
}
|
||||
|
||||
public float getZ()
|
||||
{
|
||||
return pos.z;
|
||||
}
|
||||
|
||||
public void addToZ(float z)
|
||||
{
|
||||
pos.z += z;
|
||||
}
|
||||
|
||||
public void setRotation(Vector3f rotation)
|
||||
{
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
public Vector3f getRotation()
|
||||
{
|
||||
return rotation;
|
||||
}
|
||||
|
||||
public void setRotationX(float x)
|
||||
public void setRotation(Vector3f rotation)
|
||||
{
|
||||
rotation.x = x;
|
||||
}
|
||||
|
||||
public float getRotationX()
|
||||
{
|
||||
return rotation.x;
|
||||
}
|
||||
|
||||
public void addToRotationX(float x)
|
||||
{
|
||||
rotation.x += x;
|
||||
}
|
||||
|
||||
public void setRotationY(float y)
|
||||
{
|
||||
rotation.y = y;
|
||||
}
|
||||
|
||||
public float getRotationY()
|
||||
{
|
||||
return rotation.y;
|
||||
}
|
||||
|
||||
public void addToRotationY(float y)
|
||||
{
|
||||
rotation.y += y;
|
||||
}
|
||||
|
||||
public void setRotationZ(float z)
|
||||
{
|
||||
rotation.z = z;
|
||||
}
|
||||
|
||||
public float getRotationZ()
|
||||
{
|
||||
return rotation.z;
|
||||
}
|
||||
|
||||
public void addToRotationZ(float z)
|
||||
{
|
||||
rotation.z += z;
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
public void setMouseSensitivity(float mouseSensitivity)
|
||||
|
||||
@@ -33,43 +33,59 @@ import com.google.gson.Gson;
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.runelite.cache.definitions.ModelDefinition;
|
||||
import net.runelite.cache.definitions.NpcDefinition;
|
||||
import net.runelite.cache.definitions.OverlayDefinition;
|
||||
import net.runelite.cache.definitions.UnderlayDefinition;
|
||||
import net.runelite.cache.definitions.loaders.ModelLoader;
|
||||
import net.runelite.cache.models.Vector3f;
|
||||
import net.runelite.cache.models.VertexNormal;
|
||||
import net.runelite.cache.region.Region;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import static org.lwjgl.opengl.GL11.glRotatef;
|
||||
|
||||
public class ModelViewer
|
||||
{
|
||||
private static final int NUM_UNDERLAYS = 150;
|
||||
private static final int NUM_OVERLAYS = 174;
|
||||
|
||||
private static UnderlayDefinition[] underlays = new UnderlayDefinition[NUM_UNDERLAYS];
|
||||
private static OverlayDefinition[] overlays = new OverlayDefinition[NUM_OVERLAYS];
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
Options options = new Options();
|
||||
|
||||
options.addOption(null, "npcdir", true, "npc directory");
|
||||
options.addOption(null, "modeldir", true, "model directory");
|
||||
options.addOption(null, "mapdir", true, "maps directory");
|
||||
|
||||
options.addOption(null, "npc", true, "npc to render");
|
||||
options.addOption(null, "model", true, "model to render");
|
||||
options.addOption(null, "map", true, "map region to render");
|
||||
|
||||
CommandLineParser parser = new DefaultParser();
|
||||
CommandLine cmd = parser.parse(options, args);
|
||||
|
||||
String npcdir = cmd.getOptionValue("npcdir");
|
||||
String modeldir = cmd.getOptionValue("modeldir");
|
||||
String mapdir = cmd.getOptionValue("mapdir");
|
||||
|
||||
NpcDefinition npcdef = null;
|
||||
List<ModelDefinition> models = new ArrayList<>();
|
||||
Region region = null;
|
||||
|
||||
if (cmd.hasOption("model"))
|
||||
{
|
||||
@@ -81,7 +97,7 @@ public class ModelViewer
|
||||
ModelDefinition md = loader.load(b);
|
||||
models.add(md);
|
||||
}
|
||||
else if (cmd.hasOption("npc"))
|
||||
if (cmd.hasOption("npc"))
|
||||
{
|
||||
String npc = cmd.getOptionValue("npc");
|
||||
|
||||
@@ -98,10 +114,23 @@ public class ModelViewer
|
||||
models.add(md);
|
||||
}
|
||||
}
|
||||
else
|
||||
if (cmd.hasOption("map"))
|
||||
{
|
||||
System.out.println("Must specify model or npc");
|
||||
return;
|
||||
String map = cmd.getOptionValue("map");
|
||||
String[] s = map.split(",");
|
||||
|
||||
int x = Integer.parseInt(s[0]), y = Integer.parseInt(s[1]);
|
||||
|
||||
region = new Region(x, y);
|
||||
|
||||
try (FileInputStream fin = new FileInputStream(mapdir + "/m" + x + "_" + y + ".dat"))
|
||||
{
|
||||
byte[] b = IOUtils.toByteArray(fin);
|
||||
region.loadTerrain(b);
|
||||
}
|
||||
|
||||
loadUnderlays();
|
||||
loadOverlays();
|
||||
}
|
||||
|
||||
Display.setDisplayMode(new DisplayMode(800, 600));
|
||||
@@ -113,7 +142,7 @@ public class ModelViewer
|
||||
GL11.glLoadIdentity();
|
||||
double aspect = 1;
|
||||
double near = 1; // near should be chosen as far into the scene as possible
|
||||
double far = 1000;
|
||||
double far = 10000;
|
||||
double fov = 1; // 1 gives you a 90° field of view. It's tan(fov_angle)/2.
|
||||
GL11.glFrustum(-aspect * near * fov, aspect * near * fov, -fov, fov, near, far);
|
||||
|
||||
@@ -121,7 +150,6 @@ public class ModelViewer
|
||||
|
||||
GL11.glCullFace(GL11.GL_BACK);
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
|
||||
long last = 0;
|
||||
|
||||
Camera camera = new Camera();
|
||||
@@ -136,6 +164,8 @@ public class ModelViewer
|
||||
drawModel(npcdef, def);
|
||||
}
|
||||
|
||||
drawRegion(region);
|
||||
|
||||
Display.update();
|
||||
Display.sync(50); // fps
|
||||
|
||||
@@ -224,6 +254,129 @@ public class ModelViewer
|
||||
GL11.glEnd();
|
||||
}
|
||||
|
||||
private static void drawRegion(Region region)
|
||||
{
|
||||
if (region == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GL11.glBegin(GL11.GL_TRIANGLES);
|
||||
|
||||
for (int regionX = 0; regionX < Region.X; ++regionX)
|
||||
{
|
||||
for (int regionY = 0; regionY < Region.Y; ++regionY)
|
||||
{
|
||||
int x = regionX;
|
||||
int y = regionY;
|
||||
|
||||
int TILE_SCALE = 16;
|
||||
x *= TILE_SCALE;
|
||||
y *= TILE_SCALE;
|
||||
|
||||
/*
|
||||
Split into two triangles with verticies
|
||||
x,y,z1 x+1,y,z2 x,y+1,z3
|
||||
x,y+1,z3 x+1,y,z2 x+1,y+1,z4
|
||||
|
||||
z1 = height
|
||||
z2 = height of tile x+1
|
||||
z3 = height of tile y-1
|
||||
|
||||
in rs 0,0 (x,y) is the bottom left with
|
||||
y increasing going further from you
|
||||
|
||||
in opengl, 0,0 (x,z) is the bottom left
|
||||
with z decreasing going further from you
|
||||
|
||||
in rs, height is also negative
|
||||
|
||||
so we do rs(x,y,z) -> opengl(x,-z,-y)
|
||||
*/
|
||||
int z1 = -region.getTileHeight(0, regionX, regionY);
|
||||
int z2 = regionX + 1 < Region.X ? -region.getTileHeight(0, regionX + 1, regionY) : z1;
|
||||
int z3 = regionY + 1 < Region.Y ? -region.getTileHeight(0, regionX, regionY + 1) : z1;
|
||||
int z4 = regionX + 1 < Region.X && regionY + 1 < Region.Y ? -region.getTileHeight(0, regionX + 1, regionY + 1) : z1;
|
||||
|
||||
// scale down height (I randomally picked this)
|
||||
z1 /= 4;
|
||||
z2 /= 4;
|
||||
z3 /= 4;
|
||||
z4 /= 4;
|
||||
|
||||
int underlayId = region.getUnderlayId(0, regionX, regionY);
|
||||
int overlayId = region.getOverlayId(0, regionX, regionY);
|
||||
|
||||
Color color = null;
|
||||
if (underlayId > 0)
|
||||
{
|
||||
UnderlayDefinition ud = underlays[underlayId - 1];
|
||||
color = new Color(ud.getColor());
|
||||
}
|
||||
if (overlayId > 0)
|
||||
{
|
||||
OverlayDefinition od = overlays[overlayId - 1];
|
||||
color = new Color(od.getRgbColor());
|
||||
|
||||
if (od.getSecondaryRgbColor() > -1)
|
||||
{
|
||||
color = new Color(od.getSecondaryRgbColor());
|
||||
}
|
||||
|
||||
if (od.getTexture() > -1)
|
||||
{
|
||||
// textures?
|
||||
}
|
||||
}
|
||||
|
||||
if (color != null)
|
||||
{
|
||||
GL11.glColor3f((float) color.getRed() / 255f, (float) color.getGreen() / 255f, (float) color.getBlue() / 255f);
|
||||
}
|
||||
|
||||
GL11.glVertex3i(x, z1, -y);
|
||||
GL11.glVertex3i(x + TILE_SCALE, z2, -y);
|
||||
GL11.glVertex3i(x, z3, -(y + TILE_SCALE));
|
||||
|
||||
GL11.glVertex3i(x, z3, -(y + TILE_SCALE));
|
||||
GL11.glVertex3i(x + TILE_SCALE, z2, -y);
|
||||
GL11.glVertex3i(x + TILE_SCALE, z4, -(y + TILE_SCALE));
|
||||
}
|
||||
}
|
||||
|
||||
GL11.glEnd();
|
||||
}
|
||||
|
||||
private static void loadUnderlays() throws IOException
|
||||
{
|
||||
for (int i = 0; i < NUM_UNDERLAYS; ++i)
|
||||
{
|
||||
try (FileInputStream fin = new FileInputStream("underlays/" + i + ".json"))
|
||||
{
|
||||
UnderlayDefinition underlay = new Gson().fromJson(new InputStreamReader(fin), UnderlayDefinition.class);
|
||||
underlays[i] = underlay;
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadOverlays() throws IOException
|
||||
{
|
||||
for (int i = 0; i < NUM_UNDERLAYS; ++i)
|
||||
{
|
||||
try (FileInputStream fin = new FileInputStream("overlays/" + i + ".json"))
|
||||
{
|
||||
OverlayDefinition overlay = new Gson().fromJson(new InputStreamReader(fin), OverlayDefinition.class);
|
||||
overlays[i] = overlay;
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// found these two functions here https://www.rune-server.org/runescape-development/rs2-client/tools/589900-rs2-hsb-color-picker.html
|
||||
public static int RGB_to_RS2HSB(int red, int green, int blue)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user