Author Topic: Technical side discussion  (Read 164726 times)

Arcana

  • Sultaness of Stats
  • Elite Boss
  • *****
  • Posts: 3,672
Re: Technical side discussion
« Reply #40 on: July 11, 2015, 01:41:28 AM »
My dreams of adapting an existing bot with a PC plugin are starting to look like so much star dust, lol.

I guess I'm going to have to dive into the nuts and bolts of XMPP to do this right.

I believe it is highly unlikely you'll be able to repurpose existing bot technology here.  Most bot technology is designed to manipulate game clients or computer input (i.e. pushing buttons, typing keys, and using pattern recognition to locate buttons and other screen elements to drive the bot actions).  Unless you want to write a bot that literally takes over the City of Heroes game client, and can only do what a player can do operating that client, you'll have to implement the actual XMPP communications channel instead.

This is something few if any bots do, because its ordinarily so complicated and difficult of a task.  However, in this case, as complex as Codewalker's information appears, it is infinitely easier to generate XMPP to pretend to be a Paragon Chat bot than it would be to try to do this directly with a game's client under normal circumstances.  You might be able to make a client-input-controlling World of Warcraft bot in an afternoon, but a native WoW bot that talks directly to the WoW servers?  That's a task and a half.  I'm all the way to an invisible bot and most of the way to a visible Paragon Chat bot (that can do things no player can do) in about ten cumulative hours of work.  That's ten hours to learn XMPP, understand how stanzas work, learn a python XMPP framework (sleekxmpp), write practice code, test it, and also install and configure a dedicated Openfire test server to test my code without interfering with live Paragon Chat users.

Starting from scratch ten hours probably doesn't get you past the WoW authentication servers.

However, if all you want to do is literally run around like a player might, you could use someone's bot framework and write a bot that basically takes over keyboard and mouse from you after you start up Paragon Chat.  What I want to do can't be done that way.  But if what you want to do can be, it might be easier than implementing a native bot from scratch.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #41 on: July 11, 2015, 02:28:28 AM »
I got the impression slickriptide was talking about something more akin to adapting an IRC chat bot or response bot, which is a lot closer in principle to how a Paragon Chat bot would work.

I could probably whip up some reference code of the costume hash at some point. Maybe in Python since it's easy to do quick prototypes in, and would plug in to your existing bot framework.

Arcana

  • Sultaness of Stats
  • Elite Boss
  • *****
  • Posts: 3,672
Re: Technical side discussion
« Reply #42 on: July 11, 2015, 02:49:25 AM »
I got the impression slickriptide was talking about something more akin to adapting an IRC chat bot or response bot, which is a lot closer in principle to how a Paragon Chat bot would work.

On the surface yes, but when slickriptide specified that he/she wanted an avatar and the ability to both speak and emote, to me that immediately left the realm of text chat botting, at least based on my knowledge of the limits of how those tend to work.  The IRC part would be doing so little compared to how much you would have to build to make work as to make the contribution of the IRC bot itself seem not worth the effort to me.  Perhaps there are better chat bot frameworks that I'm not familiar with that you could adapt.  That's outside my wheelhouse.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #43 on: July 11, 2015, 03:00:54 AM »
Also sounds vaguely like a MUD bot or plugin running an NPC script, but those usually don't have to worry about costumes and 3D positioning...

Arcana

  • Sultaness of Stats
  • Elite Boss
  • *****
  • Posts: 3,672
Re: Technical side discussion
« Reply #44 on: July 11, 2015, 03:17:18 AM »
Also sounds vaguely like a MUD bot or plugin running an NPC script, but those usually don't have to worry about costumes and 3D positioning...

If you would be so kind as to add /move_left, /move_right, /move_forward, /move_backward, /move_leap, /turn_clockwise, /turn_counterclockwise, /display_costume_file, and /use_item slash commands in version 0.97, we could turn City of Heroes into Zork and bot writing would become a heck of a lot easier.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #45 on: July 11, 2015, 05:02:50 AM »
If you would be so kind as to add /move_left, /move_right, /move_forward, /move_backward, /move_leap, /turn_clockwise, /turn_counterclockwise, /display_costume_file, and /use_item slash commands in version 0.97, we could turn City of Heroes into Zork and bot writing would become a heck of a lot easier.

That's actually why one of the future goals is to add a scripting API using Lua or something similar to Paragon Chat eventually, so that you can leverage its knowledge of the game world to move around without having to load and parse maps and geometry, etc.

That's a ways off though, so for now XMPP bots with static locations or fixed paths are probably the way to go.

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #46 on: July 11, 2015, 07:29:14 AM »
I'm actually working with Sleekxmpp but it was only a couple of hours ago that I dug up the developer docs on Github that talked about how to create custom stanzas. Now I'm feeling more confident that it actually can do the sort of processing required to deal with the special Paragon Chat <pc:> and <u:> stanzas and whatever else there is or might potentially be.

I am not imagining anything terribly complicated for a first outing. For a chatbot-based NPC, I envision something like old-school Everquest NPC's. Imagine the following:

A little girl is standing near a bus stop. Periodically, she does a "worry" emote and says, "Oh, my poor kitty!" or "I'm so worried about my kitty!"

If someone local says, "What about your kitty?" or really, anything with the word "kitty" in it, the girl replies that her kitty is stuck in a tree and can't get down.

If the erstwhile hero asks where is the tree, she says, "Follow me" and leads the hero around the zone to a place with a tree and an invisible bot in that location.

If the hero chooses any of a number of verbs (shake tree, kick tree, punch tree, etc...) the invisible bot gives itself a costume hash, becomes visible,and a catgirl drops out of the sky, meows threateningly, and runs away leaving the hero to accept the thanks of the little girl and wonder what the hell just happened, heh.

All of that ought to be doable, though the moving around bit would present some challenges.

Speaking of stanzas, I've been wondering - Are there dtd's for the namespaces of those custom stanzas or is it enough to simply define the name spaces and leave the structure of them ambiguous? If Paragon Chat has DTD's defined for <pc:> and <u:> and what not, do bots that define the same name spaces require those DTD's?

I think what I'm really going to be interested in whether a bot can induce a change in the state of a player. For instance, I've edited my character record in the SQLite database to put my character next to the flagpole atop city hall. It would be very interesting to be able to send a message to a player that says, "Change to these x,y,z coordinates". You could make a taxibot that offers a series of destinations and a player could say, "Taxibot, flagpole" to be "teleported" to the flagpole.




Arcana

  • Sultaness of Stats
  • Elite Boss
  • *****
  • Posts: 3,672
Re: Technical side discussion
« Reply #47 on: July 11, 2015, 09:42:11 AM »
I'm actually working with Sleekxmpp but it was only a couple of hours ago that I dug up the developer docs on Github that talked about how to create custom stanzas. Now I'm feeling more confident that it actually can do the sort of processing required to deal with the special Paragon Chat <pc:> and <u:> stanzas and whatever else there is or might potentially be.

It most definitely can.  Its a little frustrating figuring out the language, but the capabilities are all there.  Just don't ask me send/send_X semantics questions yet.


Quote
Speaking of stanzas, I've been wondering - Are there dtd's for the namespaces of those custom stanzas or is it enough to simply define the name spaces and leave the structure of them ambiguous? If Paragon Chat has DTD's defined for <pc:> and <u:> and what not, do bots that define the same name spaces require those DTD's?

Codewalker described all of them above.  However, since I already worked out sleekxmpp's kinks:

from sleekxmpp import ClientXMPP
from sleekxmpp.xmlstream.stanzabase import ElementBase

class pcCharacterStanza(ElementBase):
    namespace = 'pc:character'
    name = 'character'
    plugin_attrib = 'character'
    interfaces = set(('origin','map','class','name','costume'))
   
class pcPresenceStanza(ElementBase):
    namespace = 'pc:presence'
    name = 'pc'
    plugin_attrib = 'pc'
    interfaces = set(('jid','protocol'))

class pcuStanza(ElementBase):
    namespace = 'pc:u'
    name = 'u'
    plugin_attrib = "u"
    interfaces = set(('p','m','v','o'))

class pcChannelStanza(ElementBase):
    namespace = 'pc:message'
    name = 'channel'
    plugin_attrib = 'channel'
    interfaces = set(('id'))

class pcDescriptionStanza(ElementBase):
    namespace = 'pc:description'
    name = 'description'
    plugin_attr = 'description'

(warning: do not list subinterfaces like a lot of sleekxmpp demo code does.  That will convert stanza attributes into substanzas, i.e. it will turn <u xmlns="pc:u" o="0 0 0" /> into <u xmlns="pc:u"><o>"0 0 0"</ o></ u>.  Demo writers like to teach highly normalized XML/XMPP.)

You have to register those as plugins to the appropriate parent stanza:

registerStanzaPlugin(Presence,pcPresenceStanza)
registerStanzaPlugin(Presence,pcCharacterStanza)
registerStanzaPlugin(Iq,pcDescriptionStanza)
registerStanzaPlugin(Message,pcuStanza)
registerStanzaPlugin(Message,pcChannelStanza)

You then make handlers that access the contents of a stanza like so:

def handle_pcPresenceStanza(self,msg):
    print "Debug: pcPresence jid:" + str(msg.values['pc']['jid'])
    print "Debug: pcPresence character costume: " + str(msg.values['character']['costume'])

and register them as a callback in the appropriate xmpp object, with the appropriate XPath matching pattern:

self.registerHandler(Callback('pcPresenceStanza Handler', MatchXPath('{%s}presence/{%s}pc' % (self.default_ns, pcPresenceStanza.namespace)), self.handle_pcPresenceStanza))

Technically speaking, you don't need to implement stanza plugins because you can just register handlers to process all Iq, Presence, and Message stanzas and write your own parser to parse the raw stanza information (ala str(stanza_msg)), but that's crazy.

I haven't written the costume code yet, so those stanza definitions aren't above yet.  But you should be able to figure out how to do that by following the examples.


Quote
I think what I'm really going to be interested in whether a bot can induce a change in the state of a player. For instance, I've edited my character record in the SQLite database to put my character next to the flagpole atop city hall. It would be very interesting to be able to send a message to a player that says, "Change to these x,y,z coordinates". You could make a taxibot that offers a series of destinations and a player could say, "Taxibot, flagpole" to be "teleported" to the flagpole.

At the moment I do not believe that is possible, because I don't think Paragon Chat itself supports that.  Which is why I'm investigating bots.  Paragon Chat doesn't "react" to events, but nothing stops a bot from doing so.  To put it another way, at the moment a bot cannot knock a player over.  But hypothetically speaking, a player can knock a bot over, because bots can take dives.

Just a note: your bot won't have any idea where flagpoles and buildings are, and for that matter where the ground is, unless you write special code that can read City of Heroes mapfiles.  In the absence of such an ability, you will be forced to "hardcode" where the bot goes so it doesn't pass through walls or move downward through the ground.  Your bot doesn't have the game client's collision detection logic, so you have to write your own or figure out another way for the bot to go where you want it to go with the right movement path that "looks right" to everyone else in the game.

That's what the whole LUA-thing exchange was between Codewalker and myself just now.  Theoretically speaking, Paragon Chat (the software) itself knows what players can and cannot do in large part, including knowing how to read maps and detect collisions.  Its hypothetically possible for Codewalker to add features to Paragon Chat that allow bot writers and other scripters like machinima authors to tell Paragon Chat what they want the bot to do, and have Paragon Chat tell the bot if those actions are legal, or alternatively calculate their result and push that back to the bot.  That would basically put me out of the bot-writing business (and put me in the LUA scripting business).

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #48 on: July 11, 2015, 01:24:52 PM »
Thanks for the code @Arcana. That is substantially what I was composing in my brain after reading the docs, though I was still scratching my head over the way Sleekxmpp tends to treat attributes and elements as somewhat interchangable from a data manipulation standpoint.

My question about namespaces is a non-issue. It's so ingrained in me that a xml namespace is a URI that it never occurred to me that the URI was simply a convention without inherent meaning. I learned something new. Thanks wikipedia! ;-) (Due, no doubt, to Googles's web page schema data initiative being my first exposure to name spaces.)

Personally, I look forward to the day that I get out of the bot scripting biz and into the LUA scripting biz. ;-)

I think maybe you're right about the teleporting. Given what we know about the way movement used to work, it seems more likely that "teleport" was really a case of the client saying to the server, "I'm jumping over fo point X,Y,Z now using power Blah" and the server replying, "Okay, that's legit. I won't rubber band you back where you started."

OTOH - Team teleport illustrates that some sort of triggered moving mechanism had to exist in the client for that to work.

The server had the final say about the character's position in the world. With Paragon Chat acting as a kind of stub server, it might be possible for Codewalker to make a "move character #NAME to point X, Y, Z" primitive that a bot or script could invoke.



« Last Edit: July 11, 2015, 01:42:08 PM by slickriptide »

FloatingFatMan

  • An Offal
  • Elite Boss
  • *****
  • Posts: 1,178
  • Kheldian's Forever!
Re: Technical side discussion
« Reply #49 on: July 11, 2015, 02:17:14 PM »
I've have gotten a whole bunch of power animations working. Yay me! ;)

However, they have no FX, therefore only the basic fighting ones are of much use.  Is there a way of spawning power fx?  If not... Is that in the TODO list that CW hasn't written up yet? ;)

Also, many animations are made of multiple seqbits, yet chaining with mutliple Bits lines in emote.cfg does nada. Is it possible to chain movs?

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #50 on: July 11, 2015, 05:34:04 PM »
There is no support for Fx yet, as Fx are more complex in that they need source and target entities, and have to be handled differently for persistent fx versus one-shot fx. There are also some anti-griefing protections that need to be dealt with as there are some screen space Fx that do things like blur, shake, or black out everybody's screen.

Also, many animations are made of multiple seqbits, yet chaining with mutliple Bits lines in emote.cfg does nada. Is it possible to chain movs?

No, emotes are emotes and briefly assert a specific set of bits when used.

I'm not sure why you would need that, though. Not even powers do that, they all just set the bits once and let the sequencers handle chaining between moves.

FloatingFatMan

  • An Offal
  • Elite Boss
  • *****
  • Posts: 1,178
  • Kheldian's Forever!
Re: Technical side discussion
« Reply #51 on: July 11, 2015, 06:00:07 PM »
Ah, no worries, I was misreading how the sequencer ran the bits. I understand better now. :)

For the FX part, should not the targeting aspect work automatically, as long as I have someone actually targeted? Also, I quite understand about the griefing part, but as the ignore mode utterly removes an offender from your view etc, I presumed you wouldn't see that either...

Anyway, no rush on any FX stuff.. That's a "would be nice" thing way down the road of lots of more important stuff! ;)

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #52 on: July 11, 2015, 06:08:59 PM »
The selection (target) has nothing to do with fx playing. Fx have distinct source and target entities that don't necessarily have any relation to your actual target. For example, Fx designed to be played as power hit fx operate backwards, where the source is the entity that is being hit, and the target is the entity that launched the attack.

Ignore is good, but the problem with screen space Fx is that in a crowded zone, there wouldn't be any way to tell just who was causing the offending Fx to play.

FloatingFatMan

  • An Offal
  • Elite Boss
  • *****
  • Posts: 1,178
  • Kheldian's Forever!
Re: Technical side discussion
« Reply #53 on: July 11, 2015, 06:13:05 PM »
OK, gotcha.  So my next question is.  What about player based fx such as heal aura's and what not?  No target other than the actual player to worry about, then.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #54 on: July 11, 2015, 06:21:08 PM »
Yeah, that would be nice to have, though as I mentioned about the toggle fx in costumes, Paragon Chat doesn't load the fx info so it has no way of knowing what kind of fx a given name is.

I'm not sure if loading the fxinfo is the best way to go in the long run, or if parsing the powers data and gleaning it from what kind of powers it's used by would be the safer bet. Either way means taking a big hit on Paragon Chat's startup time and memory usage, though I suspect if the powers data could be used for other things people may not mind so much.

Arcana

  • Sultaness of Stats
  • Elite Boss
  • *****
  • Posts: 3,672
Re: Technical side discussion
« Reply #55 on: July 11, 2015, 07:33:12 PM »
The selection (target) has nothing to do with fx playing. Fx have distinct source and target entities that don't necessarily have any relation to your actual target. For example, Fx designed to be played as power hit fx operate backwards, where the source is the entity that is being hit, and the target is the entity that launched the attack.

Ignore is good, but the problem with screen space Fx is that in a crowded zone, there wouldn't be any way to tell just who was causing the offending Fx to play.

One possibility is to use an opt in mechanism whereby Paragon Chat will let fx play on its own client, and send messages to everyone else with a special <u /> that has to be approved by the destination with some mechanism.  If it is, you will see the results of that person's fx spawning.  If you do not, you will not see.  Basically a reverse ignore.  By default you ignore everyone, opt in allows you to see.  Then this can be used in things like private maps or RP zones where everyone agrees to play nice.  Something like /enable_fx and /disable_fx, with parameters to enable and disable a specific person's fx commands.  For the technically minded, you could send combat spam to a CoH channel we could monitor that would explicitly state what fx we were seeing and how the spawner was (i.e. ArcanaBot initiated SomeKindOfFX from source to destination).  Sufficiently technically adept players could use that channel to identify and report griefers.

Its not perfect, but what it does is let people experiment with it even though most people may not see it, while eliminating all the griefing possibilities until a more global way to deal with fx griefing is established.

Arcana

  • Sultaness of Stats
  • Elite Boss
  • *****
  • Posts: 3,672
Re: Technical side discussion
« Reply #56 on: July 11, 2015, 07:37:55 PM »
Yeah, that would be nice to have, though as I mentioned about the toggle fx in costumes, Paragon Chat doesn't load the fx info so it has no way of knowing what kind of fx a given name is.

I'm not sure if loading the fxinfo is the best way to go in the long run, or if parsing the powers data and gleaning it from what kind of powers it's used by would be the safer bet. Either way means taking a big hit on Paragon Chat's startup time and memory usage, though I suspect if the powers data could be used for other things people may not mind so much.

Similar to emote.cfg, I would recommend exporting the powers database to a more efficient searchable form (most obvious solution would be to put the data into a sqlite database) as a one-time thing when the database does not exist, and eat the start up cost only once when you first run Paragon Chat.  Not sure if sqlite is fast enough for our purposes here, but maybe some kind of in-memory hash table could speed up search enough to make it credible.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #57 on: July 12, 2015, 12:59:52 AM »
Then this can be used in things like private maps or RP zones where everyone agrees to play nice.

That's kind of along the lines I was thinking for private map support once that is implemented. The creator of the map is effectively the GM while you're on it, and everyone's clients trust them fully. They can designate others as helper GMs (probably by making them admins of the XMPP room) who also gain those abilities.

Stuff like Fx could either be enabled by default on private rooms, trusting the 'GM' to enforce rules while there, or start out disabled and can be enabled for specific people or everyone with a command.

Arcana

  • Sultaness of Stats
  • Elite Boss
  • *****
  • Posts: 3,672
Re: Technical side discussion
« Reply #58 on: July 12, 2015, 10:10:55 PM »
I take the Golden AN, and I put it in the TAN VAN, yeah, and then I take it to Horace...

I think I'm getting close, but I'm probably missing some small critical XMPP protocol thing.  So I connect and announce presence in the atlaspark_meta room:

<presence from="arcanabot@core3770/ArcanaBot" xml:lang="en"><pc xmlns="pc:presence" jid="arcanabot@core3770/ArcanaBot" protocol="5" /><character xmlns="pc:character" origin="Magic" map="maps/City_Zones/City_01_01/City_01_01.txt" costume="Lxdw1TQl8g/dEYfAJNh7LE7oe6c=" name="ArcanaBot" class="Class_Blaster" /></presence>

And then I groupchat my location to the room name:

<message to="atlaspark_meta@conference.core3770" type="groupchat" xml:lang="en" from="arcanabot@core3770/ArcanaBot"><u xmlns="pc:u" p="146.4 0.3 -98.4" m="READY" o="0.0 -2.83 0.0" v="0.0 0.0 0.0" /></message>

And then I wait.  I'm pretty sure that is sending in the right way, because the bot sees that Presence boomerang back (and ignores it, but it sees it) as well as the <u />.  And when Paragon Chat logs into the same room, I see its Presence:

<presence to="arcanabot@core3770/74096bbe" from="atlaspark_meta@conference.core3770/Arcana"><pc xmlns="pc:presence" jid="arcanacoh@core3770/Arcana" protocol="5" /><character xmlns="pc:character" origin="Magic" map="maps/City_Zones/City_01_01/City_01_01.txt" costume="Lxdw1TQl8g/dEYfAJNh7LE7oe6c=" class="Class_Blaster" name="Arcana" /><x xmlns="http://jabber.org/protocol/muc#user"><item affiliation="owner" jid="arcanacoh@core3770/Arcana" role="moderator" /></x></presence>

When I see a new Presence, I retransmit <u />:

<message to="atlaspark_meta@conference.core3770" type="groupchat" xml:lang="en" from="arcanabot@core3770/ArcanaBot"><u xmlns="pc:u" p="146.4 0.3 -98.4" m="READY" o="0.0 -2.83 0.0" v="0.0 0.0 0.0" /></message>

I see Paragon Chat do the same:

<message to="arcanabot@core3770/74096bbe" type="groupchat" from="atlaspark_meta@conference.core3770/Arcana"><u xmlns="pc:u" p="116.4 -0.5 -89.3" m="READY2" o="0 -1.55 0" /></message>

And then... nothing.  I keep sending, PC keeps sending, but I don't see the bot in Paragon Chat.  Not sure why.  I engineered it so the bot has the same costume hash as the Paragon Chat client, so I do not need to support Iq costume, but even if that was wrong I should have then seen an Iq request for costume, which I don't.  Paragon Chat doesn't think I'm "there" yet, and I'm still trying to hunt down why.

I hope its not one of a hundred miscellaneous XMPP protocol thingies that I presumed XMPP would take care of but isn't for some reason.  That might be difficult to track down an hour at a time.  Separate from the atlaspark_meta channel, the bot also joins the atlaspark channel, and that works fine.  Chat clients can see the bot's presence, the bot can chat with them, the bot can hear what they say.  Its not totally broken, so the problem is likely in the pc: namespace stanzas somewhere.

On the plus side, I do have wasd moving me around.  In a theoretical sort of way.  I'm working on a radar for the bot, so it can show the locations of every Paragon Chat character in the zone that it receives position data for.  No map info yet, just radar in space.  But actually becoming visible is my high priority figure-out at the moment.  If I can get the bot visible, I can then clean up all the debug code and probably start writing documentation.  At the moment, I can only document how to make a bot that nobody can see, although it tries really hard in a sad "I'm here, can anyone see me?" sort of way.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #59 on: July 12, 2015, 10:43:35 PM »
Do you have the latest update, Arcana?

Versions prior to 0.97c had a bug in the order of processing where the metadata channel presence callback would be called before the main presence handler (that parses <character>). So if the first presence received was for the meta channel, it would fail to create the proxy entity, making position updates meaningless.

This was masked by the separate issue that PC sends <character> in every presence stanza, including those to the broadcast channel and globals (i.e. Paragon Chat). So in most cases it had already seen <character> first. Once I fixed that issue the processing order bug became readily apparent. But your bot might very well be joining the metadata room first and bumping into that.