• You've discovered RedGuides 📕 an EverQuest multi-boxing community 🛡️🧙🗡️. We want you to play several EQ characters at once, come join us and say hello! 👋
  • IS THIS SITE UGLY? Change the look. To dismiss this notice, click the X --->
MQ2DanNet

Plugin - MQ2DanNet (1 Viewer)

dannuic

Moderator
Joined
Sep 12, 2004
RedCents
15,264¢
dannuic submitted a new resource:

MQ2DanNet - It's not just for Dans anymore

Here we have an auto-discovery peer to peer networking plugin that utilizes ∅MQ and zyre. I have linked the README.md on the github for command/TLO/ini reference.

The gdrive link points to the latest live build, but the source compiles for ROF2 and Test without modification, so feel free to clone https://github.com/dannuic/MQ2Dan and compile it (all required libs are built and statically linked along with it). I usually have a test build available since I play on test, so...

Read more about this resource...
 
Some Notes about Setup
  • Some complicated network topologies won't be supported (a server interface is a better solution)
  • If for some reason the peers aren't self-discovering on a local network
    • check the output of /dnet interface
    • set one of the discovered interface names with /dnet interface <name>
    • failing that, I'll have to look into why, so contact me with as much info as possible
Use
There are 2 basic uses
  1. Set up an observer
  • Methods of setting up an observer
  • Reading an observer's data: ${DanNet[<name>].Observe[<query>]} or ${DanNet[<name>].O[<query>]}
  • Dropping an observer: /dobserve <name> <query> drop

  1. Single-use direct query
  • Submitting a query: /dquery <name> [-q <query>] [-o <result>] [-t <timeout>]
    • Combines /delay with /varset
    • timeout is optional, and the default can be configured
    • result is optional, will just write out the result if omitted
    • If not run in a macro, ignores result and just writes out
Queries

A query is simply a normal TLO access from the perspective of the peer with the external ${} stripped Examples:
  • Me.CurrentMana
  • Target.ID
  • Me.Current$\{thing} -- this will evaluate ${thing} on the peer before sending a response
Names

A fully-qualified name is <server>_<character>, but if you only intend to communicate on your own server, you can ommit the first part and use just <charactername> in all these commands. Examples:
  • Locally talk to fatty: /dtell fatty You smell.
  • Talk to fatty on the test server: /dtell test_fatty I can still smell you from this server!
Commands

I have added some simple echo commands in addition to /dinfo and /dobserve, as well as a way to join/leave arbitrary groups.
  • /djoin <group> [all|save] -- join a group, and optionally write to [General] or [server_character] (all or save, respectively)
  • /dleave <group> [all|save] -- leave a group, and optionally write to [General] or [server_character] (all or save, respectively)
  • /dtell <name> <text> -- echo text on peer's console
  • /dgtell <group> <text> -- echo text on console for all peers in group
  • /dexecute <name> <command> -- executes a command on peer's client
  • /dgexecute <group> <command> -- executes a command on all clients in a group (except own)
  • /dgaexecute <group> <command> -- executes a command on all clients in a group (including own)
  • /dnet [<arg>] -- sets some variables, gives info, check in-game output for use
  • /dobserve <name> [-q <query>] [-o <result>] [-drop] -- add an observer on name and update values in result, or drop the observer
  • /dquery <name> [-q <query>] [-o <result>] [-t <timeout>] -- execute query on name and store return in result
TLO Members
  • Name -- current node name (fully qualified)
  • Debug -- debugging flag
  • LocalEcho -- local echo flag (outgoing echo)
  • CommandEcho -- command echo (incoming commands)
  • FullNames -- print fully qualified names?
  • FrontDelim -- use a front | in arrays?
  • Timeout -- timeout for implicit delay in /dquery and /dobserve commands
  • ObserveDelay -- delay between observe broadcasts (in ms)
  • Keepalive -- keepalive time for non-responding peers (in ms)
  • PeerCount -- number of connected peers
  • Peers -- list of connected peers
  • GroupCount -- number of all groups
  • Groups -- list of all groups
  • JoinedCount -- number of joined groups
  • Joined -- list of joined groups
  • O Observe -- observe accessor, accessed like: ${DanNet[peer_name].Observe[query]}
  • Q Query -- query accessor, for last executed query

Both Observe andQueryare their own data types, which provide aReceivedmember to determine the last received timestamp, or 0 for never received. Used like${DanNet.Q.Received}`

INI entries (MQ2DanNet.ini)
  • [General]
    • Groups -- |-delimited list of groups for all characters to auto-join, default empty
    • Debugging -- on/off/true/false boolean for debugging output, default off
    • Local Echo -- on/off/true/false boolean for local echo, default on
    • Command Echo -- on/off/true/false boolean for remote and local command (/dgex, &c) output, default on
    • Full Names -- on/off/true/false boolean for displaying fully-qualified names (on means that all names are displayed as server_character), default on
    • Front Delimiter -- on/off/true/false boolean for putting the | at the front for the TLO output of DanNet.Peers &c, default off
    • Query Timeout -- timeout string for implicit delay in /dquery and /dobserve, default is 1s
    • Observe Delay -- delay in milliseconds for observation evaluations to be sent, default is 1000
    • Keepalive -- timeout in milliseconds before an unresponsive peer is dropped, default is 30000
    • Tank -- short-name class list to auto-join the tank channel, default is war|pal|shd|
    • Priest -- short-name class list to auto-join the priest channel, default is clr|dru|shm|
    • Melee -- short-name class list to auto-join the melee channel, default is brd|rng|mnk|rog|bst|ber|
    • Caster -- short-name class list to auto-join the caster channel, default is nec|wiz|mag|enc|
  • [server_character]
    • Groups -- |-delimited list of groups for this specific character to auto-join, default empty
 
Last edited:
So i'm curious. Is this a plugin written to control multiple clients on the same subnet for the purpose of playing on your own emu server?
 
So i'm curious. Is this a plugin written to control multiple clients on the same subnet for the purpose of playing on your own emu server?
No, this is more towards the purpose of coordinating all of your clients, and providing an interface for remote execution of commands without needing a server.
 
INI:
check the output of /dnet info interface
set one of the discovered interface names with /dnet info interface <name>
so is this the correct command?
 
Can we get some actual examples? For instance, what is the sequence of commands to "observe" whether another character is targetting something? Or whether it has a given buff?

I tried a few iterations but I am clearly too stupid to understand the explanations.

Thx.
JJB
 
Disregard this, had an old version of another plugin causing some stack corruption and this just happened to be where it all fell down :(

What plugin was causing the issue? Having the same issue not using anything out of the ordinary from what comes with the redguides build.
 
Yah so a plugin not the problem as it turns out on testing some more. Looking like a linking issue, will need to be sorted out in the compile as soon as someone figures out how...
 
OK. Time for stupid questions. I have 2 characters running MQ2DanNet and trying to test using /dquery CharacherName -q Me.Name from the command line. using /dnet info shows both characters in the list and using /btell CharacterName Hello work fine. How can I get this to work for testing NOT using a Macro?
 
This plugin does will NOT update Outer Variables from a Sub Routine, it can't even see the Outer Variables. If you create the variables in the sub routine as local variables it works fine.

Never Mind. I figured it out.
 
Last edited:
was wondering if someone could explain the intended purpose of observers vs. queries. I am working on developing a macro framework that is entirely based on MQ2Dannet at it's core. When I tried to use observers I found it made my routines very unstable and unreliable, so I wonder if I misunderstand what they truly do. I have to say though that being able to access TLO's on the fly using /dquery is awesome and lightning fast compared to methods used to gather data by other macros.
 
Last edited:
From the way I understand it, observers are a more of a connection you create that get refreshed. Where a query is just that, get me what I ask for when I ask for it.

Something to keep in mind when using /dquery. Use global variables in your query. DanNet will throw errorrs when using local variables, if Dannet is not able to return the /dquery data, while your still in the routine, where you issued the /dquery call.

What I did, to try and fix that issue, was move all local variables to Outer variables, and the second, I set a variable to an initial value and used that variable as the Response variable. Then did a /delay checking the response. See Below:

/varset DResponse @null@
/dquery "WhoToQuery" -q Me.Name -o DResponse
/delay 20 ${DResponse.NotEqual[@null@]}

That's all I can suggest for now..
 
From the way I understand it, observers are a more of a connection you create that get refreshed. Where a query is just that, get me what I ask for when I ask for it.

Something to keep in mind when using /dquery. Use global variables in your query. DanNet will throw errorrs when using local variables, if Dannet is not able to return the /dquery data, while your still in the routine, where you issued the /dquery call.

What I did, to try and fix that issue, was move all local variables to Outer variables, and the second, I set a variable to an initial value and used that variable as the Response variable. Then did a /delay checking the response. See Below:

/varset DResponse @null@
/dquery "WhoToQuery" -q Me.Name -o DResponse
/delay 20 ${DResponse.NotEqual[@null@]}

That's all I can suggest for now..

I really hadn't encountered this error myself... Until I was working on checking for buff stacking. To test my routine for doing so, I created a level 1 cleric and ran the macro on it. It worked fine until I switched back to my main cleric and ran the macro again. Suddenly it was having problems updating local variables and was double casting buffs. Totally closed out of both my cleric and target characters session and restarted eq and the problem went away. The double casting is the same issue I was having when accessing observers repeatedly. It's like /dquery and observers are leaving phantom copies that return double results when accessed from different perspectives.

code I used that caused the issue in this circumstance :

INI:
        /if (${hpbuff.NotEqual[NULL]}) {
            /dquery ${Group.Member[${gmember}]} -q "Me.Buff[${hpbufftocheck}].ID" -o hpbuffcheck
                /if (!${hpbuffcheck} && !${Me.Casting.ID}) {
                    /call castspell "${hpbuff}" ${Group.Member[${gmember}].ID} "${Group.Member[${gmember}]}"
                }
        }

There is a lot more to the macro obviously but this is where the error occurred. Under normal circumstances with a clean eq session, it works 100% even using local variables.
 
Last edited:
I would try adding a delay after the /dquery, like I did in my example. That will help, but could still be issues. Moving all the variables to outer will correct the problem with error messages, but it will not fix the problem. The task at hand, is to find a way to make sure the /dquery has completed before letting you macro continue.

What is happening is the plugin is getting stalled, but your macro is continuing to run. Once the plugin finally catches up, your macro has exited the routine that issued the /dquery and is working in another routine.
 
MQ2DanNet is fine if you just want to send requests to other characters. The issue used to be when trying to get confirmation back from another client, that the request had been completed. I know there has been an update since I last tested Dannet, so this issue may be fixed. This is one of the things on my list to test. I just need to find the time.
 
MQ2DanNet is fine if you just want to send requests to other characters. The issue used to be when trying to get confirmation back from another client, that the request had been completed. I know there has been an update since I last tested Dannet, so this issue may be fixed. This is one of the things on my list to test. I just need to find the time.
I would be interested in knowing if this has changed too, how are others making sure queried vars are up to date before continuing?

Here's how /dquery works:
  • you issue the command with a query to a remote character
  • the TLO ${DanNet[<char>].Query[<query>]} clears, and the received time in ${DanNet[<char>].Query[<query>].Received} is some invalid entry (I actually forget which I made it because I'm dumb and I still don't have my computer unpacked)
  • when the remote character responds, those two entries are populated with information and a timestamp, respectively
    • This allows for macros do do things like /delay 10s ${DanNet[<char>].Query[<query>].Received} so that you delay the code just enough to get the information you want
    • You can also put the output (in macros only!) into a macro variable with the -o switch after declaring it

Alternatively! you can use /dobs, which has much the same format, but will continually send you updates from the remote character (default is once a second). After you set up the observer, getting the information will just grab you the latest received data without a wait for the handshake (at the cost of streaming the data over the network constantly, this is the trade-off). If you want to check the freshness of the data, there is still an .Received timestamp member on the TLO.
 
@dannuic , Running the attached macro on 9 characters. Using the command /bcaa //dantest ping all, worked for a while, but I finally got it to crash one of my toons. I started issuing the command from different characters to test, and it finally crashed. I can send you the dump file if you want.
 

Attachments

  • DanNetTest.mac
    6.8 KB · Views: 52
@dannuic , Running the attached macro on 9 characters. Using the command /bcaa //dantest ping all, worked for a while, but I finally got it to crash one of my toons. I started issuing the command from different characters to test, and it finally crashed. I can send you the dump file if you want.

I've had a crash or 2 from refreshing injections which is something I almost never do.

@ctaylor22 Nice test, pretty harsh, I'm curious how long it ran before you got it to crash? In a more real world instance like that where you know your going to be running the same queries over and over I imagine we'd use an observer instead, do you think if this was run setting up the queries as observers that it would still crash?
 
@dannuic , Running the attached macro on 9 characters. Using the command /bcaa //dantest ping all, worked for a while, but I finally got it to crash one of my toons. I started issuing the command from different characters to test, and it finally crashed. I can send you the dump file if you want.
Why would you invoke it with BC?
 
Plugin - MQ2DanNet

Users who are viewing this thread

Back
Top