Load NPC stats async
This commit is contained in:
@@ -26,12 +26,12 @@
|
|||||||
package net.runelite.client.game;
|
package net.runelite.client.game;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.stream.JsonReader;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import io.reactivex.Completable;
|
||||||
import java.io.InputStream;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.lang.reflect.Type;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
@@ -41,20 +41,37 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@Singleton
|
@Singleton
|
||||||
public class NPCManager
|
public class NPCManager
|
||||||
{
|
{
|
||||||
private final ImmutableMap<Integer, NPCStats> statsMap;
|
private ImmutableMap<Integer, NPCStats> statsMap;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private NPCManager()
|
private NPCManager()
|
||||||
{
|
{
|
||||||
final Gson gson = new Gson();
|
Completable.fromAction(this::loadStats)
|
||||||
|
.subscribeOn(Schedulers.computation())
|
||||||
|
.subscribe(
|
||||||
|
() -> log.debug("Loaded {} NPC stats", statsMap.size()),
|
||||||
|
ex -> log.warn("Error loading NPC stats", ex)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
final Type typeToken = new TypeToken<Map<Integer, NPCStats>>()
|
private void loadStats() throws IOException
|
||||||
|
{
|
||||||
|
try (JsonReader reader = new JsonReader(new InputStreamReader(NPCManager.class.getResourceAsStream("/npc_stats.json"), StandardCharsets.UTF_8)))
|
||||||
{
|
{
|
||||||
}.getType();
|
ImmutableMap.Builder<Integer, NPCStats> builder = ImmutableMap.builderWithExpectedSize(2821);
|
||||||
|
reader.beginObject();
|
||||||
|
|
||||||
final InputStream statsFile = getClass().getResourceAsStream("/npc_stats.json");
|
while (reader.hasNext())
|
||||||
final Map<Integer, NPCStats> stats = gson.fromJson(new InputStreamReader(statsFile), typeToken);
|
{
|
||||||
statsMap = ImmutableMap.copyOf(stats);
|
builder.put(
|
||||||
|
Integer.parseInt(reader.nextName()),
|
||||||
|
NPCStats.NPC_STATS_TYPE_ADAPTER.read(reader)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject();
|
||||||
|
statsMap = builder.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,9 +24,15 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.game;
|
package net.runelite.client.game;
|
||||||
|
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
|
@Builder(builderClassName = "Builder")
|
||||||
public class NPCStats
|
public class NPCStats
|
||||||
{
|
{
|
||||||
private final String name;
|
private final String name;
|
||||||
@@ -77,4 +83,120 @@ public class NPCStats
|
|||||||
|
|
||||||
return (1 + Math.floor(averageLevel * (averageDefBonus + bonusStrength + bonusAttack) / 5120) / 40);
|
return (1 + Math.floor(averageLevel * (averageDefBonus + bonusStrength + bonusAttack) / 5120) / 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Because this class is here we can't add the TypeAdapter to gson (easily)
|
||||||
|
// doesn't mean we can't use one to do it a bit quicker
|
||||||
|
public static final TypeAdapter<NPCStats> NPC_STATS_TYPE_ADAPTER = new TypeAdapter<NPCStats>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void write(JsonWriter out, NPCStats value)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NPCStats read(JsonReader in) throws IOException
|
||||||
|
{
|
||||||
|
in.beginObject();
|
||||||
|
NPCStats.Builder builder = NPCStats.builder();
|
||||||
|
|
||||||
|
// Name is the only one that's guaranteed
|
||||||
|
in.skipValue();
|
||||||
|
builder.name(in.nextString());
|
||||||
|
|
||||||
|
while (in.hasNext())
|
||||||
|
{
|
||||||
|
switch (in.nextName())
|
||||||
|
{
|
||||||
|
case "hitpoints":
|
||||||
|
builder.hitpoints(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "combatLevel":
|
||||||
|
builder.combatLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "slayerLevel":
|
||||||
|
builder.slayerLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "attackSpeed":
|
||||||
|
builder.attackSpeed(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "attackLevel":
|
||||||
|
builder.attackLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "strengthLevel":
|
||||||
|
builder.strengthLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "defenceLevel":
|
||||||
|
builder.defenceLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "rangeLevel":
|
||||||
|
builder.rangeLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "magicLevel":
|
||||||
|
builder.magicLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "stab":
|
||||||
|
builder.stab(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "slash":
|
||||||
|
builder.slash(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "crush":
|
||||||
|
builder.crush(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "range":
|
||||||
|
builder.range(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "magic":
|
||||||
|
builder.magic(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "stabDef":
|
||||||
|
builder.stabDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "slashDef":
|
||||||
|
builder.slashDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "crushDef":
|
||||||
|
builder.crushDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "rangeDef":
|
||||||
|
builder.rangeDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "magicDef":
|
||||||
|
builder.magicDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusAttack":
|
||||||
|
builder.bonusAttack(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusStrength":
|
||||||
|
builder.bonusStrength(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusRangeStrength":
|
||||||
|
builder.bonusRangeStrength(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusMagicDamage":
|
||||||
|
builder.bonusMagicDamage(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "poisonImmune":
|
||||||
|
builder.poisonImmune(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "venomImmune":
|
||||||
|
builder.venomImmune(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "dragon":
|
||||||
|
builder.dragon(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "demon":
|
||||||
|
builder.demon(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "undead":
|
||||||
|
builder.undead(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in.endObject();
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user