Fix hiding player attacks in client, add option to hide cast as well (#896)

Tiny bit of refactoring as well
This commit is contained in:
Lucwousin
2019-07-05 23:10:02 +02:00
committed by Kyleeld
parent a8cf657e4c
commit 2367f7ee18
19 changed files with 187 additions and 69 deletions

View File

@@ -2,6 +2,7 @@ package net.runelite.injector.raw;
import com.google.common.base.Stopwatch;
import java.util.Iterator;
import java.util.ListIterator;
import net.runelite.asm.Method;
import net.runelite.asm.attributes.code.Instruction;
import net.runelite.asm.attributes.code.Instructions;
@@ -9,9 +10,12 @@ import net.runelite.asm.attributes.code.Label;
import net.runelite.asm.attributes.code.instruction.types.ComparisonInstruction;
import net.runelite.asm.attributes.code.instruction.types.JumpingInstruction;
import net.runelite.asm.attributes.code.instructions.ALoad;
import net.runelite.asm.attributes.code.instructions.BiPush;
import net.runelite.asm.attributes.code.instructions.GetStatic;
import net.runelite.asm.attributes.code.instructions.IAnd;
import net.runelite.asm.attributes.code.instructions.IfACmpEq;
import net.runelite.asm.attributes.code.instructions.IfACmpNe;
import net.runelite.asm.attributes.code.instructions.IfICmpNe;
import net.runelite.asm.attributes.code.instructions.IfNe;
import net.runelite.asm.attributes.code.instructions.InvokeStatic;
import net.runelite.asm.pool.Field;
@@ -31,14 +35,28 @@ public class HidePlayerAttacks
this.inject = inject;
}
private Method addPlayerOptions;
private net.runelite.asm.pool.Method shouldHideAttackOptionFor;
public void inject() throws InjectionException
{
Stopwatch stopwatch = Stopwatch.createStarted();
final Method addPlayerOptions = InjectUtil.findStaticMethod(inject, "addPlayerToMenu");
addPlayerOptions = InjectUtil.findStaticMethod(inject, "addPlayerToMenu");
shouldHideAttackOptionFor = inject.getVanilla().findClass("client").findMethod("shouldHideAttackOptionFor").getPoolMethod();
injectHideAttack();
injectHideCast();
stopwatch.stop();
log.info("HidePlayerAttacks took {}", stopwatch.toString());
}
private void injectHideAttack() throws InjectionException
{
final Field AttackOption_hidden = InjectUtil.findDeobField(inject, "AttackOption_hidden", "AttackOption").getPoolField();
final Field attackOption = InjectUtil.findDeobField(inject, "playerAttackOption", "Client").getPoolField();
final net.runelite.asm.pool.Method shouldHideAttackOptionFor = inject.getVanilla().findClass("client").findMethod("shouldHideAttackOptionFor").getPoolMethod();
// GETSTATIC GETSTATIC
// GETSTATIC GETSTATIC
@@ -123,9 +141,65 @@ public class HidePlayerAttacks
IfNe i3 = new IfNe(ins, label);
ins.addInstruction(injectIdx, i3);
}
stopwatch.stop();
private void injectHideCast() throws InjectionException
{
// LABEL before
// BIPUSH 8
// LDC (garbage)
// GETSTATIC selectedSpellFlags
// IMUL
// BIPUSH 8
// IAND
// IF_ICMPNE -> skip adding option
//
// <--- Inject call here
// <--- Inject comparison here (duh)
//
// add option n such
log.info("HidePlayerAttacks took {}", stopwatch.toString());
Instructions ins = addPlayerOptions.getCode().getInstructions();
ListIterator<Instruction> iterator = ins.getInstructions().listIterator();
while (iterator.hasNext())
{
Instruction i = iterator.next();
if (!(i instanceof BiPush) || (byte) ((BiPush) i).getConstant() != 8)
{
continue;
}
i = iterator.next();
while (!(i instanceof BiPush) || (byte) ((BiPush) i).getConstant() != 8)
{
i = iterator.next();
}
i = iterator.next();
if (!(i instanceof IAnd))
{
throw new InjectionException("Yikes I didn't expect this");
}
i = iterator.next();
if (!(i instanceof IfICmpNe))
{
throw new InjectionException("Yikes I didn't expect this");
}
Label target = ((IfICmpNe) i).getJumps().get(0);
// Load the player
ALoad i1 = new ALoad(ins, 0);
// Get the boolean
InvokeStatic i2 = new InvokeStatic(ins, shouldHideAttackOptionFor);
// Compare n such
IfNe i3 = new IfNe(ins, target);
iterator.add(i1);
iterator.add(i2);
iterator.add(i3);
return;
}
}
}

View File

@@ -27,6 +27,7 @@ package net.runelite.api;
import java.awt.Canvas;
import java.awt.Dimension;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
@@ -1661,13 +1662,23 @@ public interface Client extends GameShell
String getSelectedSpellName();
boolean getIsSpellSelected();
boolean isSpellSelected();
/**
* Set whether or not player attack options will be hidden for clanmembers/friends
*/
void setHideFriendAttackOptions(boolean yes);
/**
* Set whether or not player cast options will be hidden for clanmembers/friends
*/
void setHideFriendCastOptions(boolean yes);
/**
* Set spells excluded from above hiding
*/
void setUnhiddenCasts(HashSet<String> casts);
/**
* Sorts the current menu entries in the same way the client does this.
* The last entry will be the left click one after this.

View File

@@ -24,6 +24,7 @@
*/
package net.runelite.mixins;
import java.util.HashSet;
import net.runelite.api.ChatMessageType;
import net.runelite.api.ClanMember;
import net.runelite.api.EnumDefinition;
@@ -200,7 +201,13 @@ public abstract class RSClientMixin implements RSClient
}
@Inject
private static boolean hideFriendAttackOptions;
private static boolean hideFriendAttackOptions = false;
@Inject
private static boolean hideFriendCastOptions = false;
@Inject
private static HashSet<String> unhiddenCasts = new HashSet<String>();
@Inject
@Override
@@ -209,6 +216,20 @@ public abstract class RSClientMixin implements RSClient
hideFriendAttackOptions = yes;
}
@Inject
@Override
public void setHideFriendCastOptions(boolean yes)
{
hideFriendCastOptions = yes;
}
@Inject
@Override
public void setUnhiddenCasts(HashSet<String> casts)
{
unhiddenCasts = casts;
}
@Inject
public RSClientMixin()
{
@@ -1577,6 +1598,13 @@ public abstract class RSClientMixin implements RSClient
@Inject
static boolean shouldHideAttackOptionFor(RSPlayer p)
{
if (client.isSpellSelected())
{
return hideFriendCastOptions
&& (p.isFriended() || p.isClanMember())
&& !unhiddenCasts.contains(client.getSelectedSpellName());
}
return hideFriendAttackOptions && p.isFriended() || p.isClanMember();
}
}

View File

@@ -1012,7 +1012,7 @@ public interface RSClient extends RSGameShell, Client
String getSelectedSpellName();
@Import("isSpellSelected")
boolean getIsSpellSelected();
boolean isSpellSelected();
@Import("readSoundEffect")
RSSoundEffect getTrack(RSAbstractIndexCache indexData, int id, int var0);

View File

@@ -271,7 +271,7 @@ public class BufferedSource implements Runnable {
Client.tileLastDrawnActor[var3][var4] = Client.viewportDrawCount;
}
long var5 = FontName.method5637(0, 0, 1, !var2.definition.isInteractable, Client.npcIndices[var1]);
long var5 = FontName.calculateTag(0, 0, 1, !var2.definition.isInteractable, Client.npcIndices[var1]);
var2.playerCycle = Client.cycle;
class65.scene.method285(SoundSystem.plane, var2.x, var2.y, class32.getTileHeight(var2.size * 64 - 64 + var2.x, var2.size * 64 - 64 + var2.y, SoundSystem.plane), var2.size * 64 - 64 + 60, var2, var2.field9, var5, var2.field10);
}

View File

@@ -2156,7 +2156,7 @@ public final class Client extends GameShell implements Usernamed {
for (var21 = 0; var21 < 104; ++var21) {
for (var56 = 0; var56 < 104; ++var56) {
TilePaint.method3061(var21, var56);
TilePaint.updateItemPile(var21, var56);
}
}
@@ -5311,7 +5311,7 @@ public final class Client extends GameShell implements Usernamed {
for (var6 = Canvas.field95; var6 < Canvas.field95 + 8; ++var6) {
if (groundItems[SoundSystem.plane][var37][var6] != null) {
groundItems[SoundSystem.plane][var37][var6] = null;
TilePaint.method3061(var37, var6);
TilePaint.updateItemPile(var37, var6);
}
}
}

View File

@@ -54,10 +54,11 @@ public class FontName {
signature = "(IIIZII)J",
garbageValue = "1039369805"
)
public static long method5637(int var0, int var1, int var2, boolean var3, int var4) {
long var5 = (long)((var0 & 127) << 0 | (var1 & 127) << 7 | (var2 & 3) << 14) | ((long)var4 & 4294967295L) << 17;
if (var3) {
var5 |= 65536L;
@Export("calculateTag")
public static long calculateTag(int x, int y, int type, boolean isNotInteractable, int identifier) {
long var5 = (long)((x & 0b1111111) << 0 | (y & 0b1111111) << 7 | (type & 0b11) << 14) | ((long)identifier & 0xffffffffL) << 17;
if (isNotInteractable) {
var5 |= 0x10000L;
}
return var5;

View File

@@ -1123,7 +1123,7 @@ public class Model extends Entity {
int var17;
if (!var1 || var10 != -5000 && var11 != -5000 && var12 != -5000) {
if (var2 && NPCDefinition.method5164(modelViewportYs[var8], modelViewportYs[var16], modelViewportYs[var9], var10, var11, var12, var6)) {
Projectile.method2081(var4);
Projectile.addEntityTagAtMouse(var4);
var2 = false;
}
@@ -1609,7 +1609,7 @@ public class Model extends Entity {
if (var35) {
if (this.isSingleTile) {
Projectile.method2081(var9);
Projectile.addEntityTagAtMouse(var9);
} else {
var31 = true;
}

View File

@@ -207,7 +207,7 @@ public class ParamKeyDefinition extends DualNode {
int var23 = var22[var18][var21] + var22[var19][var20] + var22[var18][var20] + var22[var19][var21] >> 2;
int var24 = (var2 << 7) + (var39 << 6);
int var25 = (var3 << 7) + (var17 << 6);
long var26 = FontName.method5637(var2, var3, 2, var38.int1 == 0, var4);
long var26 = FontName.calculateTag(var2, var3, 2, var38.int1 == 0, var4);
int var28 = (var5 << 6) + var6;
if (var38.int3 == 1) {
var28 += 256;

View File

@@ -268,7 +268,8 @@ public final class Projectile extends Entity {
}
@ObfuscatedName("g")
static final void method2081(long var0) {
@Export("addEntityTagAtMouse")
static final void addEntityTagAtMouse(long var0) {
ViewportMouse.ViewportMouse_entityTags[++ViewportMouse.ViewportMouse_entityCount - 1] = var0;
}

View File

@@ -68,13 +68,14 @@ public final class TilePaint {
signature = "(IIB)V",
garbageValue = "0"
)
static final void method3061(int var0, int var1) {
@Export("updateItemPile")
static final void updateItemPile(int var0, int var1) {
NodeDeque var2 = Client.groundItems[SoundSystem.plane][var0][var1];
if (var2 == null) {
class65.scene.removeGroundItemPile(SoundSystem.plane, var0, var1);
} else {
long var3 = -99999999L;
GroundItem var5 = null;
long highestValue = -99999999L;
GroundItem highestValuedItem = null;
GroundItem var6;
for (var6 = (GroundItem)var2.last(); var6 != null; var6 = (GroundItem)var2.previous()) {
@@ -84,21 +85,21 @@ public final class TilePaint {
var8 *= (long)(var6.quantity + 1);
}
if (var8 > var3) {
var3 = var8;
var5 = var6;
if (var8 > highestValue) {
highestValue = var8;
highestValuedItem = var6;
}
}
if (var5 == null) {
if (highestValuedItem == null) {
class65.scene.removeGroundItemPile(SoundSystem.plane, var0, var1);
} else {
var2.addLast(var5);
var2.addLast(highestValuedItem);
GroundItem var11 = null;
GroundItem var12 = null;
for (var6 = (GroundItem)var2.last(); var6 != null; var6 = (GroundItem)var2.previous()) {
if (var5.id != var6.id) {
if (highestValuedItem.id != var6.id) {
if (var11 == null) {
var11 = var6;
}
@@ -109,8 +110,8 @@ public final class TilePaint {
}
}
long var9 = FontName.method5637(var0, var1, 3, false, 0);
class65.scene.newGroundItemPile(SoundSystem.plane, var0, var1, class32.getTileHeight(var0 * 128 + 64, var1 * 128 + 64, SoundSystem.plane), var5, var9, var11, var12);
long var9 = FontName.calculateTag(var0, var1, 3, false, 0);
class65.scene.newGroundItemPile(SoundSystem.plane, var0, var1, class32.getTileHeight(var0 * 128 + 64, var1 * 128 + 64, SoundSystem.plane), highestValuedItem, var9, var11, var12);
}
}

View File

@@ -36,7 +36,8 @@ public class TriBool {
signature = "(I)V",
garbageValue = "-1009406649"
)
static void method5560() {
@Export("addTargetPlayerToScene")
static void addTargetPlayerToScene() {
if (Client.combatTargetPlayerIndex >= 0 && Client.players[Client.combatTargetPlayerIndex] != null) {
WorldMapCacheName.addPlayerToScene(Client.players[Client.combatTargetPlayerIndex], false);
}

View File

@@ -154,7 +154,7 @@ public class WorldMapCacheName {
int var2 = var0.x >> 7;
int var3 = var0.y >> 7;
if (var2 >= 0 && var2 < 104 && var3 >= 0 && var3 < 104) {
long var4 = FontName.method5637(0, 0, 0, false, var0.index);
long var4 = FontName.calculateTag(0, 0, 0, false, var0.index);
if (var0.model0 != null && Client.cycle >= var0.animationCycleStart && Client.cycle < var0.animationCycleEnd) {
var0.isUnanimated = false;
var0.tileHeight = class32.getTileHeight(var0.x, var0.y, SoundSystem.plane);

View File

@@ -78,18 +78,18 @@ public class WorldMapEvent {
return;
}
long var10 = ViewportMouse.ViewportMouse_entityTags[var8];
if (var6 != var10) {
long tag = ViewportMouse.ViewportMouse_entityTags[var8];
if (var6 != tag) {
label276: {
var6 = var10;
int var12 = method780(var8);
var6 = tag;
int x = method780(var8);
long var13 = ViewportMouse.ViewportMouse_entityTags[var8];
int var15 = (int)(var13 >>> 7 & 127L);
var15 = var15;
int y = (int)(var13 >>> 7 & 127L);
y = y;
int var16 = GrandExchangeEvent.method80(var8);
int var17 = ClientPreferences.method1808(var8);
if (var16 == 2 && class65.scene.getObjectFlags(SoundSystem.plane, var12, var15, var10) >= 0) {
ObjectDefinition var18 = class50.getObjectDefinition(var17);
int identifier = ClientPreferences.method1808(var8);
if (var16 == 2 && class65.scene.getObjectFlags(SoundSystem.plane, x, y, tag) >= 0) {
ObjectDefinition var18 = class50.getObjectDefinition(identifier);
if (var18.transforms != null) {
var18 = var18.transform();
}
@@ -99,10 +99,10 @@ public class WorldMapEvent {
}
if (Client.isItemSelected == 1) {
Tiles.insertMenuItemNoShift("Use", Client.selectedItemName + " -> " + BufferedFile.colorStartTag(65535) + var18.name, 1, var17, var12, var15);
Tiles.insertMenuItemNoShift("Use", Client.selectedItemName + " -> " + BufferedFile.colorStartTag(65535) + var18.name, 1, identifier, x, y);
} else if (Client.isSpellSelected) {
if ((FloorDecoration.selectedSpellFlags & 4) == 4) {
Tiles.insertMenuItemNoShift(Client.selectedSpellActionName, Client.selectedSpellName + " -> " + BufferedFile.colorStartTag(65535) + var18.name, 2, var17, var12, var15);
Tiles.insertMenuItemNoShift(Client.selectedSpellActionName, Client.selectedSpellName + " -> " + BufferedFile.colorStartTag(65535) + var18.name, 2, identifier, x, y);
}
} else {
String[] var19 = var18.actions;
@@ -130,12 +130,12 @@ public class WorldMapEvent {
var21 = 1001;
}
Tiles.insertMenuItemNoShift(var19[var20], BufferedFile.colorStartTag(65535) + var18.name, var21, var17, var12, var15);
Tiles.insertMenuItemNoShift(var19[var20], BufferedFile.colorStartTag(65535) + var18.name, var21, identifier, x, y);
}
}
}
Tiles.insertMenuItemNoShift("Examine", BufferedFile.colorStartTag(65535) + var18.name, 1002, var18.id, var12, var15);
Tiles.insertMenuItemNoShift("Examine", BufferedFile.colorStartTag(65535) + var18.name, 1002, var18.id, x, y);
}
}
@@ -145,7 +145,7 @@ public class WorldMapEvent {
Player var32;
int[] var34;
if (var16 == 1) {
NPC var23 = Client.npcs[var17];
NPC var23 = Client.npcs[identifier];
if (var23 == null) {
break label276;
}
@@ -154,7 +154,7 @@ public class WorldMapEvent {
for (var30 = 0; var30 < Client.npcCount; ++var30) {
var31 = Client.npcs[Client.npcIndices[var30]];
if (var31 != null && var23 != var31 && var31.definition.size == 1 && var31.x == var23.x && var31.y == var23.y) {
Tile.addNpcToMenu(var31.definition, Client.npcIndices[var30], var12, var15);
Tile.addNpcToMenu(var31.definition, Client.npcIndices[var30], x, y);
}
}
@@ -164,16 +164,16 @@ public class WorldMapEvent {
for (var22 = 0; var22 < var30; ++var22) {
var32 = Client.players[var34[var22]];
if (var32 != null && var32.x == var23.x && var32.y == var23.y) {
TotalQuantityComparator.addPlayerToMenu(var32, var34[var22], var12, var15);
TotalQuantityComparator.addPlayerToMenu(var32, var34[var22], x, y);
}
}
}
Tile.addNpcToMenu(var23.definition, var17, var12, var15);
Tile.addNpcToMenu(var23.definition, identifier, x, y);
}
if (var16 == 0) {
Player var33 = Client.players[var17];
Player var33 = Client.players[identifier];
if (var33 == null) {
break label276;
}
@@ -182,7 +182,7 @@ public class WorldMapEvent {
for (var30 = 0; var30 < Client.npcCount; ++var30) {
var31 = Client.npcs[Client.npcIndices[var30]];
if (var31 != null && var31.definition.size == 1 && var33.x == var31.x && var33.y == var31.y) {
Tile.addNpcToMenu(var31.definition, Client.npcIndices[var30], var12, var15);
Tile.addNpcToMenu(var31.definition, Client.npcIndices[var30], x, y);
}
}
@@ -192,28 +192,28 @@ public class WorldMapEvent {
for (var22 = 0; var22 < var30; ++var22) {
var32 = Client.players[var34[var22]];
if (var32 != null && var32 != var33 && var32.x == var33.x && var32.y == var33.y) {
TotalQuantityComparator.addPlayerToMenu(var32, var34[var22], var12, var15);
TotalQuantityComparator.addPlayerToMenu(var32, var34[var22], x, y);
}
}
}
if (var17 != Client.combatTargetPlayerIndex) {
TotalQuantityComparator.addPlayerToMenu(var33, var17, var12, var15);
if (identifier != Client.combatTargetPlayerIndex) {
TotalQuantityComparator.addPlayerToMenu(var33, identifier, x, y);
} else {
var4 = var10;
var4 = tag;
}
}
if (var16 == 3) {
NodeDeque var35 = Client.groundItems[SoundSystem.plane][var12][var15];
NodeDeque var35 = Client.groundItems[SoundSystem.plane][x][y];
if (var35 != null) {
for (GroundItem var24 = (GroundItem)var35.first(); var24 != null; var24 = (GroundItem)var35.next()) {
ItemDefinition var25 = Skills.getItemDefinition(var24.id);
if (Client.isItemSelected == 1) {
Tiles.insertMenuItemNoShift("Use", Client.selectedItemName + " -> " + BufferedFile.colorStartTag(16748608) + var25.name, 16, var24.id, var12, var15);
Tiles.insertMenuItemNoShift("Use", Client.selectedItemName + " -> " + BufferedFile.colorStartTag(16748608) + var25.name, 16, var24.id, x, y);
} else if (Client.isSpellSelected) {
if ((FloorDecoration.selectedSpellFlags & 1) == 1) {
Tiles.insertMenuItemNoShift(Client.selectedSpellActionName, Client.selectedSpellName + " -> " + BufferedFile.colorStartTag(16748608) + var25.name, 17, var24.id, var12, var15);
Tiles.insertMenuItemNoShift(Client.selectedSpellActionName, Client.selectedSpellName + " -> " + BufferedFile.colorStartTag(16748608) + var25.name, 17, var24.id, x, y);
}
} else {
String[] var26 = var25.groundActions;
@@ -241,13 +241,13 @@ public class WorldMapEvent {
var28 = 22;
}
Tiles.insertMenuItemNoShift(var26[var27], BufferedFile.colorStartTag(16748608) + var25.name, var28, var24.id, var12, var15);
Tiles.insertMenuItemNoShift(var26[var27], BufferedFile.colorStartTag(16748608) + var25.name, var28, var24.id, x, y);
} else if (var27 == 2) {
Tiles.insertMenuItemNoShift("Take", BufferedFile.colorStartTag(16748608) + var25.name, 20, var24.id, var12, var15);
Tiles.insertMenuItemNoShift("Take", BufferedFile.colorStartTag(16748608) + var25.name, 20, var24.id, x, y);
}
}
Tiles.insertMenuItemNoShift("Examine", BufferedFile.colorStartTag(16748608) + var25.name, 1004, var24.id, var12, var15);
Tiles.insertMenuItemNoShift("Examine", BufferedFile.colorStartTag(16748608) + var25.name, 1004, var24.id, x, y);
}
}
}

View File

@@ -694,13 +694,13 @@ public class WorldMapRegion {
boolean var10 = var9 >= class231.field2805.field2820 && var9 <= class231.field2804.field2820 || var9 == class231.field2806.field2820;
if (var10) {
ObjectDefinition var11 = class50.getObjectDefinition(var8.field199);
int var12 = var11.int1 != 0 ? -3407872 : -3355444;
int var12 = var11.int1 != 0 ? 0xffcc0000 : 0xffcccccc;
if (var8.field198 == class231.field2805.field2820) {
this.method422(var1, var2, var8.field202, var12);
}
if (var8.field198 == class231.field2813.field2820) {
this.method422(var1, var2, var8.field202, -3355444);
this.method422(var1, var2, var8.field202, 0xffcccccc);
this.method422(var1, var2, var8.field202 + 1, var12);
}

View File

@@ -314,7 +314,7 @@ public class class16 {
Client.groundItems[SoundSystem.plane][var2][var32] = null;
}
TilePaint.method3061(var2, var32);
TilePaint.updateItemPile(var2, var32);
}
}
} else if (class190.field2350 == var0) {
@@ -369,7 +369,7 @@ public class class16 {
}
Client.groundItems[SoundSystem.plane][var3][var4].addFirst(var41);
TilePaint.method3061(var3, var4);
TilePaint.updateItemPile(var3, var4);
}
}
} else {
@@ -389,7 +389,7 @@ public class class16 {
}
}
TilePaint.method3061(var4, var5);
TilePaint.updateItemPile(var4, var5);
}
}
}

View File

@@ -52,7 +52,7 @@ public class class227 {
int var16 = var15[var12][var14] + var15[var11][var14] + var15[var11][var13] + var15[var12][var13] >> 2;
int var17 = (var1 << 7) + (var9 << 6);
int var18 = (var2 << 7) + (var10 << 6);
long var19 = FontName.method5637(var1, var2, 2, var8.int1 == 0, var3);
long var19 = FontName.calculateTag(var1, var2, 2, var8.int1 == 0, var3);
int var21 = var5 + (var4 << 6);
if (var8.int3 == 1) {
var21 += 256;

View File

@@ -72,7 +72,8 @@ public class class25 {
signature = "(I)V",
garbageValue = "641029128"
)
static void method349() {
@Export("addLocalPlayerToScene")
static void addLocalPlayerToScene() {
if (Client.renderSelf) {
WorldMapCacheName.addPlayerToScene(Canvas.localPlayer, false);
}

View File

@@ -637,8 +637,8 @@ public class class40 {
static final void drawEntities(int var0, int var1, int var2, int var3) {
++Client.viewportDrawCount;
class229.method4514();
class25.method349();
TriBool.method5560();
class25.addLocalPlayerToScene();
TriBool.addTargetPlayerToScene();
BufferedSource.method3423(true);
int var4 = Players.Players_count;
int[] var5 = Players.Players_indices;