API Discussion

[21:13:25] <lord2800> instead of trying to do all this complicated code in-core for 2.0, we should expose all the raw functions and properties and whatnot /right in the api/
[21:13:41] <lord2800> and then /build the api in raw javascript/
[21:16:02] <lord2800> there would be no confusion whatsoever about what any given function does
[21:20:26] <lord2800> so really, there's only a handful of things that /must/ be developed, the rest is more or less copy/paste fodder
[21:20:48] <lord2800> I need to look at how Node.js handles byte buffers, make a duplicate of that, and then we've got packets
[21:21:08] <lord2800> and I need to make a way to raise your own events
[21:21:22] <lord2800> (in fact, I need to write the whole event system)
[21:22:22] <lord2800> then I need to expose the UnitAny struct, all the unit lists, and various other bits like that, and then the rest can be done in javascript
[21:32:06] <CrazyCasta> so then the only thing left in the core would be the D2 function pointers, a little bit of assembly and w/e needs to be super fast?
[21:44:50] <lord2800> CrazyCasta: essentially, yeah
[21:45:24] <CrazyCasta> well, I don't like it all that much
[21:45:40] <CrazyCasta> I like that we can essentially keep the user from crashing the game/sending bad packets
[21:45:51] <lord2800> we can still prevent crashes
[21:45:53] <CrazyCasta> what I would support is making each js export function only do one thing
[21:45:59] <lord2800> by doing state checks at every api call
[21:46:30] <CrazyCasta> well, isn't it possible that the user could call a function w/ an invalid unit id?
[21:46:31] <lord2800> sending bad packets... well, we don't necessarily have to provide a way to /send/ packets, just /receive/ them and parse them and potentially block them
[21:47:03] <lord2800> the point would be that you never call an api function with a unit id, you call it with an instance of an exposed UnitAny, which we can stick the actual UnitAny ptr right in the private data
[21:47:06] <CrazyCasta> like calling the D2 export for click item on ground, but giving it id -1 or something
[21:47:32] <lord2800> and we just invalidate UnitAnys as necessary
[21:47:59] <CrazyCasta> oh, ok, so export the concept of the exports, but not the interface
[21:48:04] <lord2800> right
[21:48:21] <CrazyCasta> yeah, I'll still have to think abt it a bit, but it doesn't sound like that bad of an idea
[21:48:40] <lord2800> if it takes a ptr, we expose that object as a js object and make /that js object/ be the required param for the exposed function
[21:49:01] <lord2800> that way we never lose data integrity and we can do state checks as needed
[21:49:09] <CrazyCasta> right, but we're going to have to do more than that I think
[21:49:17] <lord2800> that means we have to deeply hook into the game's object creation stuff
[21:49:24] <lord2800> anywhere that allocates memory, basically
[21:50:06] <lord2800> basically, here's what I'm thinking: when a UnitAny is created in the game, we create a corresponding UnitAny js object and root it
[21:50:13] <CrazyCasta> basically you're saying you want to create some collection of js unitany's that mirrors d2's unitany's
[21:50:25] <CrazyCasta> such that it's a 1:1 rather 1:many relationship
[21:50:36] <lord2800> that UnitAny object has a valid property (or something) that is true so long as the UnitAny hasn't been destroyed
[21:51:01] <lord2800> when the game deletes a UnitAny, we set the private data to NULL, flip the valid flag, and unroot it
[21:51:18] <lord2800> it'll be destroyed in the next gc cycle, and no script will have access to it
[21:51:49] <lord2800> and any existing holders won't be able to do anything with it because we'll check the ptr internally, and they can check valid externally
[21:51:50] <CrazyCasta> well, when you say no script will have access, it could hang around as long as the script feels like holding on to it
[21:51:59] <CrazyCasta> they just wouldn't be able to kill themselves w/ it
[21:52:02] <lord2800> yeah
[21:52:26] <lord2800> for all intents and purposes, once the game deletes a UnitAny, any existing UnitAnys that are being held are useless
[21:52:43] <lord2800> and yeah, the goal is a 1:1 mapping of game data:exposed script data
[21:59:03] <lord2800> the d2bs api I'm hoping will be extremely minimal
[21:59:49] <lord2800> and I've mentioned this before, but I'd like to use json and sqlite for configuration (json for things that should affect the core's behavior as a whole, sqlite for things that affect a given script or character or whatnot)
[22:00:09] <lord2800> like for instance, the memory limit would go in json, profiles and script paths would go in sqlite
[22:00:55] <CrazyCasta> well, I don't have a problem w/ the json
[22:01:10] <lord2800> and maybe some day support scripts inside of archives
[22:01:13] <CrazyCasta> but I don't know as much abt the sqlite bit
[22:01:39] <CrazyCasta> I mean, I don't know of an easy utility for editing sqlite dbs basically
[22:01:52] <lord2800> we can make one, or you can use a firefox extension
[22:01:58] <lord2800> it's not very difficult
[22:02:12] <lord2800> and the goal would be to expose all the stuff via some sort of on-screen config anyway
[22:03:06] <CrazyCasta> well, two things, what's the motivation to use sqlite, and second, what about say xml
[22:03:33] <lord2800> the motivation for sqlite would be integration with game managers, and we already have support for it in the core
[22:03:46] <lord2800> xml would require another lib, though that would be reasonable too
[22:03:59] <lord2800> I dunno about the state of any xml libs for C++ though
[22:04:07] <CrazyCasta> ok, I'd like to support XML, and wouldn't have a problem writing w/e code it takes
[22:04:35] <CrazyCasta> I must say I'm w/ you on not knowing the state of XML libs, but there must be some
[22:05:31] <CrazyCasta> what would the reason be for using a different format for the whole core versus just the script specific parts be?
[22:05:33] <lord2800> yeah, at the very least there's libxml2
[22:06:03] <lord2800> well, we could stick everything in sqlite, I just felt it was better to keep it separate so it's clear what affects what
[22:06:15] <CrazyCasta> ok
[22:06:25] <lord2800> the table for core settings would be very small, and very infrequently updated
[22:06:36] <CrazyCasta> well, what I was thinking is, if we used xml, you could have all the core specific stuff in one element, and everything else in another
[22:07:15] <CrazyCasta> also, it would be nice if we could get the scripts to use the xml (probably via some sort of api)
[22:07:31] <CrazyCasta> so that their configuration is tied to a specific profile
[22:07:46] <CrazyCasta> so you could have multiple profiles for the same char w/ different configs
[22:07:48] <lord2800> oh yes, there's going to be a configuration api
[22:07:54] <lord2800> it's going to be tied into the game menu stuff
[22:08:11] <lord2800> that way you can edit your configuration by hitting esc and selecting options and whatnot
[22:08:34] <lord2800> kinda like editing hotkeys or the sound options
[22:09:01] <CrazyCasta> oh, like ntbot has
[22:09:11] <lord2800> yeah, except native to the game
[22:09:20] <lord2800> rather than built on screenhooks
[22:09:36] <CrazyCasta> hmm, ok
[22:09:55] <CrazyCasta> seems like that might be modifying the game's structure just a fair bit more than usual :P
[22:10:02] <lord2800> (someone was generous enough to post the ptrs and structs for all that)
[22:36:21] <lord2800> the good thing about a design like this for the core would be that the only updates would be if we add new features via new apis or upgrade spidermonkey, or in the rare case that we discover that our thoughts about what is valid data for a given function aren't true
[22:41:21] <lord2800> hrm... script ipc
[22:41:29] <lord2800> I'm not sure it's necessary if we have named pipes
[23:02:00] <alogwe> this all sounds really awesome, i don't understand a lot of stuff about it to appreciate it as much but it sounds great =)
[23:02:18] <lord2800> as soon as I've had a chance to discuss this with you, alogwe, I'm gonna summarize this and put it on the wiki
[23:02:35] <lord2800> what's unclear?
[23:03:11] <lord2800> if it's unclear to you, it's likely going to be unclear to others too
[23:04:08] <alogwe> well i think i get the basic idea of what you were saying but i didn't know enough about the core in it's current state to know how doing things described above is that much different
[23:04:17] <lord2800> ah, ok
[23:04:27] <alogwe> aside from the mentioned results (the 1:1 mapping of game data/d2bs data)
[23:04:45] <alogwe> lets just say reading over that is the first time i've ever seen anything about UnitAny lol
[23:04:46] <lord2800> right now we do a whole heck of a lot of work "under the hood" to verify stuff and make sure that you're not going to crash the game and parsing constants and whatnot
[23:04:58] <alogwe> and i don't know exactly what a pointer is or struct or how that all works :P so
[23:05:05] <alogwe> nothing you can really teach me in a sitting haha
[23:05:11] <lord2800> we want to keep the not crashing the game stuff, but we want to get rid of the parsing constants and other stuff
[23:05:19] <lord2800> to make the api as lightweight as possible
[23:05:40] <alogwe> okay
[23:09:44] <lord2800> basically, instead of exposing clickMap, we expose Game.D2Client.ClickMap(x, y)
[23:09:52] <lord2800> well, that's kind of a bad example
[23:10:10] <lord2800> instead of exposing clickItem, we expose ClickItemLeft, ClickItemRight, ClickMercItem, etc.
[23:10:30] <alogwe> those are the native d2 functions?
[23:10:31] <lord2800> and instead of doing any sort of processing and turning parameters into something useful, we just directly pass them in
[23:10:32] <lord2800> yes
[23:11:16] <alogwe> and you use the rooting/valid flag to keep it from crashing and throw an exception instead (or error or w/e)
[23:11:28] <lord2800> yeah

Handling properties:
[05:13:02pm]    use a series of getters/setters, each one knows how to convert from and to the appropriate type
[05:13:10pm]    the jsid tells us the offset
[05:13:21pm]    the private data tells us what the base is
[05:14:45pm]    so the properties for Unit would look like: {"gid", 0, JSPROP_whatever, readDWORD}, {"type", 4, JSPROP_whatever, readSHORT}, etc.
[05:15:26pm]    where readDWORD takes the 0, adds it to the private data stored in the object, and reads off 4 bytes and converts it to a jsval of type integer
[05:15:55pm]    and readSHORT takes the 4, adds it to the private data, reads off 2 bytes and converts it to a jsval of type integer too
[05:11:31pm]     <lord2800>     hmm
[05:11:49pm]     I wonder if it'd be possible to build a static type map
[05:12:42pm]     oh fuck, I got it
[05:13:02pm]     a series of getters/setters, each one knows how to convert from and to the appropriate type
[05:13:10pm]     the jsid tells us the offset
[05:13:21pm]     the private data tells us what the base is
[05:14:45pm]     so the properties for Unit would look like: {"gid", 0, JSPROP_whatever, readDWORD}, {"type", 4, JSPROP_whatever, readSHORT}, etc.
[05:15:26pm]     where readDWORD takes the 0, adds it to the private data stored in the object, and reads off 4 bytes and converts it to a jsval of type integer
[05:15:55pm]     and readSHORT takes the 4, adds it to the private data, reads off 2 bytes and converts it to a jsval of type integer too

Object Creation/Destruction
[12:09:01pm]    <joder-8D1>    okay lord2800
[12:09:03pm]    6FD8C918 6A 00 PUSH 0
    6FD8C91A 68 C1010000 PUSH 1C1
    6FD8C91F 68 4031DE6F PUSH D2Common.6FDE3140 ; ASCII "..\Source\D2Common\COLLISN\Collisn.cpp"
[12:09:04pm]    6FD8C924 8BCE MOV ECX,ESI
    6FD8C926 E8 FDC8FCFF CALL <JMP.&Fog.#10046>
[12:09:07pm]    FOG.10046
[12:09:13pm]    <joder-8D1>    occurs to he the free function
[12:09:14pm]    of fog
[12:09:20pm]    you can identify objects by teh pushed string
[12:09:23pm]    altho I dont recommend that
[12:11:37pm]    <joder-8D1>    Fog.10046 is the free function
[12:11:39pm]    <joder-8D1>    it's __fastcall
[12:12:52pm]    <joder-8D1>    however lord2800, if you hook Fog.10046
[12:12:59pm]    <joder-8D1>    you know when a object is being freed
[12:13:17pm]    I rekon you have a list of all objects you'd love to free
[12:13:20pm]    so you can just store its address
[12:13:26pm]    <lord2800>    I was just thinking the same thing
[12:13:55pm]    <lord2800>    store jsvals in a std::map<uint32, jsval> and look up things that just got free'd by that