Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

Sign up now!

Need help creating a web.

Joined
Dec 18, 2014
Messages
398
As I've said before, I've been attempting this for 3 days, with a total of about 20 hours burnt on trying to get from Point A to Point B. I would be strongly in your debt if you could help me get past this block.

edit: The problem is that the web.getPathBuilder().buildTo(new Coordinate(2851, 3027, 0)); is returning a null Path. I think I've generated the coordinates correctly, written them down correctly, read them correctly, and assigned them back to the web correctly. I can't find any error.
Code:
// in WebCreator.java
private Web web = new Web();
private FileWeb fileWeb = new FileWeb();
private Player player = Players.getLocal();

//these are Defeat3d's methods in his tutorial
    public static List<Coordinate> getSurroundingWeb(final Locatable loc, final int radius, final int divisibleBy) {
           final Coordinate[] reachable = loc.getPosition().getReachableCoordinates().toArray(new Coordinate[] {});
           List<Coordinate> web = new ArrayList<Coordinate>();
           for (Coordinate c : reachable) {
               if (c.getX() % divisibleBy == 0 && c.getY() % divisibleBy == 0 && c.distanceTo(loc) <= radius) {
                   web.add(c);
               }
           }
           return web;
       }
   
       public void addCoordinate(Coordinate... coordinates) {
           final GameObjectQueryBuilder objects = GameObjects.newQuery().types(GameObject.Type.BOUNDARY_OBJECT, GameObject.Type.PRIMARY, GameObject.Type.WALL_DECORATION);
           for (Coordinate c : coordinates) {
               final CoordinateVertex cv = new CoordinateVertex(c);
               web.addVertices(cv);
               final int[][] add = new int[][]{{-2, +2}, {0, +2}, {+2, +2}, {+2, 0}, {+2, -2}, {0, -2}, {-2, -2}, {-2, 0}};
               for (int[] i : add) {
                   final Coordinate yes = new Coordinate(c.getX() + i[0], c.getY() + i[1], c.getPlane());
                   final Coordinate between = new Coordinate(c.getX() + i[0] / 2, c.getY() + i[1] / 2, c.getPlane());
                   final WebVertex v = getVertexAt(yes);
                   if (v != null && objects.on(between).results().isEmpty()) {
                       cv.addBidirectionalEdge(v);
                   }
               }
           }
       }
   
       WebVertex getVertexAt(Coordinate coordinate) {
           for (WebVertex v : web.getRegularVertices()) {
               if (v.getPosition().equals(coordinate)) {
                   return v;
               }
           }
           return null;
       }


//calling Defeat3d's methods with a GUI
onActionPerformed(ActionEvent e)
{
if(e.getActionPerformed.equals("addArea")

// this is being called about every ten steps, encompassing with excess the starting and ending area
addCoordinate(getSurroundingWeb(player, 20, 2).toArray(new Coordinate[] {}));

else if(e.getActionPerformed.equals("write")
write();
}

//my method to write to a file
    public void write()
    {
        FileWeb web = new FileWeb();
        web.addVertices(this.web.getVertices());
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("webbie.web")))
        {
            oos.writeObject(web.toByteArray());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }


Code:
//in RaysNatRunner.java
private Player player = Players.getLocal();
private Web web = Traversal.getDefaultWeb();

    public boolean merge(final File file) {
        try(ObjectInputStream input = new ObjectInputStream(new FileInputStream(file)))
        {
            Object obj = input.readObject();
            if(obj != null && obj instanceof byte[])
            {
                System.out.println("Is an instance of");       //successfully prints this
                FileWeb fileWeb = FileWeb.fromByteArray((byte[])obj);
                this.web.addVertices(fileWeb.getVertices());
            }
            else System.out.println("not an instance of");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

@Override
public void onStart()
{
        merge(new File("webbie.web"));
}
@Override
public void onLoop()
{
//prints  true, meaning the Path generated is null.
        System.out.println(web.getPathBuilder().buildTo(new Coordinate(2851, 3027, 0)) == null);
        stop();
}
 
Last edited:
Engineer
Joined
Jul 28, 2013
Messages
2,776
Don't use an ObjectOutputStream, use a byte[] output stream. Next, by generating the "surrounding web" every few tiles, you're generating an enormously bulky and overlapping web that doesn't connect correctly.
 
Joined
Dec 18, 2014
Messages
398
I sort of assumed that adding a vertex that the web already had would have no effect. I will use a byte[] output stream, and attempt to modify Defeat3d's methods to use a Set in hopes of preventing overlap. I'll report back.
 
Engineer
Joined
Jul 28, 2013
Messages
2,776
I sort of assumed that adding a vertex that the web already had would have no effect. I will use a byte[] output stream, and attempt to modify Defeat3d's methods to use a Set in hopes of preventing overlap. I'll report back.
The problem isn't just overlap, the problem is the vertices that are like 1 tile away won't even be linked if you stick to defeateds method.
 
Joined
Dec 18, 2014
Messages
398
@Furor You're my savior. You told me about the BresenhamPath, which works with the default web. Now I can wrap up my Nat Runner.

My current dilemma is currently solved, thanks to Furor. My thanks to Cloud, also - I know you've spent a lot of time reading this and trying to help.



But I still haven't managed to create a web.


I don't need a web anymore, but the issue is still intriguing and might be worth an investigation if you have the time.
The problem isn't just overlap, the problem is the vertices that are like 1 tile away won't even be linked if you stick to defeateds method.
That's why I tried to use general concept of his methods and create my own version using +-1. Instead of using a Set, like I said I would in my last post, I just put in a check to see if the Map already contained the key. Here's the code. It still has the same problem of returning a null Path.

Code:
//the complete RaysWebCreator.java I didn't include the GUI.
package com.raymondbl.runemate.webCreator;

import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.runemate.game.api.client.paint.PaintListener;
import com.runemate.game.api.hybrid.entities.GameObject;
import com.runemate.game.api.hybrid.entities.Player;
import com.runemate.game.api.hybrid.location.Coordinate;
import com.runemate.game.api.hybrid.location.navigation.web.WebVertex;
import com.runemate.game.api.hybrid.location.navigation.web.default_webs.FileWeb;
import com.runemate.game.api.hybrid.location.navigation.web.vertex_types.CoordinateVertex;
import com.runemate.game.api.hybrid.region.GameObjects;
import com.runemate.game.api.hybrid.region.Players;
import com.runemate.game.api.hybrid.util.StopWatch;
import com.runemate.game.api.script.Execution;
import com.runemate.game.api.script.framework.LoopingScript;

public class RaysWebCreator extends LoopingScript implements
                                PaintListener, ActionListener
{
    private boolean condition;
    private Coordinate position;
    private RaysWebCreatorGUI gui;
    private Player player;
    private String command;
    private Map<Coordinate, WebVertex> vertices = new HashMap<>();
    private StopWatch runtime = new StopWatch();
  
    @Override
    public void actionPerformed(ActionEvent e)
    {
        String command = e.getActionCommand();
        if(command.equals("addArea") || command.equals("gen"))
        {
            this.command = command;
            condition = true;
        }
    }

    @Override
    public void onPaint(Graphics2D g)
    {
        if(gui != null)
        gui.setRuntime(runtime.getRuntimeAsString());
    }

    @Override
    public void onStart(String... args)
    {
        getEventDispatcher().addListener(this);
        gui = new RaysWebCreatorGUI();
        player = Players.getLocal();
        gui.setVisible(true);
        runtime.start();
        gui.setListener(this);
    }
  
    @Override
    public void onLoop()
    {
        condition = false;
        System.out.println("Waiting...");
        gui.setStatus("Waiting...");
        Execution.delayUntil(() -> condition);
        if(command.equals("addArea"))
        {
            addArea();
        }
        if(command.equals("gen"))
            gen();
        if(command.equals("reset"))
            reset();
          
    }
  
    public void addArea()
    {
        int radius = getRadius();
        position = player.getPosition();
        Collection<Coordinate> collection = position.getReachableCoordinates();
        Iterator<Coordinate> iterator = collection.iterator();
        while(iterator.hasNext())
        {
            Coordinate c = iterator.next();
            if((c.distanceTo(player) <= radius) && !vertices.containsKey(c))
            {
                GameObject object = GameObjects.getLoadedAt(c).first();
                if((object == null) || !object.getDefinition().impassable())
                {
                    CoordinateVertex v = new CoordinateVertex(c);
                    vertices.put(c, v);
                }
            }
        }
      
        vertices.forEach((Coordinate key, WebVertex vertex) ->
        {
            int[][] ar = new int[][]
                    {
                    {-1, 0, 1}, {-1, 0, 1}
                    };
            for(int i = 0; i < 3; i++)
            {
                for(int k = 0; k < 3; k++)
                {
                    Coordinate c = new Coordinate(ar[0][i], ar[1][k]);
                    if(vertices.containsKey(c))
                    {
                        vertex.addBidirectionalEdge(vertices.get(c));
                    }
                }
            }
        });      
    }
  
    public void gen()
    {
        gui.setStatus("genning...");
        System.out.println("genning...");
        Collection<WebVertex> list = new ArrayList<>();
        vertices.forEach((Coordinate key, WebVertex vertex) ->
                list.add(vertex));
        FileWeb web = new FileWeb();
        web.addVertices(list);
        try(FileOutputStream fos = new FileOutputStream("webbset.web"))
        {
            fos.write(web.toByteArray());
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public void reset()
    {
        vertices = new HashMap<>();
    }
  
    public int getRadius()
    {
        return Integer.parseInt(gui.getRadius());
    }
  
}
Code:
//the only method that really matters in the main NatRunner class

public boolean merge(final File file) {
        try(FileInputStream input = new FileInputStream("webbset.web"))
        {
            byte[] obj = new byte[input.available() + 32];
            input.read(obj);
              FileWeb fileWeb = FileWeb.fromByteArray(obj);
            System.out.println(fileWeb.getVertices());
            this.web.addVertices(fileWeb.getVertices());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
 
Engineer
Joined
Jul 28, 2013
Messages
2,776
another problem is with your merge method, just adding the new vertices isn't enough. You have to connect things with edges or else you will have a split web. I'd assume the problem lies with your edges not correctly connecting and thus the web ending up with isolated sections.
 
Joined
Dec 18, 2014
Messages
398
I thought the edges added before writing the file would carry over. I'll add them in the merge() method first thing tomorrow morning and post a status update.
 
Engineer
Joined
Jul 28, 2013
Messages
2,776
I thought the edges added before writing the file would carry over. I'll add them in the merge() method first thing tomorrow morning and post a status update.
You're right, they should be. But you're never connecting your additions to the default web with an edge.
 
Joined
Dec 18, 2014
Messages
398
You're right, they should be. But you're never connecting your additions to the default web with an edge.
The new vertices completely cover the path, though, with room to spare. Theoretically, the default web shouldn't even be needed.
I'm also assuming in the code that the Coordinate class override the equals() method so that different objects with the same fields are treated as equal.
I'll try to connect them to the default web.
 
Joined
Dec 10, 2014
Messages
3,301
The new vertices completely cover the path, though, with room to spare. Theoretically, the default web shouldn't even be needed.
I'm also assuming in the code that the Coordinate class override the equals() method so that different objects with the same fields are treated as equal.
I'll try to connect them to the default web.
If they're not connected, then how would you expect it to build a path over the gap? Even if they overlap, if there's no edge there's no path to follow.
 
Joined
Dec 18, 2014
Messages
398
If they're not connected, then how would you expect it to build a path over the gap? Even if they overlap, if there's no edge there's no path to follow.
What gap? If what's not connected? If what overlaps? I'm not sure what you mean here. All the new vertices should be interconnected - the path is wholly within those new vertices. That's why I said the default web shouldn't be needed. I tried it using private Web web = new Web(); and using the merge method to read the FileWeb into that empty Web, but the pathbuilder still came out with a null path.
 
Joined
Dec 18, 2014
Messages
398
In the nested for loops - you see this?
Code:
Coordinate c = new Coordinate(ar[0][i], ar[1][k]);

I originally meant to put
Code:
Coordinate c = key.derive(ar[0][i], ar[1][k]);

...

*facepalm*

That was pretty much the only change to the above code for it to work with its own web, without merging the default web!
Thanks again, Cloud. I am in your debt.

I plan on saving Defeat3d some time and uploading this as a similar tool, but for RS3 and open-source. I will give Cloud and Defeat3d credit in the GUI.
 
Top