Last active
December 13, 2016 18:28
-
-
Save warmist/753a2444bbe287efa59615913de3f433 to your computer and use it in GitHub Desktop.
Work in progress
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- this requires a plugin that draws the map: https://github.com/warmist/dfhack/tree/twbt_experiments | |
--[[ | |
Ideas for future: | |
microtransactions (for rooms and stuff :D) jkjk | |
assignment to locations (e.g. performance etc) | |
see if idle location can be used for direct dwarf control | |
more info about dwarf | |
possesions (with a way to add/remove them) | |
rooms | |
artifacts | |
weapons etc... | |
thoughts | |
maybe add a way to modify thoughts? | |
cheats and hacks like: | |
make a dwarf punch someone | |
teleport for stuck dwarves | |
arena mode fights (buy stuff for dwarf and see it battle) | |
]] | |
local sock=require 'plugins.luasocket' | |
local map=require 'plugins.screenshot-map' | |
local utils=require 'utils' | |
local args={...} | |
if DEBUG then | |
printd=function ( ... ) | |
print(...) | |
end | |
else | |
printd=function ()end | |
end | |
if port and (args[1]=="-r" or args[1]=="-s") then | |
port:close() | |
port=nil | |
end | |
if timeout_looper then | |
dfhack.timeout_active(timeout_looper,nil) | |
end | |
if args[1]=="-s" then | |
print("Shutting down") | |
for k,v in pairs(clients) do | |
k:close() | |
end | |
return | |
end | |
users=users or {} | |
port=port or sock.tcp:bind("192.168.1.157",6666) | |
port:setNonblocking() | |
local clients={} | |
function get_window(x,y,z,w,h ) --maybe a fallback method? | |
local ret={} | |
local s=df.global.gps.screen | |
local ww=df.global.gps.dimx | |
local wh=df.global.gps.dimy | |
local i=0 | |
for yy=y,y+h-1 do | |
for xx=x,x+w-1 do | |
local t=xx*wh+yy | |
for j=0,3 do | |
ret[i]=s[t*4+j] | |
i=i+1 | |
end | |
end | |
end | |
return ret | |
end | |
function pick_target() | |
local u=df.global.world.units.active | |
local ret | |
local count=0 | |
while (ret==nil or not dfhack.units.isCitizen(ret)) and count<100 do | |
ret=u[math.random(0,#u-1)] | |
count=count+1 | |
end | |
return ret | |
end | |
local HTML_HEAD=[==[<html><head><meta charset="utf-8"/><style> | |
body{ | |
font-family: monospace; | |
background-color: #000000; | |
margin:0px; | |
color: #FF0000; | |
}</style></head><body>]==] | |
local HTML_END="</body></html>" | |
function unit_info(user, u ) | |
local uname=dfhack.df2utf(dfhack.TranslateName(u.name)) | |
local prof=dfhack.units.getProfessionName(u) | |
local job | |
if u.job.current_job then | |
job=dfhack.job.getName(u.job.current_job) | |
else | |
job="no job" | |
end | |
local ret=string.format('<div class="unit">%s (%s)</div><div class="job"> %s</div><div class="labors"> Labors:<ul>',uname,prof,job) | |
for i,v in ipairs(u.status.labors) do | |
if df.unit_labor.attrs[i].caption~=nil then | |
local num=1 | |
if v then | |
num=0 | |
end | |
ret=ret..string.format("<li>%s : <a href='%s?labor=%d:%d'>%s</a></li>",df.unit_labor.attrs[i].caption, | |
user.name,i,num,v) | |
end | |
end | |
ret=ret..'</ul>\n' | |
ret=ret..'<div class="labors"> Burrows:<ul>' | |
for i,v in ipairs(df.global.ui.burrows.list) do | |
local in_burrow_text="add" | |
local in_burrow_state=1 | |
if dfhack.burrows.isAssignedUnit(v,u) then | |
in_burrow_text="remove" | |
in_burrow_state=0 | |
end | |
ret=ret..string.format("<li>%s : <a href='%s?burrow=%d:%d'>%s</a></li>",v.name, | |
user.name,v.id,in_burrow_state,in_burrow_text) | |
end | |
ret=ret.."</ul>\n"; | |
return ret | |
end | |
function respond_map(user) | |
local ret=HTML_HEAD | |
local S=[===[ | |
<canvas id="canvas" width="!!canvas_w!!" height="!!canvas_h!!"></canvas><br> | |
<img id="tilesheet" src="http://i.imgur.com/fUGSAWC.png" alt="tilesheet" style="display: none;"> | |
<script> | |
var c = document.getElementById("canvas"); | |
var ctx = c.getContext("2d"); | |
var spr=document.getElementById("tilesheet"); | |
var tile_x=16; | |
var tile_y=16; | |
var canvas_tile_count=!!size!!; | |
var map=[!!map!!]; | |
var color_map=[[0,0,0],[0,0,128],[0,128,0],[0,128,128], | |
[128,0,0],[128,0,128],[128,128,0],[192,192,192], | |
[128,128,128],[0,0,255],[0,255,0],[0,255,255], | |
[255,0,0],[255,0,255],[255,255,0],[255,255,255]]; | |
function color(id){ | |
var c=color_map[id] | |
return "rgb("+c[0]+","+c[1]+","+c[2]+")"; | |
} | |
function draw_bg( x,y,bg ){ | |
ctx.fillStyle=color(bg); | |
ctx.fillRect(x*tile_x,y*tile_y,tile_x,tile_y); | |
} | |
function draw_tile( x,y,tile){ | |
var sx=tile%16; | |
var sy=Math.floor(tile/16); | |
ctx.drawImage(spr,sx*tile_x,sy*tile_y,tile_x,tile_y,x*tile_x,y*tile_y,tile_x,tile_y); | |
} | |
function color_tiles( x,y,fg,bright ){ | |
ctx.fillStyle=color(fg+bright*8); | |
ctx.fillRect(x*tile_x,y*tile_y,tile_x,tile_y); | |
} | |
function draw_map(){ | |
ctx.globalCompositeOperation="source-over"; | |
for(var x=0;x<canvas_tile_count;x++) | |
for(var y=0;y<canvas_tile_count;y++) | |
{ | |
var t=map[x+y*canvas_tile_count] | |
draw_tile(x,y,t[0]); | |
} | |
ctx.globalCompositeOperation="source-atop"; | |
for(var x=0;x<canvas_tile_count;x++) | |
for(var y=0;y<canvas_tile_count;y++) | |
{ | |
var t=map[x+y*canvas_tile_count] | |
color_tiles(x,y,t[1],t[3]); | |
} | |
ctx.globalCompositeOperation="destination-over"; | |
for(var x=0;x<canvas_tile_count;x++) | |
for(var y=0;y<canvas_tile_count;y++) | |
{ | |
var t=map[x+y*canvas_tile_count] | |
draw_bg(x,y,t[2]); | |
} | |
} | |
draw_map(); | |
</script> | |
]===] | |
local t=df.unit.find(user.unit_id)--df.global.world.units.active[unit_id]--pick_target() | |
local w=15 | |
local m=map.render_map_rect(t.pos.x-w//2-1,t.pos.y-w//2-1,t.pos.z,w,w) | |
local line="" | |
local map_string="" | |
--local skip_first=false | |
for i=0,#m,4 do | |
--if not skip_first then --temp fix because render map returns one img too little? | |
if m[i]~=0 then | |
line=line..string.char(m[i]) | |
else | |
line=line..' ' | |
end | |
map_string=map_string..string.format("[%d, %d, %d, %d],",m[i],m[i+1],m[i+2],m[i+3]) | |
--end | |
--skip_first=false | |
if #line==w then | |
--ret=ret..dfhack.df2utf(line).."<br>\n" | |
line="" | |
map_string=map_string.."\n" | |
--skip_first=true | |
end | |
end | |
local valid_variables={ | |
map=map_string, | |
size=w, | |
canvas_w=w*16, | |
canvas_h=w*16, | |
} | |
function replace_vars( v ) | |
local vname=v:sub(3,-3) | |
return tostring(valid_variables[vname]) | |
end | |
ret=ret..S:gsub("(!![^!]+!!)",replace_vars) | |
ret=ret..unit_info(user,t) | |
ret=ret..HTML_END | |
return ret | |
end | |
function respond_new_user( username ) | |
local unit=pick_target() | |
users[username]={unit_id=unit.id,name=username} | |
print("New user:"..username) | |
return string.format("%s You were assigned unit: %s (%d). %s", | |
HTML_HEAD,dfhack.df2utf(dfhack.TranslateName(unit.name)),unit.id,HTML_END) | |
end | |
function respond_err() | |
return HTML_HEAD.. "Enter username after slash to register/play. Try host/name?help for list of commands"..HTML_END | |
end | |
function respond_help() | |
local r="" | |
local choices={ | |
{"help","Print this help"}, | |
{"new_unit","Assign a new random unit"}, | |
{"labor=id:value","Set labor on or off"}, | |
{"burrow=id:value","Add or remove from burrow"}, | |
{"delete","deletes all user data"}, | |
} | |
for i,v in ipairs(choices) do | |
r=r..string.format("<li>%s : %s</li>\n",v[1],v[2]) | |
end | |
return string.format("%s <ul> %s </ul>%s",HTML_HEAD, r ,HTML_END) | |
end | |
function starts_with( s,prefix ) | |
return s:sub(1,#prefix)==prefix | |
end | |
function switch_labor(user,labor,value ) | |
labor=tonumber(labor) | |
value=tonumber(value) | |
local u=df.unit.find(user.unit_id) | |
if u.status.labors[labor]~=nil then | |
u.status.labors[labor]=value | |
end | |
end | |
function switch_burrow( user,burrow,value ) | |
burrow=tonumber(burrow) | |
value=tonumber(value) | |
local u=df.unit.find(user.unit_id) | |
local b=df.burrow.find(burrow) | |
if u and b then | |
dfhack.burrows.setAssignedUnit(b,u,value==1) | |
end | |
end | |
function perform_commands(user, cmd ) | |
if cmd=="new_unit" then | |
print("New unit for user:",user.name) | |
local unit=pick_target() | |
user={unit_id=unit.id} | |
elseif cmd=="help" then | |
return respond_help() | |
elseif starts_with(cmd,"labor=") then | |
switch_labor(user,cmd:match("labor=([^:]+):([01])")) | |
elseif starts_with(cmd,"burrow=") then | |
switch_burrow(user,cmd:match("burrow=([^:]+):([01])")) | |
elseif cmd=="delete" then | |
print("Deleting user:",user.name) | |
users[user.name]=nil | |
return HTML_HEAD.. "User deleted" .. HTML_END | |
end | |
end | |
function responses(request,cmd) | |
if users[request] then | |
local r=perform_commands(users[request],cmd) | |
if r then | |
return r | |
end | |
return respond_map(users[request]) | |
elseif request~=nil and request~='' then | |
return respond_new_user(request) | |
else | |
printd("Request:",request) | |
printd("cmd:",cmd) | |
return respond_err() | |
end | |
end | |
function parse_request( client ) | |
local s=client:receive() | |
if s==nil then | |
return false | |
end | |
printd(s) | |
local path,other=s:match("GET /([^ ?]*)([^ ]*)") | |
printd("CON:",path,other) | |
if other and other~="" then other=other:sub(2):gsub("%%20"," ") end | |
while s do | |
s=client:receive() | |
end | |
return true,path,other | |
end | |
function poke_clients() | |
local removed_entries={} | |
for k,v in pairs(clients) do | |
local ok,req,cmd=parse_request(k) | |
if ok then | |
local r=responses(req,cmd) | |
k:send(string.format("HTTP/1.0 200 OK\r\nConnection: Close\r\nContent-Length: %d\r\n\r\n%s",#r,r)) | |
k:close() | |
removed_entries[k]=true | |
end | |
end | |
for k,v in pairs(removed_entries) do | |
clients[k]=nil | |
end | |
end | |
function accept_connections( ) | |
while port:select(0,1) do | |
local c=port:accept() | |
--print("Opened Connection") | |
clients[c]=true | |
c:setNonblocking() | |
end | |
end | |
function event_loop() | |
accept_connections() | |
poke_clients() | |
timeout_looper=dfhack.timeout(10,'frames',event_loop) | |
end | |
event_loop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment