mixins: replace drawScene

This is in preparation for extending draw distance.
This commit is contained in:
Adam
2018-11-12 12:20:17 -05:00
parent 49d7c15f24
commit f09a0d7d89
5 changed files with 367 additions and 40 deletions

View File

@@ -24,7 +24,6 @@
*/
package net.runelite.mixins;
import net.runelite.api.Perspective;
import net.runelite.api.mixins.FieldHook;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
@@ -40,9 +39,6 @@ public abstract class CameraMixin implements RSClient
@Shadow("clientInstance")
static RSClient client;
@Shadow("isDrawingScene")
static boolean isDrawingScene;
@Inject
static boolean pitchRelaxEnabled = false;
@@ -113,27 +109,4 @@ public abstract class CameraMixin implements RSClient
}
lastPitch = pitch;
}
// All of this is to bypass a check in Scene.drawScene
@FieldHook("pitchSin")
@Inject
static void onPitchSinChanged(int idx)
{
if (pitchRelaxEnabled && isDrawingScene)
{
client.setPitchSin(Perspective.SINE[client.getCameraPitch()]);
}
}
@FieldHook("pitchCos")
@Inject
static void onPitchCosChanged(int idx)
{
if (pitchRelaxEnabled && isDrawingScene)
{
client.setPitchCos(Perspective.COSINE[client.getCameraPitch()]);
}
}
}

View File

@@ -24,11 +24,11 @@
*/
package net.runelite.mixins;
import net.runelite.api.Perspective;
import net.runelite.api.Renderable;
import net.runelite.api.SceneTilePaint;
import net.runelite.api.Tile;
import net.runelite.api.mixins.Copy;
import net.runelite.api.mixins.Inject;
import net.runelite.api.mixins.Mixin;
import net.runelite.api.mixins.Replace;
import net.runelite.api.mixins.Shadow;
@@ -37,33 +37,291 @@ import net.runelite.rs.api.RSDecorativeObject;
import net.runelite.rs.api.RSGroundObject;
import net.runelite.rs.api.RSItemLayer;
import net.runelite.rs.api.RSScene;
import net.runelite.rs.api.RSTile;
import net.runelite.rs.api.RSWallObject;
@Mixin(RSScene.class)
public abstract class RSSceneMixin implements RSScene
{
private static final int MAX_DISTANCE = 25;
private static final int PITCH_LOWER_LIMIT = 128;
private static final int PITCH_UPPER_LIMIT = 383;
@Shadow("clientInstance")
private static RSClient client;
@Inject
static boolean isDrawingScene;
@Copy("drawScene")
abstract void rs$drawScene(int cameraX, int cameraY, int cameraZ, int cameraPitch, int cameraYaw, int plane);
@Shadow("pitchRelaxEnabled")
private static boolean pitchRelaxEnabled;
@Replace("drawScene")
void rl$drawScene(int cameraX, int cameraY, int cameraZ, int cameraPitch, int cameraYaw, int plane)
{
try
final int maxX = getMaxX();
final int maxY = getMaxY();
final int maxZ = getMaxZ();
final int minLevel = getMinLevel();
final RSTile[][][] tiles = getTiles();
final int distance = MAX_DISTANCE;
if (cameraX < 0)
{
isDrawingScene = true;
rs$drawScene(cameraX, cameraY, cameraZ, cameraPitch, cameraYaw, plane);
client.getCallbacks().drawScene();
cameraX = 0;
}
finally
else if (cameraX >= maxX * Perspective.LOCAL_TILE_SIZE)
{
isDrawingScene = false;
cameraX = maxX * Perspective.LOCAL_TILE_SIZE - 1;
}
if (cameraZ < 0)
{
cameraZ = 0;
}
else if (cameraZ >= maxZ * Perspective.LOCAL_TILE_SIZE)
{
cameraZ = maxZ * Perspective.LOCAL_TILE_SIZE - 1;
}
// we store the uncapped pitch for setting camera angle for the pitch relaxer
// we still have to cap the pitch in order to access the visibility map, though
int realPitch = cameraPitch;
if (cameraPitch < PITCH_LOWER_LIMIT)
{
cameraPitch = PITCH_LOWER_LIMIT;
}
else if (cameraPitch > PITCH_UPPER_LIMIT)
{
cameraPitch = PITCH_UPPER_LIMIT;
}
if (!pitchRelaxEnabled)
{
realPitch = cameraPitch;
}
client.setCycle(client.getCycle() + 1);
client.setPitchSin(Perspective.SINE[realPitch]);
client.setPitchCos(Perspective.COSINE[realPitch]);
client.setYawSin(Perspective.SINE[cameraYaw]);
client.setYawCos(Perspective.COSINE[cameraYaw]);
final int[][][] tileHeights = client.getTileHeights();
boolean[][] renderArea = client.getVisibilityMaps()[(cameraPitch - 128) / 32][cameraYaw / 64];
client.setRenderArea(renderArea);
client.setCameraX2(cameraX);
client.setCameraY2(cameraY);
client.setCameraZ2(cameraZ);
int screenCenterX = cameraX / Perspective.LOCAL_TILE_SIZE;
int screenCenterZ = cameraZ / Perspective.LOCAL_TILE_SIZE;
client.setScreenCenterX(screenCenterX);
client.setScreenCenterZ(screenCenterZ);
client.setScenePlane(plane);
int minTileX = screenCenterX - distance;
if (minTileX < 0)
{
minTileX = 0;
}
int minTileZ = screenCenterZ - distance;
if (minTileZ < 0)
{
minTileZ = 0;
}
int maxTileX = screenCenterX + distance;
if (maxTileX > maxX)
{
maxTileX = maxX;
}
int maxTileZ = screenCenterZ + distance;
if (maxTileZ > maxZ)
{
maxTileZ = maxZ;
}
client.setMinTileX(minTileX);
client.setMinTileZ(minTileZ);
client.setMaxTileX(maxTileX);
client.setMaxTileZ(maxTileZ);
updateOccluders();
client.setTileUpdateCount(0);
for (int z = minLevel; z < maxY; ++z)
{
RSTile[][] planeTiles = tiles[z];
for (int x = minTileX; x < maxTileX; ++x)
{
for (int y = minTileZ; y < maxTileZ; ++y)
{
RSTile tile = planeTiles[x][y];
if (tile != null)
{
if (tile.getPhysicalLevel() <= plane
&& (renderArea[x - screenCenterX + MAX_DISTANCE][y - screenCenterZ + MAX_DISTANCE]
|| tileHeights[z][x][y] - cameraY >= 2000))
{
tile.setDraw(true);
tile.setVisible(true);
tile.setDrawEntities(true);
client.setTileUpdateCount(client.getTileUpdateCount() + 1);
}
else
{
tile.setDraw(false);
tile.setVisible(false);
tile.setWallCullDirection(0);
}
}
}
}
}
for (int z = minLevel; z < maxY; ++z)
{
RSTile[][] planeTiles = tiles[z];
for (int x = -distance; x <= 0; ++x)
{
int var10 = x + screenCenterX;
int var16 = screenCenterX - x;
if (var10 >= minTileX || var16 < maxTileX)
{
for (int y = -distance; y <= 0; ++y)
{
int var13 = y + screenCenterZ;
int var14 = screenCenterZ - y;
if (var10 >= minTileX)
{
if (var13 >= minTileZ)
{
RSTile tile = planeTiles[var10][var13];
if (tile != null && tile.isDraw())
{
draw(tile, true);
}
}
if (var14 < maxTileZ)
{
RSTile tile = planeTiles[var10][var14];
if (tile != null && tile.isDraw())
{
draw(tile, true);
}
}
}
if (var16 < maxTileX)
{
if (var13 >= minTileZ)
{
RSTile tile = planeTiles[var16][var13];
if (tile != null && tile.isDraw())
{
draw(tile, true);
}
}
if (var14 < maxTileZ)
{
RSTile tile = planeTiles[var16][var14];
if (tile != null && tile.isDraw())
{
draw(tile, true);
}
}
}
if (client.getTileUpdateCount() == 0)
{
client.setCheckClick(false);
client.getCallbacks().drawScene();
return;
}
}
}
}
}
for (int z = minLevel; z < maxY; ++z)
{
RSTile[][] planeTiles = tiles[z];
for (int x = -distance; x <= 0; ++x)
{
int var10 = x + screenCenterX;
int var16 = screenCenterX - x;
if (var10 >= minTileX || var16 < maxTileX)
{
for (int y = -distance; y <= 0; ++y)
{
int var13 = y + screenCenterZ;
int var14 = screenCenterZ - y;
if (var10 >= minTileX)
{
if (var13 >= minTileZ)
{
RSTile tile = planeTiles[var10][var13];
if (tile != null && tile.isDraw())
{
draw(tile, false);
}
}
if (var14 < maxTileZ)
{
RSTile tile = planeTiles[var10][var14];
if (tile != null && tile.isDraw())
{
draw(tile, false);
}
}
}
if (var16 < maxTileX)
{
if (var13 >= minTileZ)
{
RSTile tile = planeTiles[var16][var13];
if (tile != null && tile.isDraw())
{
draw(tile, false);
}
}
if (var14 < maxTileZ)
{
RSTile tile = planeTiles[var16][var14];
if (tile != null && tile.isDraw())
{
draw(tile, false);
}
}
}
if (client.getTileUpdateCount() == 0)
{
client.setCheckClick(false);
client.getCallbacks().drawScene();
return;
}
}
}
}
}
client.setCheckClick(false);
client.getCallbacks().drawScene();
}
@Copy("addBoundaryDecoration")