I want to make a contribution, so here:
package com.liverare.better.scripts.farming_aid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.osbot.rs07.api.model.NPC;
import org.osbot.rs07.script.MethodProvider;
public class FishingSpotIdentifier {
/**
* MethodProvided the running script instance is using
*/
private final MethodProvider methodProvider;
/**
* <key = action profile, value = NPC ID>
*/
private final Map<ActionProfile, Integer> fishingSpotIdCache;
public FishingSpotIdentifier(MethodProvider methodProvider) {
this.methodProvider = methodProvider;
this.fishingSpotIdCache = new HashMap<>();
}
/**
* @param actionProfile
* The specific fishing spot to find
* @return List of the requested fishing spot, ordered by distance
*/
public List<NPC> get(ActionProfile actionProfile) {
List<NPC> result = null;
final List<NPC> found = methodProvider.getNpcs().getAll();
Integer cachedId = fishingSpotIdCache.get(actionProfile);
if (cachedId != null) {
result = found.stream().filter(npc -> cachedId.equals(npc.getId())).collect(Collectors.toList());
} else {
result = found.stream().filter(npc -> hasAllActions(npc.getActions(), actionProfile.getActions()))
.collect(Collectors.toList());
fishingSpotIdCache.put(actionProfile, result.iterator().next().getId());
}
if (!result.isEmpty()) {
result.sort((a, b) -> Integer.compare(methodProvider.getMap().distance(a),
methodProvider.getMap().distance(b)));
}
return result;
}
/**
*
* @param actions
* Actions to check against
* @param actionsToFind
* Actions to find (all!)
* @return <tt>Actions array contains all of our requested actions</tt>
*/
private boolean hasAllActions(String[] actions, String... actionsToFind) {
boolean result = true;
for (String actionToFind : actionsToFind) {
if (!contains(actions, actionToFind)) {
result = false;
break;
}
}
return result;
}
/**
*
* @param arr
* Array of strings to search
* @param aString
* String to find within the array
* @return <tt>Requested string is present within the array</tt>
*/
private boolean contains(String[] arr, String aString) {
boolean found = false;
for (String s : arr) {
if (s.equals(aString)) {
found = true;
break;
}
}
return found;
}
/*
* Each record will be used to distinguish each fishing spot.
*/
public static enum ActionProfile {
CAGE_HARPOON("Cage", "Harpoon"),
NET_HARPOON("Net", "Harpoon"),
;
private final String[] actions;
private ActionProfile(String... actions) {
this.actions = actions;
}
public String[] getActions() {
return actions;
}
};
}
It can be used as:
package com.liverare.better.scripts.farming_aid;
import java.util.List;
import org.osbot.rs07.api.model.NPC;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.script.ScriptManifest;
import com.liverare.better.scripts.farming_aid.FishingSpotIdentifier.ActionProfile;
@ScriptManifest(name = "Fishing", info = "Fishes", version = 1.0, author = "LiveRare", logo = "")
public class FishingScript extends Script {
FishingSpotIdentifier fishingSpotIdentifier;
@Override
public void onStart() throws InterruptedException {
fishingSpotIdentifier = new FishingSpotIdentifier(this);
}
@Override
public int onLoop() throws InterruptedException {
List<NPC> fishingSpot = fishingSpotIdentifier.get(ActionProfile.NET_HARPOON);
if (!fishingSpot.isEmpty()) {
fishingSpot.iterator().next().interact("Harpoon");
}
return 500;
}
}
Same fishing spots all have a consistent ID, so if you can discern which spot is for which fish, you can cach the profile and ID of the fishing spot. Then, when you need to re-find a new fishing spot, you won't need to run another action check, since you now have the ID of the fishing spot. This is more efficient, also the FishingSpotIdentifier#ActionProfile enumerator can be expanded to include all fishing spots. In fact, you could add an uninitiated integer field variable in the enumerator and initiate that, instead of dealing with a Map. But...cba. The Map strategy came to me first.