work in progress libraries are "client" and "server" stuff in both is also put in "common" note, behaviour might be subtly different all files must use "/" as a path separator (Unix Master Race) valid characters are listed here (ignoring the path separator): -.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz anything else is invalid and will just be outright rejected furthermore, no paths will be accepted where a . follows a / this means that hidden files on unixlikes will not be accepted! files that are meant to be intercepted should be prefixed with a * e.g. "*thismap" maximum path length is 128 stuff that's actually implemented will be marked with an @ lua base library stuff: math.* @ string.* @ pcall @ error @ print @ loadstring @ loadfile @ (TODO: filter the path) dofile @ (TODO: filter the path) nothing else yet (TODO: stop leaking the whole base library) check http://www.lua.org/manual/5.1/ for more info on these client/server.hook_tick = fn(sec_curtime, sec_delta)->sec_wait @ sets a hook called every "tick" returns a number telling it how long it wants to wait for "sec_curtime" is the current time elapsed from the start "sec_delta" is the time elapsed from the start of the last call to the hooked function setting this to nil will quit your game NOTE: DO NOT USE COMMON FOR THIS HOOK! (only client/server is accepted) client/server.hook_file = fn(ftype, fname, clisock)->object sets a hook to intercept networked file requests "clisock" is the socket pertaining to the file request can return nil to cancel the request can return true to perform the default request NOTE: DO NOT USE COMMON FOR THIS HOOK! (only client/server is accepted) client.hook_render = fn() @ sets a hook called every frame this is the only place where it is safe to render stuff such as models and HUDs and whatnot client.hook_key = fn(key, state) @ sets a hook called every time a key changes state is either true or false client.hook_mouse_button = fn(button, state) @ sets a hook called every time a mouse button changes state is either true or false client.hook_mouse_motion = fn(x, y, dx, dy) @ sets a hook called every time the mouse is moved x, y are the current position dx, dy are the delta positions you will probably use the latter pair if the mouse is "locked" as x, y are not defined the same on all platforms! client.mouse_lock_set(state) @ locks / unlocks the mouse depending on "state" client.mouse_visible_set(state) @ shows / hides the mouse depending on "state" map = common.map_load(fname, fmt = "auto") loads a map, either .vxl or some format we might invent which will probably be .vxl with our own header + changed meaning for the 4th colour byte map = common.map_new(lx, ly, lz) creates a new map note, ly is the *height* of the new map also all dimensions must be powers of two, otherwise this will fail horribly! this will throw a lua error if it fails. common.map_set(map) sets the "current" map to "map" note, "map" can be nil to disable rendering anything common.map_save(map, fname, fmt = "icemap") saves a map to a file this will throw a lua error if it fails. r, g, b, dist = client.map_fog_get() @ gets the current fog colour / distance client.map_fog_set(r, g, b, dist) @ sets the current fog colour / distance lx, ly, lz = common.map_get_dims() @ gets the map's dimensions these will be nil if there is no map loaded table = common.map_pillar_get(px, pz) @ returns a full pillar of data, skipping the total size header this will be nil if there is no map loaded note, the data wraps around here (wrt px,pz)! common.map_pillar_set(px, pz, table) @ sets a full pillar of data this will be nil if there is no map loaded the data is checked before setting, and will throw a lua error if it fails. note, the data wraps around here (wrt px,pz)! WARNING: You MUST update the side pillars in your code! You MUST ALSO fill in the newly-exposed blocks, as well as remove the newly-unexposed blocks! Otherwise, there WILL be gaps! WE'RE NOT DOING IT FOR YOU! client.camera_point(dx, dy, dz, zoom = 1.0, roll = 0.0) @ points the camera in a direction with zoom factor "zoom" and roll "roll" (in radians, sorry) client.camera_move_local(dx, dy, dz) @ moves the camera in the camera-local direction (dx,dy,dz) client.camera_move_global(dx, dy, dz) @ moves the camera in the world direction (dx,dy,dz) client.camera_move_to(px, py, pz) @ moves the camera to the world position (px,py,pz) px, py, pz = client.camera_get_pos() @ gets the camera's position dx, dy, dz = client.camera_get_forward() @ gets the camera's forward vector pmf = common.model_new(bonemax = 5) @ creates a new model remember to free it when you're done as this is only a light userdata "bonemax" is the initial maximum number of "bones" this model can have initially useful if you know exactly how many you'll need currently the number of bones is limited to 256 pmf = common.model_load_pmf(fname) @ loads a pmf from a file remember to free it when you're done as this is only a light userdata limits of bones / points still applies here; files which exceed these WILL be rejected! returns nil on failure. success = common.model_save_pmf(pmf, fname) @ saves a pmf to a file common.model_free(pmf) @ free the given model if you don't do this then it's memoryleaktopia (plus i'm allowed to kill you) TODO: clean up all models on game kill len = common.model_len(pmf) @ get the number of bones in this model pmf, boneidx = common.model_bone_new(pmf, ptmax = 20) @ creates a new bone "ptmax" is the initial maximum number of "points" this bone can have initially useful if you know exactly how many you'll need currently the number of points is limited to 4096 WARNING: YOU *MUST* TAKE THE pmf VALUE RETURNED AND *NOT* USE THE OLD ONE ANY LONGER! this is because realloc() is called on this dynamic list and it can seriously crash badly JUST SAYING common.model_bone_free(pmf, boneidx) @ removes a bone from the model name, table = common.model_bone_get(pmf, boneidx) @ gets a table with every point in the given bone each entry in the table has the following keys: uint16_t radius; // fixed point 8.8 int16_t x,y,z; // fixed point 8.8 uint8_t r,g,b; the reserved field of each point is inaccessible from this API common.model_bone_set(pmf, boneidx, name, table) @ replaces the bone's contents with that in the table note, bones will be rejected if: - name is > 15 chars long - radius,x,y,z,r,g,b are missing - 0 <= radius < 65536 fails - -32768 <= x,y,z < 32768 fails - 0 <= r,g,b < 256 fails these exceptions will throw a lua error boneidx = common.model_bone_find(pmf, name) @ finds the first bone with the given name note, this is case sensitive if it cannot be found, this returns nil client.model_render_bone_global(pmf, boneidx, px, py, pz, ry, rx, ry2, scale) @ renders a bone at world position (px,py,pz), rotated around Y by "ry" radians, then around X by "rx" radians, then around Y by "ry2" radians, and scaled "scale" times client.model_render_bone_local(pmf, boneidx, px, py, pz, ry, rx, ry2, scale) @ renders a bone at camera-local position (px,py,pz), rotated around Y by "ry" radians, then around X by "rx" radians, then around Y by "ry2" radians, and scaled "scale" times width, height = client.screen_get_dims() @ gets the dimensions of the screen img, width, height = common.img_load(fname) @ loads an image with filename "fname" remember to free it when you're done as this is only a light userdata if this fails, img, width, height will all be nil common.img_free(img) @ free the given image if you don't do this then it's memoryleaktopia (plus i'm allowed to kill you) width, height = common.img_get_dims(img) @ gets the image's dimensions client.img_blit(img, dx, dy, width = iwidth, height = iheight, sx = 0, sy = 0, color = 0xFFFFFFFF) @ blits an image onto screen position dx, dy "color" indicates a base 0xAARRGGBB colour to use this is clipped to fit! #