Revert "bringup to current runelite-master"

This reverts commit 74da8a883f.
This commit is contained in:
Zeruth
2019-07-02 18:37:05 -04:00
parent 269db34f11
commit e111b3aeae
22 changed files with 434 additions and 1148 deletions

View File

@@ -108,7 +108,7 @@ class Sprite
}
public void drawAtOn(Rasterizer2D graphics, int x, int y)
public void drawAtOn(Rasterizer2D graphics, int x, int y)
{
x += this.offsetX;
y += this.offsetY;

View File

@@ -64,7 +64,7 @@ public class AreaDumper
for (AreaDefinition area : areaManager.getAreas())
{
Files.asCharSink(new File(outDir, area.id + ".json"), Charset.defaultCharset()).write(gson.toJson(area));
Files.asCharSink(new File(outDir, area.id + ".json"), Charset.defaultCharset()).write(gson.toJson(area));
++count;
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.http.service.animation;
import java.util.List;
import java.util.stream.Collectors;
import net.runelite.http.api.animation.AnimationKey;
import net.runelite.http.api.animation.AnimationRequest;
import net.runelite.http.service.util.exception.NotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/animation")
public class AnimationController
{
@Autowired
private AnimationEndpoint animationService;
@RequestMapping(method = POST)
public void submit(@RequestBody AnimationRequest animationRequest)
{
animationService.submit(animationRequest);
}
@GetMapping
public List<AnimationKey> get()
{
return animationService.get().stream()
.map(AnimationController::entryToKey)
.collect(Collectors.toList());
}
@GetMapping("/{npcid}")
public AnimationKey getRegion(@PathVariable int npcid)
{
AnimationEntry animationEntry = animationService.getNPC(npcid);
if (animationEntry == null)
{
throw new NotFoundException();
}
return entryToKey(animationEntry);
}
private static AnimationKey entryToKey(AnimationEntry xe)
{
AnimationKey animationKey = new AnimationKey();
animationKey.setNPCId(xe.getNPCId());
animationKey.setAnimations(new int[]
{
xe.getAnimations()[0],
xe.getAnimations()[1],
xe.getAnimations()[2],
xe.getAnimations()[3],
xe.getAnimations()[4],
xe.getAnimations()[5],
xe.getAnimations()[6],
xe.getAnimations()[7],
xe.getAnimations()[8],
xe.getAnimations()[9],
});
return animationKey;
}
}

View File

@@ -288,7 +288,7 @@ public enum AgilityShortcut
GOBLIN_VILLAGE_WALL(14, "Wall", new WorldPoint(2925, 3523, 0), TIGHTGAP),
CORSAIR_COVE_DUNGEON_PILLAR(15, "Pillar Jump", new WorldPoint(1980, 8996, 0), PILLAR_31809),
EDGEVILLE_DUNGEON_MONKEYBARS(15, "Monkey Bars", null, MONKEYBARS_23566),
TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15
TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15
YANILLE_UNDERWALL_TUNNEL(16, "Underwall Tunnel", new WorldPoint(2574, 3109, 0), HOLE_16520, CASTLE_WALL),
YANILLE_WATCHTOWER_TRELLIS(18, "Trellis", null, TRELLIS_20056),
COAL_TRUCKS_LOG_BALANCE(20, "Log Balance", new WorldPoint(2598, 3475, 0), LOG_BALANCE_23274),

View File

@@ -80,7 +80,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
new CrypticClue("Speak to the bartender of the Blue Moon Inn in Varrock.", "Bartender", new WorldPoint(3226, 3399, 0), "Talk to the bartender in Blue Moon Inn in Varrock."),
new CrypticClue("This aviator is at the peak of his profession.", "Captain Bleemadge", new WorldPoint(2846, 1749, 0), "Captain Bleemadge, the gnome glider pilot, is found at the top of White Wolf Mountain."),
new CrypticClue("Search the crates in the shed just north of East Ardougne.", CRATE_355, new WorldPoint(2617, 3347, 0), "The crates in the shed north of the northern Ardougne bank."),
new CrypticClue("I wouldn't wear this jean on my legs.", "Father Jean", new WorldPoint(1734, 3576, 0), "Talk to father Jean in the Hosidius church"),
new CrypticClue("I wouldn't wear this jean on my legs.", "Father Jean", new WorldPoint(1697, 3574, 0), "Talk to father Jean in the Hosidius church"),
new CrypticClue("Search the crate in the Toad and Chicken pub.", CRATE_354, new WorldPoint(2913, 3536, 0), "The Toad and Chicken pub is located in Burthorpe."),
new CrypticClue("Search chests found in the upstairs of shops in Port Sarim.", CLOSED_CHEST_375, new WorldPoint(3016, 3205, 1), "Search the chest in the upstairs of Wydin's Food Store, on the east wall."),
new CrypticClue("Right on the blessed border, cursed by the evil ones. On the spot inaccessible by both; I will be waiting. The bugs' imminent possession holds the answer.", new WorldPoint(3410, 3324, 0), "B I P. Dig right under the fairy ring."),

View File

@@ -1,6 +1,5 @@
/*
* Copyright (c) 2018, Eadgars Ruse <https://github.com/Eadgars-Ruse>
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,19 +24,21 @@
*/
package net.runelite.client.plugins.cluescrolls.clues;
import com.google.common.collect.Lists;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import lombok.EqualsAndHashCode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.NPC;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
@@ -46,45 +47,35 @@ import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin;
import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET;
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdArea;
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation;
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdSolver;
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdTemperature;
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdTemperatureChange;
import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
@EqualsAndHashCode(callSuper = false, exclude = { "hotColdSolver", "location" })
@Getter
@Slf4j
public class HotColdClue extends ClueScroll implements LocationClueScroll, LocationsClueScroll, TextClueScroll, NpcClueScroll
{
private static final int HOT_COLD_PANEL_WIDTH = 200;
private static final HotColdClue BEGINNER_CLUE = new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Reldo may have a clue.",
"Reldo",
"Speak to Reldo to receive a strange device.");
private static final HotColdClue MASTER_CLUE = new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Jorral may have a clue.",
"Jorral",
"Speak to Jorral to receive a strange device.");
private static final Pattern INITIAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*)");
private static final Pattern STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*), (.*) last time\\.");
private static final Pattern FINAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is visibly shaking.*");
private static final HotColdClue CLUE =
new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Jorral may have a clue.",
"Jorral",
"Speak to Jorral to receive a strange device.");
// list of potential places to dig
private List<HotColdLocation> digLocations = new ArrayList<>();
private final String text;
private final String npc;
private final String solution;
@Nullable
private HotColdSolver hotColdSolver;
private WorldPoint location;
private WorldPoint lastWorldPoint;
public static HotColdClue forText(String text)
{
if (BEGINNER_CLUE.text.equalsIgnoreCase(text))
if (CLUE.text.equalsIgnoreCase(text))
{
BEGINNER_CLUE.reset();
return BEGINNER_CLUE;
}
else if (MASTER_CLUE.text.equalsIgnoreCase(text))
{
MASTER_CLUE.reset();
return MASTER_CLUE;
return CLUE;
}
return null;
@@ -96,35 +87,24 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
this.npc = npc;
this.solution = solution;
setRequiresSpade(true);
initializeSolver();
}
@Override
public WorldPoint[] getLocations()
{
if (hotColdSolver == null)
{
return new WorldPoint[0];
}
return hotColdSolver.getPossibleLocations().stream().map(HotColdLocation::getWorldPoint).toArray(WorldPoint[]::new);
return Lists.transform(digLocations, HotColdLocation::getWorldPoint).toArray(new WorldPoint[0]);
}
@Override
public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin)
{
if (hotColdSolver == null)
{
return;
}
panelComponent.getChildren().add(TitleComponent.builder()
.text("Hot/Cold Clue")
.build());
panelComponent.setPreferredSize(new Dimension(HOT_COLD_PANEL_WIDTH, 0));
panelComponent.setPreferredSize(new Dimension(200, 0));
// strange device has not been tested yet, show how to get it
if (hotColdSolver.getLastWorldPoint() == null && location == null)
if (lastWorldPoint == null && location == null)
{
if (getNpc() != null)
{
@@ -151,9 +131,7 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
panelComponent.getChildren().add(LineComponent.builder()
.left("Possible areas:")
.build());
final Map<HotColdArea, Integer> locationCounts = new EnumMap<>(HotColdArea.class);
final Collection<HotColdLocation> digLocations = hotColdSolver.getPossibleLocations();
Map<HotColdArea, Integer> locationCounts = new HashMap<>();
for (HotColdLocation hotColdLocation : digLocations)
{
@@ -181,16 +159,17 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
}
else
{
for (HotColdArea area : locationCounts.keySet())
for (HotColdArea s : locationCounts.keySet())
{
panelComponent.getChildren().add(LineComponent.builder()
.left(area.getName() + ':')
.left(s.getName() + ":")
.build());
for (HotColdLocation hotColdLocation : digLocations)
{
if (hotColdLocation.getHotColdArea() == area)
if (hotColdLocation.getHotColdArea() == s)
{
Rectangle2D r = hotColdLocation.getRect();
panelComponent.getChildren().add(LineComponent.builder()
.left("- " + hotColdLocation.getArea())
.leftColor(Color.LIGHT_GRAY)
@@ -205,13 +184,8 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
@Override
public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin)
{
if (hotColdSolver == null)
{
return;
}
// when final location has been found
if (location != null)
if (this.location != null)
{
LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation());
@@ -223,17 +197,20 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
return;
}
// when strange device hasn't been activated yet, show npc who gives you the strange device
if (hotColdSolver.getLastWorldPoint() == null && plugin.getNpcsToMark() != null)
// when strange device hasn't been activated yet, show Jorral
if (lastWorldPoint == null)
{
for (NPC npcToMark : plugin.getNpcsToMark())
// Mark NPC
if (plugin.getNpcsToMark() != null)
{
OverlayUtil.renderActorOverlayImage(graphics, npcToMark, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET);
for (NPC npc : plugin.getNpcsToMark())
{
OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET);
}
}
}
// once the number of possible dig locations is below 10, show the dig spots
final Collection<HotColdLocation> digLocations = hotColdSolver.getPossibleLocations();
if (digLocations.size() < 10)
{
// Mark potential dig locations
@@ -254,87 +231,171 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
public boolean update(final String message, final ClueScrollPlugin plugin)
{
if (hotColdSolver == null)
if (!message.startsWith("The device is"))
{
return false;
}
final Set<HotColdTemperature> temperatureSet;
Matcher m1 = FINAL_STRANGE_DEVICE_MESSAGE.matcher(message);
Matcher m2 = STRANGE_DEVICE_MESSAGE.matcher(message);
Matcher m3 = INITIAL_STRANGE_DEVICE_MESSAGE.matcher(message);
if (this.equals(BEGINNER_CLUE))
// the order that these pattern matchers are checked is important
if (m1.find())
{
temperatureSet = HotColdTemperature.BEGINNER_HOT_COLD_TEMPERATURES;
// final location for hot cold clue has been found
WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
if (localWorld != null)
{
markFinalSpot(localWorld);
return true;
}
}
else if (this.equals(MASTER_CLUE))
else if (m2.find())
{
temperatureSet = HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES;
String temperature = m2.group(1);
String difference = m2.group(2);
WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
if (localWorld != null)
{
updatePossibleArea(localWorld, temperature, difference);
return true;
}
}
else
else if (m3.find())
{
temperatureSet = null;
String temperature = m3.group(1);
WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
if (localWorld != null)
{
updatePossibleArea(localWorld, temperature, "");
return true;
}
}
final HotColdTemperature temperature = HotColdTemperature.getFromTemperatureSet(temperatureSet, message);
if (temperature == null)
{
return false;
}
final WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
if (localWorld == null)
{
return false;
}
if ((this.equals(BEGINNER_CLUE) && temperature == HotColdTemperature.BEGINNER_VISIBLY_SHAKING)
|| (this.equals(MASTER_CLUE) && temperature == HotColdTemperature.MASTER_VISIBLY_SHAKING))
{
markFinalSpot(localWorld);
}
else
{
location = null;
final HotColdTemperatureChange temperatureChange = HotColdTemperatureChange.of(message);
hotColdSolver.signal(localWorld, temperature, temperatureChange);
}
return true;
return false;
}
@Override
public void reset()
{
initializeSolver();
this.lastWorldPoint = null;
digLocations.clear();
}
private void initializeSolver()
private void updatePossibleArea(WorldPoint currentWp, String temperature, String difference)
{
final boolean isBeginner;
this.location = null;
if (this.equals(BEGINNER_CLUE))
if (digLocations.isEmpty())
{
isBeginner = true;
}
else if (this.equals(MASTER_CLUE))
{
isBeginner = false;
digLocations.addAll(Arrays.asList(HotColdLocation.values()));
}
else
int maxSquaresAway = 5000;
int minSquaresAway = 0;
switch (temperature)
{
log.warn("Hot cold solver could not be initialized, clue type is unknown; text: {}, npc: {}, solution: {}",
text, npc, solution);
hotColdSolver = null;
return;
// when the strange device reads a temperature, that means that the center of the final dig location
// is a range of squares away from the player's current location (Chebyshev AKA Chess-board distance)
case "ice cold":
maxSquaresAway = 5000;
minSquaresAway = 500;
break;
case "very cold":
maxSquaresAway = 499;
minSquaresAway = 200;
break;
case "cold":
maxSquaresAway = 199;
minSquaresAway = 150;
break;
case "warm":
maxSquaresAway = 149;
minSquaresAway = 100;
break;
case "hot":
maxSquaresAway = 99;
minSquaresAway = 70;
break;
case "very hot":
maxSquaresAway = 69;
minSquaresAway = 30;
break;
case "incredibly hot":
maxSquaresAway = 29;
minSquaresAway = 5;
break;
}
final Set<HotColdLocation> locations = Arrays.stream(HotColdLocation.values())
.filter(l -> l.isBeginnerClue() == isBeginner)
.collect(Collectors.toSet());
hotColdSolver = new HotColdSolver(locations);
// rectangle r1 encompasses all of the points that are within the max possible distance from the player
Point p1 = new Point(currentWp.getX() - maxSquaresAway, currentWp.getY() - maxSquaresAway);
Rectangle r1 = new Rectangle((int) p1.getX(), (int) p1.getY(), 2 * maxSquaresAway + 1, 2 * maxSquaresAway + 1);
// rectangle r2 encompasses all of the points that are within the min possible distance from the player
Point p2 = new Point(currentWp.getX() - minSquaresAway, currentWp.getY() - minSquaresAway);
Rectangle r2 = new Rectangle((int) p2.getX(), (int) p2.getY(), 2 * minSquaresAway + 1, 2 * minSquaresAway + 1);
// eliminate from consideration dig spots that lie entirely within the min range or entirely outside of the max range
digLocations.removeIf(entry -> r2.contains(entry.getRect()) || !r1.intersects(entry.getRect()));
// if a previous world point has been recorded, we can consider the warmer/colder result from the strange device
if (lastWorldPoint != null)
{
switch (difference)
{
case "but colder than":
// eliminate spots that are absolutely warmer
digLocations.removeIf(entry -> isFirstPointCloserRect(currentWp, lastWorldPoint, entry.getRect()));
break;
case "and warmer than":
// eliminate spots that are absolutely colder
digLocations.removeIf(entry -> isFirstPointCloserRect(lastWorldPoint, currentWp, entry.getRect()));
break;
case "and the same temperature as":
// I couldn't figure out a clean implementation for this case
// not necessary for quickly determining final location
}
}
lastWorldPoint = currentWp;
}
private boolean isFirstPointCloserRect(WorldPoint firstWp, WorldPoint secondWp, Rectangle2D r)
{
WorldPoint p1 = new WorldPoint((int) r.getMaxX(), (int) r.getMaxY(), 0);
if (!isFirstPointCloser(firstWp, secondWp, p1))
{
return false;
}
WorldPoint p2 = new WorldPoint((int) r.getMaxX(), (int) r.getMinY(), 0);
if (!isFirstPointCloser(firstWp, secondWp, p2))
{
return false;
}
WorldPoint p3 = new WorldPoint((int) r.getMinX(), (int) r.getMaxY(), 0);
if (!isFirstPointCloser(firstWp, secondWp, p3))
{
return false;
}
WorldPoint p4 = new WorldPoint((int) r.getMinX(), (int) r.getMinY(), 0);
return (isFirstPointCloser(firstWp, secondWp, p4));
}
private boolean isFirstPointCloser(WorldPoint firstWp, WorldPoint secondWp, WorldPoint wp)
{
int firstDistance = firstWp.distanceTo2D(wp);
int secondDistance = secondWp.distanceTo2D(wp);
return (firstDistance < secondDistance);
}
private void markFinalSpot(WorldPoint wp)
@@ -347,4 +408,4 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
{
return new String[]{npc};
}
}
}

View File

@@ -1,7 +1,6 @@
/*
* Copyright (c) 2018, Eadgars Ruse <https://github.com/Eadgars-Ruse>
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,6 +26,7 @@
package net.runelite.client.plugins.cluescrolls.clues.hotcold;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.runelite.api.coords.WorldPoint;
@@ -69,8 +69,6 @@ public enum HotColdLocation
DESERT_POLLNIVNEACH(new WorldPoint(3287, 2975, 0), DESERT, "West of Pollnivneach."),
DESERT_MTA(new WorldPoint(3350, 3293, 0), DESERT, "Next to Mage Training Arena."),
DESERT_SHANTY(new WorldPoint(3294, 3106, 0), DESERT, "South-west of Shantay Pass."),
DRAYNOR_MANOR_MUSHROOMS(true, new WorldPoint(3096, 3379, 0), MISTHALIN, "Patch of mushrooms just northwest of Draynor Manor"),
DRAYNOR_WHEAT_FIELD(true, new WorldPoint(3120, 3282, 0), MISTHALIN, "Inside the wheat field next to Draynor Village"),
FELDIP_HILLS_JIGGIG(new WorldPoint(2413, 3055, 0), FELDIP_HILLS, "West of Jiggig, east of the fairy ring bkp."),
FELDIP_HILLS_SW(new WorldPoint(2582, 2895, 0), FELDIP_HILLS, "West of the southeasternmost lake in Feldip Hills."),
FELDIP_HILLS_GNOME_GLITER(new WorldPoint(2553, 2972, 0), FELDIP_HILLS, "East of the gnome glider (Lemantolly Undri)."),
@@ -93,7 +91,6 @@ public enum HotColdLocation
FREMENNIK_PROVINCE_ASTRAL_ALTER(new WorldPoint(2147, 3862, 0), FREMENNIK_PROVINCE, "Astral altar"),
FREMENNIK_PROVINCE_LUNAR_VILLAGE(new WorldPoint(2087, 3915, 0), FREMENNIK_PROVINCE, "Lunar Isle, inside the village."),
FREMENNIK_PROVINCE_LUNAR_NORTH(new WorldPoint(2106, 3949, 0), FREMENNIK_PROVINCE, "Lunar Isle, north of the village."),
ICE_MOUNTAIN(true, new WorldPoint(3007, 3475, 0), MISTHALIN, "Atop Ice Mountain"),
KANDARIN_SINCLAR_MANSION(new WorldPoint(2726, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut."),
KANDARIN_CATHERBY(new WorldPoint(2774, 3433, 0), KANDARIN, "Catherby, between the bank and the beehives, near small rock formation."),
KANDARIN_GRAND_TREE(new WorldPoint(2444, 3503, 0), KANDARIN, "Grand Tree, just east of the terrorchick gnome enclosure."),
@@ -118,7 +115,6 @@ public enum HotColdLocation
KARAMJA_KHARAZI_NE(new WorldPoint(2904, 2925, 0), KARAMJA, "North-eastern part of Kharazi Jungle."),
KARAMJA_KHARAZI_SW(new WorldPoint(2783, 2898, 0), KARAMJA, "South-western part of Kharazi Jungle."),
KARAMJA_CRASH_ISLAND(new WorldPoint(2910, 2737, 0), KARAMJA, "Northern part of Crash Island."),
LUMBRIDGE_COW_FIELD(true, new WorldPoint(3174, 3336, 0), MISTHALIN, "Cow field north of Lumbridge"),
MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."),
MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."),
MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."),
@@ -135,7 +131,6 @@ public enum HotColdLocation
MORYTANIA_MOS_LES_HARMLESS_BAR(new WorldPoint(3670, 2974, 0), MORYTANIA, "Near Mos Le'Harmless southern bar."),
MORYTANIA_DRAGONTOOTH_NORTH(new WorldPoint(3813, 3567, 0), MORYTANIA, "Northern part of Dragontooth Island."),
MORYTANIA_DRAGONTOOTH_SOUTH(new WorldPoint(3803, 3532, 0), MORYTANIA, "Southern part of Dragontooth Island."),
NORTHEAST_OF_AL_KHARID_MINE(true, new WorldPoint(3332, 3313, 0), MISTHALIN, "Northeast of Al Kharid Mine"),
WESTERN_PROVINCE_EAGLES_PEAK(new WorldPoint(2297, 3530, 0), WESTERN_PROVINCE, "North-west of Eagles' Peak."),
WESTERN_PROVINCE_PISCATORIS(new WorldPoint(2337, 3689, 0), WESTERN_PROVINCE, "Piscatoris Fishing Colony"),
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2361, 3566, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry."),
@@ -181,20 +176,12 @@ public enum HotColdLocation
ZEAH_DAIRY_COW(new WorldPoint(1320, 3718, 0), ZEAH, "North-east of the Kebos Lowlands, east of the dairy cow."),
ZEAH_CRIMSON_SWIFTS(new WorldPoint(1186, 3583, 0), ZEAH, "South-west of the Kebos Swamp, below the crimson swifts.");
private final boolean beginnerClue;
private final WorldPoint worldPoint;
private final HotColdArea hotColdArea;
private final String area;
HotColdLocation(WorldPoint worldPoint, HotColdArea hotColdArea, String areaDescription)
public Rectangle2D getRect()
{
this(false, worldPoint, hotColdArea, areaDescription);
}
public Rectangle getRect()
{
final int digRadius = beginnerClue ? HotColdTemperature.BEGINNER_VISIBLY_SHAKING.getMaxDistance() :
HotColdTemperature.MASTER_VISIBLY_SHAKING.getMaxDistance();
return new Rectangle(worldPoint.getX() - digRadius, worldPoint.getY() - digRadius, digRadius * 2 + 1, digRadius * 2 + 1);
return new Rectangle(worldPoint.getX() - 4, worldPoint.getY() - 4, 9, 9);
}
}

View File

@@ -1,167 +0,0 @@
/*
* Copyright (c) 2018, Eadgars Ruse <https://github.com/Eadgars-Ruse>
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import com.google.common.annotations.VisibleForTesting;
import java.awt.Rectangle;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import lombok.Getter;
import net.runelite.api.coords.WorldPoint;
/**
* Solution finder for hot-cold style puzzles.
* <p>
* These puzzles are established by having some way to test the distance from the solution via "warmth", where being
* colder means one is farther away from the target, and being warmer means one is closer to it, with the goal being to
* reach the most warm value to discover the solution point. Hot-cold puzzles in Old School Runescape are implemented
* with specific set of solution points, so this solver will filter from a provided set of possible solutions as new
* signals of temperatures and temperature changes are provided.
*/
@Getter
public class HotColdSolver
{
private final Set<HotColdLocation> possibleLocations;
@Nullable
private WorldPoint lastWorldPoint;
public HotColdSolver(Set<HotColdLocation> possibleLocations)
{
this.possibleLocations = possibleLocations;
}
/**
* Process a hot-cold update given a {@link WorldPoint} where a check occurred and the resulting temperature and
* temperature change discovered at that point. This will filter the set of possible locations which can be the
* solution.
*
* @param worldPoint The point where a hot-cold check occurred
* @param temperature The temperature of the checked point
* @param temperatureChange The change of temperature of the checked point compared to the previously-checked point
* @return A set of {@link HotColdLocation}s which are still possible after the filtering occurs. This return value
* is the same as would be returned by {@code getPossibleLocations()}.
*/
public Set<HotColdLocation> signal(@Nonnull final WorldPoint worldPoint, @Nonnull final HotColdTemperature temperature, @Nullable final HotColdTemperatureChange temperatureChange)
{
// when the strange device reads a temperature, that means that the center of the final dig location
// is a range of squares away from the player's current location (Chebyshev AKA Chess-board distance)
int maxSquaresAway = temperature.getMaxDistance();
int minSquaresAway = temperature.getMinDistance();
// maxDistanceArea encompasses all of the points that are within the max possible distance from the player
final Rectangle maxDistanceArea = new Rectangle(
worldPoint.getX() - maxSquaresAway,
worldPoint.getY() - maxSquaresAway,
2 * maxSquaresAway + 1,
2 * maxSquaresAway + 1);
// minDistanceArea encompasses all of the points that are within the min possible distance from the player
final Rectangle minDistanceArea = new Rectangle(
worldPoint.getX() - minSquaresAway,
worldPoint.getY() - minSquaresAway,
2 * minSquaresAway + 1,
2 * minSquaresAway + 1);
// eliminate from consideration dig spots that lie entirely within the min range or entirely outside of the max range
possibleLocations.removeIf(entry -> minDistanceArea.contains(entry.getRect()) || !maxDistanceArea.intersects(entry.getRect()));
// if a previous world point has been recorded, we can consider the warmer/colder result from the strange device
if (lastWorldPoint != null && temperatureChange != null)
{
switch (temperatureChange)
{
case COLDER:
// eliminate spots that are absolutely warmer
possibleLocations.removeIf(entry -> isFirstPointCloserRect(worldPoint, lastWorldPoint, entry.getRect()));
break;
case WARMER:
// eliminate spots that are absolutely colder
possibleLocations.removeIf(entry -> isFirstPointCloserRect(lastWorldPoint, worldPoint, entry.getRect()));
break;
case SAME:
// I couldn't figure out a clean implementation for this case
// not necessary for quickly determining final location
}
}
lastWorldPoint = worldPoint;
return getPossibleLocations();
}
/**
* Determines whether the first point passed is closer to each corner of the given rectangle than the second point.
*
* @param firstPoint First point to test. Return result will be relating to this point's location.
* @param secondPoint Second point to test
* @param rect Rectangle, whose corner points will be compared to the first and second points passed
* @return {@code true} if {@code firstPoint} is closer to each of {@code rect}'s four corner points than
* {@code secondPoint}, {@code false} otherwise.
* @see WorldPoint#distanceTo2D
*/
@VisibleForTesting
static boolean isFirstPointCloserRect(final WorldPoint firstPoint, final WorldPoint secondPoint, final Rectangle rect)
{
final WorldPoint nePoint = new WorldPoint((rect.x + rect.width), (rect.y + rect.height), 0);
if (!isFirstPointCloser(firstPoint, secondPoint, nePoint))
{
return false;
}
final WorldPoint sePoint = new WorldPoint((rect.x + rect.width), rect.y, 0);
if (!isFirstPointCloser(firstPoint, secondPoint, sePoint))
{
return false;
}
final WorldPoint nwPoint = new WorldPoint(rect.x, (rect.y + rect.height), 0);
if (!isFirstPointCloser(firstPoint, secondPoint, nwPoint))
{
return false;
}
final WorldPoint swPoint = new WorldPoint(rect.x, rect.y, 0);
return (isFirstPointCloser(firstPoint, secondPoint, swPoint));
}
/**
* Determines whether the first point passed is closer to the given point of comparison than the second point.
*
* @param firstPoint First point to test. Return result will be relating to this point's location.
* @param secondPoint Second point to test
* @param worldPoint Point to compare to the first and second points passed
* @return {@code true} if {@code firstPoint} is closer to {@code worldPoint} than {@code secondPoint},
* {@code false} otherwise.
* @see WorldPoint#distanceTo2D
*/
@VisibleForTesting
static boolean isFirstPointCloser(final WorldPoint firstPoint, final WorldPoint secondPoint, final WorldPoint worldPoint)
{
return firstPoint.distanceTo2D(worldPoint) < secondPoint.distanceTo2D(worldPoint);
}
}

View File

@@ -1,112 +0,0 @@
/*
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum HotColdTemperature
{
ICE_COLD("ice cold", 500, 5000),
VERY_COLD("very cold", 200, 499),
COLD("cold", 150, 199),
WARM("warm", 100, 149),
HOT("hot", 70, 99),
VERY_HOT("very hot", 30, 69),
BEGINNER_INCREDIBLY_HOT("incredibly hot", 4, 29),
BEGINNER_VISIBLY_SHAKING("visibly shaking", 0, 3),
MASTER_INCREDIBLY_HOT("incredibly hot", 5, 29),
MASTER_VISIBLY_SHAKING("visibly shaking", 0, 4);
public static final Set<HotColdTemperature> BEGINNER_HOT_COLD_TEMPERATURES = Sets.immutableEnumSet(
ICE_COLD,
VERY_COLD,
COLD,
WARM,
HOT,
VERY_HOT,
BEGINNER_INCREDIBLY_HOT,
BEGINNER_VISIBLY_SHAKING
);
public static final Set<HotColdTemperature> MASTER_HOT_COLD_TEMPERATURES = Sets.immutableEnumSet(
ICE_COLD,
VERY_COLD,
COLD,
WARM,
HOT,
VERY_HOT,
MASTER_INCREDIBLY_HOT,
MASTER_VISIBLY_SHAKING
);
private final String text;
private final int minDistance;
private final int maxDistance;
private static final String DEVICE_USED_START_TEXT = "The device is ";
/**
* Gets the temperature from a set of temperatures corresponding to the passed string.
*
* @param temperatureSet A set of temperature values to select from
* @param message A string containing a temperature value
* @return The corresponding enum from the given temperature set.
* <p>
* Note that in cases where two temperature values in the given set are equally likely to be the given
* temperature (say, two temperatures with identical text values), the behavior is undefined.
*/
@Nullable
public static HotColdTemperature getFromTemperatureSet(final Set<HotColdTemperature> temperatureSet, final String message)
{
if (!message.startsWith(DEVICE_USED_START_TEXT) || temperatureSet == null)
{
return null;
}
final List<HotColdTemperature> possibleTemperatures = new ArrayList<>();
for (final HotColdTemperature temperature : temperatureSet)
{
if (message.contains(temperature.getText()))
{
possibleTemperatures.add(temperature);
}
}
return possibleTemperatures.stream()
// For messages such as "The device is very cold", this will choose the Enum with text of greatest length so
// that VERY_COLD would be selected over COLD, though both Enums have matching text for this message.
.max(Comparator.comparingInt(x -> (x.getText()).length()))
.orElse(null);
}
}

View File

@@ -1,55 +0,0 @@
/*
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import lombok.AllArgsConstructor;
@AllArgsConstructor
public enum HotColdTemperatureChange
{
WARMER("and warmer than"),
SAME("and the same temperature as"),
COLDER("but colder than");
private final String text;
public static HotColdTemperatureChange of(final String message)
{
if (!message.endsWith(" last time."))
{
return null;
}
for (final HotColdTemperatureChange change : values())
{
if (message.contains(change.text))
{
return change;
}
}
return null;
}
}

View File

@@ -173,10 +173,10 @@ public interface ItemChargeConfig extends Config
}
@ConfigItem(
keyName = "showBellowCharges",
name = "Show Bellow Charges",
description = "Configures if ogre bellow item charge is shown",
position = 12
keyName = "showBellowCharges",
name = "Show Bellow Charges",
description = "Configures if ogre bellow item charge is shown",
position = 12
)
default boolean showBellowCharges()
{
@@ -184,32 +184,10 @@ public interface ItemChargeConfig extends Config
}
@ConfigItem(
keyName = "showBasketCharges",
name = "Show Basket Charges",
description = "Configures if fruit basket item charge is shown",
position = 13
)
default boolean showBasketCharges()
{
return true;
}
@ConfigItem(
keyName = "showSackCharges",
name = "Show Sack Charges",
description = "Configures if sack item charge is shown",
position = 14
)
default boolean showSackCharges()
{
return true;
}
@ConfigItem(
keyName = "showAbyssalBraceletCharges",
name = "Show Abyssal Bracelet Charges",
description = "Configures if abyssal bracelet item charge is shown",
position = 15
keyName = "showAbyssalBraceletCharges",
name = "Show Abyssal Bracelet Charges",
description = "Configures if abyssal bracelet item charge is shown",
position = 13
)
default boolean showAbyssalBraceletCharges()
{
@@ -220,7 +198,7 @@ public interface ItemChargeConfig extends Config
keyName = "recoilNotification",
name = "Ring of Recoil Notification",
description = "Configures if the ring of recoil breaking notification is shown",
position = 16
position = 14
)
default boolean recoilNotification()
{
@@ -231,7 +209,7 @@ public interface ItemChargeConfig extends Config
keyName = "showBindingNecklaceCharges",
name = "Show Binding Necklace Charges",
description = "Configures if binding necklace item charge is shown",
position = 17
position = 15
)
default boolean showBindingNecklaceCharges()
{
@@ -260,7 +238,7 @@ public interface ItemChargeConfig extends Config
keyName = "bindingNotification",
name = "Binding Necklace Notification",
description = "Configures if the binding necklace breaking notification is shown",
position = 18
position = 16
)
default boolean bindingNotification()
{
@@ -271,7 +249,7 @@ public interface ItemChargeConfig extends Config
keyName = "showExplorerRingCharges",
name = "Show Explorer's Ring Alch Charges",
description = "Configures if explorer's ring alchemy charges are shown",
position = 19
position = 17
)
default boolean showExplorerRingCharges()
{
@@ -300,7 +278,7 @@ public interface ItemChargeConfig extends Config
keyName = "showInfoboxes",
name = "Show Infoboxes",
description = "Configures whether to show an infobox equipped charge items",
position = 20
position = 18
)
default boolean showInfoboxes()
{

View File

@@ -38,8 +38,6 @@ import static net.runelite.client.plugins.itemcharges.ItemChargeType.IMPBOX;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.TELEPORT;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERCAN;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERSKIN;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.FRUIT_BASKET;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.SACK;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.WidgetItemOverlay;
import net.runelite.client.ui.overlay.components.TextComponent;
@@ -154,8 +152,6 @@ class ItemChargeOverlay extends WidgetItemOverlay
|| (type == WATERCAN && !config.showWateringCanCharges())
|| (type == WATERSKIN && !config.showWaterskinCharges())
|| (type == BELLOWS && !config.showBellowCharges())
|| (type == FRUIT_BASKET && !config.showBasketCharges())
|| (type == SACK && !config.showSackCharges())
|| (type == ABYSSAL_BRACELET && !config.showAbyssalBraceletCharges()))
{
return;
@@ -176,7 +172,6 @@ class ItemChargeOverlay extends WidgetItemOverlay
{
return config.showTeleportCharges() || config.showDodgyCount() || config.showFungicideCharges()
|| config.showImpCharges() || config.showWateringCanCharges() || config.showWaterskinCharges()
|| config.showBellowCharges() || config.showBasketCharges() || config.showSackCharges()
|| config.showAbyssalBraceletCharges() || config.showExplorerRingCharges();
|| config.showBellowCharges() || config.showAbyssalBraceletCharges() || config.showExplorerRingCharges();
}
}

View File

@@ -37,7 +37,5 @@ enum ItemChargeType
BRACELET_OF_SLAUGHTER,
EXPEDITIOUS_BRACELET,
BINDING_NECKLACE,
EXPLORER_RING,
FRUIT_BASKET,
SACK
EXPLORER_RING
}

View File

@@ -29,8 +29,133 @@ import java.util.Map;
import javax.annotation.Nullable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import static net.runelite.api.ItemID.*;
import static net.runelite.api.ItemID.ABYSSAL_BRACELET1;
import static net.runelite.api.ItemID.ABYSSAL_BRACELET2;
import static net.runelite.api.ItemID.ABYSSAL_BRACELET3;
import static net.runelite.api.ItemID.ABYSSAL_BRACELET4;
import static net.runelite.api.ItemID.ABYSSAL_BRACELET5;
import static net.runelite.api.ItemID.AMULET_OF_GLORY1;
import static net.runelite.api.ItemID.AMULET_OF_GLORY2;
import static net.runelite.api.ItemID.AMULET_OF_GLORY3;
import static net.runelite.api.ItemID.AMULET_OF_GLORY4;
import static net.runelite.api.ItemID.AMULET_OF_GLORY5;
import static net.runelite.api.ItemID.AMULET_OF_GLORY6;
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T1;
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T2;
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T3;
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T4;
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T5;
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T6;
import static net.runelite.api.ItemID.BURNING_AMULET1;
import static net.runelite.api.ItemID.BURNING_AMULET2;
import static net.runelite.api.ItemID.BURNING_AMULET3;
import static net.runelite.api.ItemID.BURNING_AMULET4;
import static net.runelite.api.ItemID.BURNING_AMULET5;
import static net.runelite.api.ItemID.COMBAT_BRACELET1;
import static net.runelite.api.ItemID.COMBAT_BRACELET2;
import static net.runelite.api.ItemID.COMBAT_BRACELET3;
import static net.runelite.api.ItemID.COMBAT_BRACELET4;
import static net.runelite.api.ItemID.COMBAT_BRACELET5;
import static net.runelite.api.ItemID.COMBAT_BRACELET6;
import static net.runelite.api.ItemID.DIGSITE_PENDANT_1;
import static net.runelite.api.ItemID.DIGSITE_PENDANT_2;
import static net.runelite.api.ItemID.DIGSITE_PENDANT_3;
import static net.runelite.api.ItemID.DIGSITE_PENDANT_4;
import static net.runelite.api.ItemID.DIGSITE_PENDANT_5;
import static net.runelite.api.ItemID.ENCHANTED_LYRE1;
import static net.runelite.api.ItemID.ENCHANTED_LYRE2;
import static net.runelite.api.ItemID.ENCHANTED_LYRE3;
import static net.runelite.api.ItemID.ENCHANTED_LYRE4;
import static net.runelite.api.ItemID.ENCHANTED_LYRE5;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_0;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_1;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_10;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_2;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_3;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_4;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_5;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_6;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_7;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_8;
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_9;
import static net.runelite.api.ItemID.GAMES_NECKLACE1;
import static net.runelite.api.ItemID.GAMES_NECKLACE2;
import static net.runelite.api.ItemID.GAMES_NECKLACE3;
import static net.runelite.api.ItemID.GAMES_NECKLACE4;
import static net.runelite.api.ItemID.GAMES_NECKLACE5;
import static net.runelite.api.ItemID.GAMES_NECKLACE6;
import static net.runelite.api.ItemID.GAMES_NECKLACE7;
import static net.runelite.api.ItemID.GAMES_NECKLACE8;
import static net.runelite.api.ItemID.IMPINABOX1;
import static net.runelite.api.ItemID.IMPINABOX2;
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE1;
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE2;
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE3;
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE4;
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE5;
import static net.runelite.api.ItemID.OGRE_BELLOWS;
import static net.runelite.api.ItemID.OGRE_BELLOWS_1;
import static net.runelite.api.ItemID.OGRE_BELLOWS_2;
import static net.runelite.api.ItemID.OGRE_BELLOWS_3;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_1;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_2;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_3;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_4;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_5;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_6;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_7;
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_8;
import static net.runelite.api.ItemID.RING_OF_DUELING1;
import static net.runelite.api.ItemID.RING_OF_DUELING2;
import static net.runelite.api.ItemID.RING_OF_DUELING3;
import static net.runelite.api.ItemID.RING_OF_DUELING4;
import static net.runelite.api.ItemID.RING_OF_DUELING5;
import static net.runelite.api.ItemID.RING_OF_DUELING6;
import static net.runelite.api.ItemID.RING_OF_DUELING7;
import static net.runelite.api.ItemID.RING_OF_DUELING8;
import static net.runelite.api.ItemID.RING_OF_RETURNING1;
import static net.runelite.api.ItemID.RING_OF_RETURNING2;
import static net.runelite.api.ItemID.RING_OF_RETURNING3;
import static net.runelite.api.ItemID.RING_OF_RETURNING4;
import static net.runelite.api.ItemID.RING_OF_RETURNING5;
import static net.runelite.api.ItemID.RING_OF_WEALTH_1;
import static net.runelite.api.ItemID.RING_OF_WEALTH_2;
import static net.runelite.api.ItemID.RING_OF_WEALTH_3;
import static net.runelite.api.ItemID.RING_OF_WEALTH_4;
import static net.runelite.api.ItemID.RING_OF_WEALTH_5;
import static net.runelite.api.ItemID.SKILLS_NECKLACE1;
import static net.runelite.api.ItemID.SKILLS_NECKLACE2;
import static net.runelite.api.ItemID.SKILLS_NECKLACE3;
import static net.runelite.api.ItemID.SKILLS_NECKLACE4;
import static net.runelite.api.ItemID.SKILLS_NECKLACE5;
import static net.runelite.api.ItemID.SKILLS_NECKLACE6;
import static net.runelite.api.ItemID.SLAYER_RING_1;
import static net.runelite.api.ItemID.SLAYER_RING_2;
import static net.runelite.api.ItemID.SLAYER_RING_3;
import static net.runelite.api.ItemID.SLAYER_RING_4;
import static net.runelite.api.ItemID.SLAYER_RING_5;
import static net.runelite.api.ItemID.SLAYER_RING_6;
import static net.runelite.api.ItemID.SLAYER_RING_7;
import static net.runelite.api.ItemID.SLAYER_RING_8;
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_1;
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_2;
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_3;
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_4;
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_5;
import static net.runelite.api.ItemID.WATERING_CAN;
import static net.runelite.api.ItemID.WATERING_CAN1;
import static net.runelite.api.ItemID.WATERING_CAN2;
import static net.runelite.api.ItemID.WATERING_CAN3;
import static net.runelite.api.ItemID.WATERING_CAN4;
import static net.runelite.api.ItemID.WATERING_CAN5;
import static net.runelite.api.ItemID.WATERING_CAN6;
import static net.runelite.api.ItemID.WATERING_CAN7;
import static net.runelite.api.ItemID.WATERING_CAN8;
import static net.runelite.api.ItemID.WATERSKIN0;
import static net.runelite.api.ItemID.WATERSKIN1;
import static net.runelite.api.ItemID.WATERSKIN2;
import static net.runelite.api.ItemID.WATERSKIN3;
import static net.runelite.api.ItemID.WATERSKIN4;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.ABYSSAL_BRACELET;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.BELLOWS;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.FUNGICIDE_SPRAY;
@@ -38,8 +163,6 @@ import static net.runelite.client.plugins.itemcharges.ItemChargeType.IMPBOX;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.TELEPORT;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERCAN;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERSKIN;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.FRUIT_BASKET;
import static net.runelite.client.plugins.itemcharges.ItemChargeType.SACK;
@AllArgsConstructor
@Getter
@@ -50,31 +173,6 @@ enum ItemWithCharge
ABRACE3(ABYSSAL_BRACELET, ABYSSAL_BRACELET3, 3),
ABRACE4(ABYSSAL_BRACELET, ABYSSAL_BRACELET4, 4),
ABRACE5(ABYSSAL_BRACELET, ABYSSAL_BRACELET5, 5),
BASKET_APPLES1(FRUIT_BASKET, APPLES1, 1),
BASKET_APPLES2(FRUIT_BASKET, APPLES2, 2),
BASKET_APPLES3(FRUIT_BASKET, APPLES3, 3),
BASKET_APPLES4(FRUIT_BASKET, APPLES4, 4),
BASKET_APPLES5(FRUIT_BASKET, APPLES5, 5),
BASKET_BANANAS1(FRUIT_BASKET, BANANAS1, 1),
BASKET_BANANAS2(FRUIT_BASKET, BANANAS2, 2),
BASKET_BANANAS3(FRUIT_BASKET, BANANAS3, 3),
BASKET_BANANAS4(FRUIT_BASKET, BANANAS4, 4),
BASKET_BANANAS5(FRUIT_BASKET, BANANAS5, 5),
BASKET_ORANGES1(FRUIT_BASKET, ORANGES1, 1),
BASKET_ORANGES2(FRUIT_BASKET, ORANGES2, 2),
BASKET_ORANGES3(FRUIT_BASKET, ORANGES3, 3),
BASKET_ORANGES4(FRUIT_BASKET, ORANGES4, 4),
BASKET_ORANGES5(FRUIT_BASKET, ORANGES5, 5),
BASKET_STRAWBERRIES1(FRUIT_BASKET, STRAWBERRIES1, 1),
BASKET_STRAWBERRIES2(FRUIT_BASKET, STRAWBERRIES2, 2),
BASKET_STRAWBERRIES3(FRUIT_BASKET, STRAWBERRIES3, 3),
BASKET_STRAWBERRIES4(FRUIT_BASKET, STRAWBERRIES4, 4),
BASKET_STRAWBERRIES5(FRUIT_BASKET, STRAWBERRIES5, 5),
BASKET_TOMATOES1(FRUIT_BASKET, TOMATOES1, 1),
BASKET_TOMATOES2(FRUIT_BASKET, TOMATOES2, 2),
BASKET_TOMATOES3(FRUIT_BASKET, TOMATOES3, 3),
BASKET_TOMATOES4(FRUIT_BASKET, TOMATOES4, 4),
BASKET_TOMATOES5(FRUIT_BASKET, TOMATOES5, 5),
BELLOWS0(BELLOWS, OGRE_BELLOWS, 0),
BELLOWS1(BELLOWS, OGRE_BELLOWS_1, 1),
BELLOWS2(BELLOWS, OGRE_BELLOWS_2, 2),
@@ -172,36 +270,6 @@ enum ItemWithCharge
ROW3(TELEPORT, RING_OF_WEALTH_3, 3),
ROW4(TELEPORT, RING_OF_WEALTH_4, 4),
ROW5(TELEPORT, RING_OF_WEALTH_5, 5),
SACK_CABBAGES1(SACK, CABBAGES1, 1),
SACK_CABBAGES2(SACK, CABBAGES2, 2),
SACK_CABBAGES3(SACK, CABBAGES3, 3),
SACK_CABBAGES4(SACK, CABBAGES4, 4),
SACK_CABBAGES5(SACK, CABBAGES5, 5),
SACK_CABBAGES6(SACK, CABBAGES6, 6),
SACK_CABBAGES7(SACK, CABBAGES7, 7),
SACK_CABBAGES8(SACK, CABBAGES8, 8),
SACK_CABBAGES9(SACK, CABBAGES9, 9),
SACK_CABBAGES10(SACK, CABBAGES10, 10),
SACK_ONIONS1(SACK, ONIONS1, 1),
SACK_ONIONS2(SACK, ONIONS2, 2),
SACK_ONIONS3(SACK, ONIONS3, 3),
SACK_ONIONS4(SACK, ONIONS4, 4),
SACK_ONIONS5(SACK, ONIONS5, 5),
SACK_ONIONS6(SACK, ONIONS6, 6),
SACK_ONIONS7(SACK, ONIONS7, 7),
SACK_ONIONS8(SACK, ONIONS8, 8),
SACK_ONIONS9(SACK, ONIONS9, 9),
SACK_ONIONS10(SACK, ONIONS10, 10),
SACK_POTATOES1(SACK, POTATOES1, 1),
SACK_POTATOES2(SACK, POTATOES2, 2),
SACK_POTATOES3(SACK, POTATOES3, 3),
SACK_POTATOES4(SACK, POTATOES4, 4),
SACK_POTATOES5(SACK, POTATOES5, 5),
SACK_POTATOES6(SACK, POTATOES6, 6),
SACK_POTATOES7(SACK, POTATOES7, 7),
SACK_POTATOES8(SACK, POTATOES8, 8),
SACK_POTATOES9(SACK, POTATOES9, 9),
SACK_POTATOES10(SACK, POTATOES10, 10),
SKILLS1(TELEPORT, SKILLS_NECKLACE1, 1),
SKILLS2(TELEPORT, SKILLS_NECKLACE2, 2),
SKILLS3(TELEPORT, SKILLS_NECKLACE3, 3),

View File

@@ -1690,4 +1690,4 @@ default CharterOption charterOption()
{
return true;
}
}
}

View File

@@ -29,8 +29,6 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
@@ -171,7 +169,12 @@ class ScreenMarkerPanel extends JPanel
@Override
public void mousePressed(MouseEvent mouseEvent)
{
save();
marker.getMarker().setName(nameInput.getText());
plugin.updateConfig();
nameInput.setEditable(false);
updateNameActions(false);
requestFocusInWindow();
}
@Override
@@ -195,7 +198,10 @@ class ScreenMarkerPanel extends JPanel
@Override
public void mousePressed(MouseEvent mouseEvent)
{
cancel();
nameInput.setEditable(false);
nameInput.setText(marker.getMarker().getName());
updateNameActions(false);
requestFocusInWindow();
}
@Override
@@ -246,35 +252,6 @@ class ScreenMarkerPanel extends JPanel
nameInput.setPreferredSize(new Dimension(0, 24));
nameInput.getTextField().setForeground(Color.WHITE);
nameInput.getTextField().setBorder(new EmptyBorder(0, 8, 0, 0));
nameInput.addKeyListener(new KeyAdapter()
{
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
save();
}
else if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
{
cancel();
}
}
});
nameInput.getTextField().addMouseListener(new MouseAdapter()
{
@Override
public void mouseEntered(MouseEvent mouseEvent)
{
preview(true);
}
@Override
public void mouseExited(MouseEvent mouseEvent)
{
preview(false);
}
});
nameWrapper.add(nameInput, BorderLayout.CENTER);
nameWrapper.add(nameActions, BorderLayout.EAST);
@@ -382,7 +359,10 @@ class ScreenMarkerPanel extends JPanel
@Override
public void mousePressed(MouseEvent mouseEvent)
{
toggle(!visible);
visible = !visible;
marker.getMarker().setVisible(visible);
plugin.updateConfig();
updateVisibility();
}
@Override
@@ -444,42 +424,6 @@ class ScreenMarkerPanel extends JPanel
}
private void preview(boolean on)
{
if (visible)
{
return;
}
marker.getMarker().setVisible(on);
}
private void toggle(boolean on)
{
visible = on;
marker.getMarker().setVisible(visible);
plugin.updateConfig();
updateVisibility();
}
private void save()
{
marker.getMarker().setName(nameInput.getText());
plugin.updateConfig();
nameInput.setEditable(false);
updateNameActions(false);
requestFocusInWindow();
}
private void cancel()
{
nameInput.setEditable(false);
nameInput.setText(marker.getMarker().getName());
updateNameActions(false);
requestFocusInWindow();
}
private void updateNameActions(boolean saveAndCancel)
{
save.setVisible(saveAndCancel);

View File

@@ -97,7 +97,7 @@ public class WorldHopperPlugin extends Plugin
{
private static final int WORLD_FETCH_TIMER = 10;
private static final int WORLD_PING_TIMER = 10;
private static final int REFRESH_THROTTLE = 60_000; // ms
private static final int REFRESH_THROTTLE = 60_000; // ms
private static final int TICK_THROTTLE = (int) Duration.ofMinutes(10).toMillis();
private static final int DISPLAY_SWITCHER_MAX_ATTEMPTS = 3;

View File

@@ -1,50 +0,0 @@
/*
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class BeginnerHotColdLocationTest
{
private static final Set<HotColdLocation> BEGINNER_HOT_COLD_LOCATIONS = Arrays.stream(HotColdLocation.values())
.filter(HotColdLocation::isBeginnerClue)
.collect(Collectors.toSet());
private static final int EXPECTED_DIMENSION_SIZE = 7;
@Test
public void beginnerHotColdLocationAreaTest()
{
for (final HotColdLocation location : BEGINNER_HOT_COLD_LOCATIONS)
{
assertEquals(EXPECTED_DIMENSION_SIZE, location.getRect().height);
assertEquals(EXPECTED_DIMENSION_SIZE, location.getRect().width);
}
}
}

View File

@@ -1,259 +0,0 @@
/*
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import com.google.common.collect.Sets;
import java.awt.Rectangle;
import java.util.EnumSet;
import java.util.Set;
import java.util.stream.Collectors;
import static junit.framework.TestCase.assertTrue;
import net.runelite.api.coords.WorldPoint;
import static net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdSolver.isFirstPointCloser;
import static net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdSolver.isFirstPointCloserRect;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
public class HotColdSolverTest
{
private static final String RESPONSE_TEXT_ICE_COLD_COLDER = "The device is ice cold, but colder than last time.";
private static final String RESPONSE_TEXT_VERY_COLD_WARMER = "The device is very cold, and warmer than last time.";
private static final String RESPONSE_TEXT_COLD = "The device is cold.";
private static final String RESPONSE_TEXT_COLD_COLDER = "The device is cold, but colder than last time.";
private static final String RESPONSE_TEXT_COLD_WARMER = "The device is cold, and warmer than last time.";
private static final String RESPONSE_TEXT_COLD_SAME_TEMP = "The device is cold, and the same temperature as last time.";
private static final String RESPONSE_TEXT_VERY_HOT = "The device is very hot.";
private static final String RESPONSE_TEXT_VERY_HOT_COLDER = "The device is very hot, but colder than last time.";
private static final String RESPONSE_TEXT_VERY_HOT_WARMER = "The device is very hot, and warmer than last time.";
private static final String RESPONSE_TEXT_VERY_HOT_SAME_TEMP = "The device is very hot, and the same temperature as last time.";
@Test
public void testOneStepSolution()
{
final Set<HotColdLocation> foundLocation = Sets.immutableEnumSet(HotColdLocation.KARAMJA_KHARAZI_NE);
testSolver(createHotColdSolver(), new WorldPoint(2852, 2992, 0), RESPONSE_TEXT_VERY_HOT, foundLocation);
}
@Test
public void testIgnoreStartingTemperatureDifference()
{
final WorldPoint testedPoint = new WorldPoint(2852, 2992, 0);
final Set<HotColdLocation> foundLocations = Sets.immutableEnumSet(HotColdLocation.KARAMJA_KHARAZI_NE);
testSolver(createHotColdSolver(), testedPoint, RESPONSE_TEXT_VERY_HOT, foundLocations);
testSolver(createHotColdSolver(), testedPoint, RESPONSE_TEXT_VERY_HOT_COLDER, foundLocations);
testSolver(createHotColdSolver(), testedPoint, RESPONSE_TEXT_VERY_HOT_WARMER, foundLocations);
testSolver(createHotColdSolver(), testedPoint, RESPONSE_TEXT_VERY_HOT_SAME_TEMP, foundLocations);
}
@Test
public void testSameTempNoChanges()
{
final HotColdSolver solver = createHotColdSolver();
final WorldPoint testedPoint = new WorldPoint(2851, 2955, 0);
final Set<HotColdLocation> foundLocations = Sets.immutableEnumSet(
HotColdLocation.KARAMJA_KHARAZI_NE,
HotColdLocation.KARAMJA_KHARAZI_SW);
testSolver(solver, testedPoint, RESPONSE_TEXT_VERY_HOT, foundLocations);
testSolver(solver, testedPoint, RESPONSE_TEXT_VERY_HOT_SAME_TEMP, foundLocations);
}
@Test
public void testNoChangesAfterSolutionFound()
{
final HotColdSolver solver = createHotColdSolver();
final Set<HotColdLocation> intermediateFoundLocations = Sets.immutableEnumSet(
HotColdLocation.KARAMJA_KHARAZI_NE,
HotColdLocation.KARAMJA_KHARAZI_SW);
final Set<HotColdLocation> finalLocation = Sets.immutableEnumSet(HotColdLocation.KARAMJA_KHARAZI_NE);
testSolver(solver, new WorldPoint(2851, 2955, 0), RESPONSE_TEXT_VERY_HOT, intermediateFoundLocations);
testSolver(solver, new WorldPoint(2852, 2955, 0), RESPONSE_TEXT_VERY_HOT_WARMER, finalLocation);
testSolver(solver, new WorldPoint(2851, 2955, 0), RESPONSE_TEXT_VERY_HOT_COLDER, finalLocation);
testSolver(solver, new WorldPoint(2465, 3495, 0), RESPONSE_TEXT_ICE_COLD_COLDER, finalLocation);
testSolver(solver, new WorldPoint(3056, 3291, 0), RESPONSE_TEXT_VERY_COLD_WARMER, finalLocation);
testSolver(solver, new WorldPoint(2571, 2956, 0), RESPONSE_TEXT_VERY_COLD_WARMER, finalLocation);
}
@Test
public void testNarrowToFindSolutions()
{
final HotColdSolver solver = createHotColdSolver();
final Set<HotColdLocation> firstLocationsSet = Sets.immutableEnumSet(
HotColdLocation.FELDIP_HILLS_GNOME_GLITER,
HotColdLocation.FELDIP_HILLS_RED_CHIN,
HotColdLocation.KARAMJA_KHARAZI_NE,
HotColdLocation.KARAMJA_CRASH_ISLAND);
final Set<HotColdLocation> secondLocationsSet = firstLocationsSet.stream()
.filter(location -> location != HotColdLocation.FELDIP_HILLS_RED_CHIN)
.collect(Collectors.toSet());
final Set<HotColdLocation> thirdLocationSet = secondLocationsSet.stream()
.filter(location -> location != HotColdLocation.FELDIP_HILLS_GNOME_GLITER)
.collect(Collectors.toSet());
final Set<HotColdLocation> finalLocation = thirdLocationSet.stream()
.filter(location -> location != HotColdLocation.KARAMJA_CRASH_ISLAND)
.collect(Collectors.toSet());
testSolver(solver, new WorldPoint(2711, 2803, 0), RESPONSE_TEXT_COLD, firstLocationsSet);
testSolver(solver, new WorldPoint(2711, 2802, 0), RESPONSE_TEXT_COLD_SAME_TEMP, firstLocationsSet);
testSolver(solver, new WorldPoint(2716, 2802, 0), RESPONSE_TEXT_COLD_WARMER, secondLocationsSet);
testSolver(solver, new WorldPoint(2739, 2808, 0), RESPONSE_TEXT_COLD_WARMER, thirdLocationSet);
testSolver(solver, new WorldPoint(2810, 2757, 0), RESPONSE_TEXT_COLD_COLDER, finalLocation);
}
@Test
public void testSomewhatDistantLocations()
{
// Activate device on Ape Atoll when solution point is HotColdLocation.KARAMJA_KHARAZI_NE
testSolver(createHotColdSolver(), new WorldPoint(2723, 2743, 0), RESPONSE_TEXT_COLD,
Sets.immutableEnumSet(
HotColdLocation.KARAMJA_KHARAZI_NE,
HotColdLocation.KARAMJA_KHARAZI_SW,
HotColdLocation.KARAMJA_CRASH_ISLAND,
HotColdLocation.FELDIP_HILLS_SW,
HotColdLocation.FELDIP_HILLS_RANTZ,
HotColdLocation.FELDIP_HILLS_RED_CHIN,
HotColdLocation.FELDIP_HILLS_SE));
// Activate device near fairy ring DKP when solution point is HotColdLocation.KARAMJA_KHARAZI_NE
testSolver(createHotColdSolver(), new WorldPoint(2900, 3111, 0), RESPONSE_TEXT_COLD,
Sets.immutableEnumSet(
HotColdLocation.KARAMJA_WEST_BRIMHAVEN,
HotColdLocation.KARAMJA_KHARAZI_NE,
HotColdLocation.ASGARNIA_COW,
HotColdLocation.ASGARNIA_CRAFT_GUILD,
HotColdLocation.KANDARIN_WITCHHAVEN,
HotColdLocation.MISTHALIN_DRAYNOR_BANK));
// Activate device on Mudskipper Point when solution point is HotColdLocation.KARAMJA_KHARAZI_NE
testSolver(createHotColdSolver(), new WorldPoint(2985, 3106, 0), RESPONSE_TEXT_COLD,
Sets.immutableEnumSet(
HotColdLocation.KARAMJA_BRIMHAVEN_FRUIT_TREE,
HotColdLocation.KARAMJA_KHARAZI_NE,
HotColdLocation.ASGARNIA_COW,
HotColdLocation.ASGARNIA_CRAFT_GUILD,
HotColdLocation.MISTHALIN_LUMBRIDGE_2,
HotColdLocation.DESERT_BEDABIN_CAMP));
}
@Test
public void testIsFirstPointCloserRect()
{
assertFalse(isFirstPointCloserRect(new WorldPoint(0, 0, 0), new WorldPoint(0, 0, 0), new Rectangle(0, 0, 1, 1)));
assertFalse(isFirstPointCloserRect(new WorldPoint(1, 0, 0), new WorldPoint(5, 0, 0), new Rectangle(2, 1, 5, 5)));
assertFalse(isFirstPointCloserRect(new WorldPoint(1, 0, 0), new WorldPoint(0, 0, 0), new Rectangle(2, 0, 1, 2)));
assertFalse(isFirstPointCloserRect(new WorldPoint(0, 0, 0), new WorldPoint(1, 1, 1), new Rectangle(2, 2, 2, 2)));
assertFalse(isFirstPointCloserRect(new WorldPoint(0, 0, 0), new WorldPoint(4, 4, 4), new Rectangle(1, 1, 2, 2)));
assertFalse(isFirstPointCloserRect(new WorldPoint(3, 2, 0), new WorldPoint(1, 5, 0), new Rectangle(0, 0, 4, 4)));
assertTrue(isFirstPointCloserRect(new WorldPoint(1, 1, 0), new WorldPoint(0, 1, 0), new Rectangle(2, 0, 3, 2)));
assertTrue(isFirstPointCloserRect(new WorldPoint(4, 4, 0), new WorldPoint(1, 1, 0), new Rectangle(3, 3, 2, 2)));
assertTrue(isFirstPointCloserRect(new WorldPoint(3, 2, 0), new WorldPoint(7, 0, 0), new Rectangle(1, 3, 4, 2)));
}
@Test
public void testIsFirstPointCloser()
{
assertFalse(isFirstPointCloser(new WorldPoint(0, 0, 0), new WorldPoint(0, 0, 0), new WorldPoint(0, 0, 0)));
assertFalse(isFirstPointCloser(new WorldPoint(0, 0, 0), new WorldPoint(0, 0, 1), new WorldPoint(0, 0, 0)));
assertFalse(isFirstPointCloser(new WorldPoint(1, 0, 0), new WorldPoint(0, 0, 0), new WorldPoint(1, 1, 0)));
assertFalse(isFirstPointCloser(new WorldPoint(2, 2, 0), new WorldPoint(0, 0, 0), new WorldPoint(1, 1, 0)));
assertTrue(isFirstPointCloser(new WorldPoint(1, 0, 0), new WorldPoint(0, 0, 0), new WorldPoint(2, 0, 0)));
assertTrue(isFirstPointCloser(new WorldPoint(1, 1, 0), new WorldPoint(1, 0, 0), new WorldPoint(2, 2, 0)));
assertTrue(isFirstPointCloser(new WorldPoint(1, 1, 1), new WorldPoint(0, 1, 0), new WorldPoint(1, 1, 0)));
}
/**
* Tests a hot-cold solver by signalling a test point, temperature, and temperature change to it and asserting the
* resulting possible location set is equal to that of a given set of expected locations.
*
* @param solver The hot-cold solver to signal to.
* <br>
* Note: This will mutate the passed solver, which is helpful for testing
* multiple sequential steps.
* @param testPoint The {@link WorldPoint} where the signal occurs.
* @param deviceResponse The string containing the temperature and temperature change which is
* given when the hot-cold checking device is activated.
* @param expectedRemainingPossibleLocations A {@link Set} of {@link HotColdLocation}s which is expected to be
* given by {@link HotColdSolver#getPossibleLocations()} after it receives
* the signal formed by the other given arguments.
*/
private static void testSolver(final HotColdSolver solver, final WorldPoint testPoint, final String deviceResponse, final Set<HotColdLocation> expectedRemainingPossibleLocations)
{
final HotColdTemperature temperature = HotColdTemperature.getFromTemperatureSet(HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES, deviceResponse);
final HotColdTemperatureChange temperatureChange = HotColdTemperatureChange.of(deviceResponse);
assertNotNull(temperature);
assertEquals(expectedRemainingPossibleLocations, solver.signal(testPoint, temperature, temperatureChange));
}
/**
* @return A hot-cold solver with a starting set of master hot-cold locations nearby the KARAMJA_KHARAZI_NE
* location. {@link HotColdLocation#values()} is not used as it may change with future game updates, and
* such changes would break this test suite.
*/
private static HotColdSolver createHotColdSolver()
{
final Set<HotColdLocation> hotColdLocations = EnumSet.of(
HotColdLocation.KARAMJA_KHARAZI_NE,
HotColdLocation.KARAMJA_KHARAZI_SW,
HotColdLocation.KARAMJA_GLIDER,
HotColdLocation.KARAMJA_MUSA_POINT,
HotColdLocation.KARAMJA_BRIMHAVEN_FRUIT_TREE,
HotColdLocation.KARAMJA_WEST_BRIMHAVEN,
HotColdLocation.KARAMJA_CRASH_ISLAND,
HotColdLocation.DESERT_BEDABIN_CAMP,
HotColdLocation.DESERT_MENAPHOS_GATE,
HotColdLocation.DESERT_POLLNIVNEACH,
HotColdLocation.DESERT_SHANTY,
HotColdLocation.MISTHALIN_LUMBRIDGE,
HotColdLocation.MISTHALIN_LUMBRIDGE_2,
HotColdLocation.MISTHALIN_DRAYNOR_BANK,
HotColdLocation.ASGARNIA_COW,
HotColdLocation.ASGARNIA_PARTY_ROOM,
HotColdLocation.ASGARNIA_CRAFT_GUILD,
HotColdLocation.ASGARNIA_RIMMINGTON,
HotColdLocation.ASGARNIA_MUDSKIPPER,
HotColdLocation.KANDARIN_WITCHHAVEN,
HotColdLocation.KANDARIN_NECRO_TOWER,
HotColdLocation.KANDARIN_FIGHT_ARENA,
HotColdLocation.KANDARIN_TREE_GNOME_VILLAGE,
HotColdLocation.FELDIP_HILLS_GNOME_GLITER,
HotColdLocation.FELDIP_HILLS_JIGGIG,
HotColdLocation.FELDIP_HILLS_RANTZ,
HotColdLocation.FELDIP_HILLS_RED_CHIN,
HotColdLocation.FELDIP_HILLS_SE,
HotColdLocation.FELDIP_HILLS_SOUTH,
HotColdLocation.FELDIP_HILLS_SW
);
return new HotColdSolver(hotColdLocations);
}
}

View File

@@ -1,68 +0,0 @@
/*
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;
public class HotColdTemperatureChangeTest
{
private static final String[] VALID_MESSAGES = {
"The device is warm, and warmer than last time.",
"The device is cold, but colder than last time.",
"The device is very hot, and the same temperature as last time.",
};
private static final String[] INVALID_MESSAGES = {
"The device is cold.",
"The device is ice cold.",
"The device is very cold.",
"The device is hot.",
"The device is incredibly hot.",
"The device is an octopus, and is wetter than last time",
"foobar",
"a q p w",
"My feet are cold, I should put them in some lukewarm water, or run hot water over them.",
"and warmer than and colder than and the same temperature",
};
@Test
public void testValidTemperatureChangeMessages()
{
for (final String message : VALID_MESSAGES)
{
assertNotNull(message, HotColdTemperatureChange.of(message));
}
}
@Test
public void testInvalidTemperatureChangeMessages()
{
for (final String message : INVALID_MESSAGES)
{
assertNull(message, HotColdTemperatureChange.of(message));
}
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;
public class HotColdTemperatureTest
{
private static final String[] VALID_MESSAGES = {
"The device is warm, and warmer than last time.",
"The device is visibly shaking and burns to the touch. This must be the spot.",
"The device is cold.",
"The device is ice cold.",
"The device is very cold.",
"The device is hot.",
"The device is incredibly hot.",
};
private static final String[] INVALID_MESSAGES = {
"The device is an octopus, and is wetter than last time.",
"foobar",
"a q p w",
"My feet are cold, I should put them in some lukewarm water, or run hot water over them.",
};
@Test
public void testValidTemperatureMessages()
{
for (final String message : VALID_MESSAGES)
{
assertNotNull(message, HotColdTemperature.getFromTemperatureSet(HotColdTemperature.BEGINNER_HOT_COLD_TEMPERATURES, message));
assertNotNull(message, HotColdTemperature.getFromTemperatureSet(HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES, message));
}
}
@Test
public void testInvalidTemperatureMessages()
{
for (final String message : INVALID_MESSAGES)
{
assertNull(message, HotColdTemperature.getFromTemperatureSet(HotColdTemperature.BEGINNER_HOT_COLD_TEMPERATURES, message));
assertNull(message, HotColdTemperature.getFromTemperatureSet(HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES, message));
}
}
@Test
public void testAmbiguousTemperatureMessages()
{
assertEquals(HotColdTemperature.ICE_COLD, HotColdTemperature.getFromTemperatureSet(HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES, "The device is ice cold."));
assertEquals(HotColdTemperature.VERY_COLD, HotColdTemperature.getFromTemperatureSet(HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES, "The device is very cold."));
assertEquals(HotColdTemperature.VERY_HOT, HotColdTemperature.getFromTemperatureSet(HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES, "The device is very hot."));
}
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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.client.plugins.cluescrolls.clues.hotcold;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class MasterHotColdLocationTest
{
private static final Set<HotColdLocation> MASTER_HOT_COLD_LOCATIONS = Arrays.stream(HotColdLocation.values())
.filter(l -> !l.isBeginnerClue())
.collect(Collectors.toSet());
private static final int EXPECTED_DIMENSION_SIZE = 9;
@Test
public void beginnerHotColdLocationAreaTest()
{
for (final HotColdLocation location : MASTER_HOT_COLD_LOCATIONS)
{
assertEquals(EXPECTED_DIMENSION_SIZE, location.getRect().height);
assertEquals(EXPECTED_DIMENSION_SIZE, location.getRect().width);
}
}
}