Advertisement
cracker64

TPT Multi

Aug 12th, 2012
1,232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 33.19 KB | None | 0 0
  1. --Cracker64's Lua Multiplayer Script
  2. --See forum post http://powdertoy.co.uk/Discussions/Thread/View.html?Thread=14352 for more info
  3. --VER 1.1 UPDATE http://pastebin.com/raw.php?i=33mxQcvW
  4.  
  5. --Version 1.1
  6.  
  7. --TODO's
  8. -- = key, pressure/velocity reset
  9. --CAPS_MODE, replace mode (for build 185+)
  10. --More work on multi-line chat
  11. --Line tool is still off slightly
  12. --Hacky method for PROP (read particle before it runs, check for a change after)
  13.  
  14. --These features are impossible (in v81), don't suggest them, even though they would be great
  15. --load a save/stamp simultaneously
  16. --sync view mode, gravity/wind modes
  17. --signs, STKM controls
  18. --AIR/VAC , WIND, PGRV/NGRV. no pressure,velocity,gravity get functions
  19. --Deco editor (script doesn't run there)
  20.  
  21. --don't send empty lines in chat
  22. --multiple lines in chat, up to 5(needs more work, optimizations) v1.1.0
  23. --floodfill delete while holding
  24. --ESC key leaves chatbox_focus
  25. --function to add data handlers so other scripts can add on functions
  26. --Hopefully fixed altgr key v1.0.9
  27. --Interface flashes a bit after a disconnect --FIXED
  28. --some keys enter spaces in chat --FIXED
  29. --different language keyboard support --just Finnish right now, taking requests for others.
  30. --WL_STREAM draws a bit too much --FIXED
  31. --Drawing on CLNE and such sets ctype --Use a small brush 8 radius or smaller v1.0.8
  32. --Block a few elements/tools from sending and notify
  33. --Zoom window, yes, you can now use the zoom whenever and however you want, pixel art and electronics fans rejoice v1.0.7
  34. --Floodfill ONLY with erase tool --v1.0.6
  35. --I broke right click, my bad --FIXED v1.0.5
  36. --HEAT/COOL are now perfect (but still laggy)
  37. --FULL BRUSH SUPPORT, triangle,square,circle,ovals. mouse wheel changing(if using build 185 or higher) v1.0.4
  38. --version check (notify if other person is higher) v1.0.3
  39. --GoL elements besides first don't work and cause errors FIXED v1.0.2
  40. --cursor (flash?) in chat box that moves (delete key) DONE v1.0.1
  41. --connect command from chat window --DONE
  42. --need better chat entering, and general looks--DONE
  43. --chat box DONE
  44. --Walls --DONE
  45. --FIGH and LIGH should only spawn once per click -FIXED
  46. --Energy particles spawning too much --FIXED
  47.  
  48. loader,msg = package.loadlib("luasocket.dll","luaopen_socket_core") --this is the socket core dll, a few shortcut helper scripts are missing. If you want those get the full lua socket download
  49. if loader then loader() else socket=require("socket") end --try loading normal location for socket
  50.  
  51. local PORT = 3000 --Change 3000 to your desired port
  52.  
  53. local KEYBOARD = 1 --only change if you have issues. Only other option right now is 2(finnish).
  54. local tcp = nil
  55. local version = 110
  56. local otherversion = 0
  57. local tptversion = tpt.version.build
  58. local usenewbrush = tptversion>=185
  59. local serverclient = nil
  60. local client = nil
  61. local lastpacket = os.clock()
  62. local lastpsent = 0
  63. local lastping = 0
  64. local pingtimer = 0
  65. local waitingforpong = false
  66. local pingtext = ""
  67. local sleft = 1 local sright = 0 --local salt=0 --for replace_mode
  68. local myleft = 1 local myright = 0 --local myalt=0
  69. local lastmx = 0 local lastmy = 0
  70. local lastsent = ""
  71. local statustext = ""
  72. local infotext = ""
  73. local infoalpha = 0
  74. local otheruser = ""
  75. local mybrx = 2 local mybry = 2
  76. local otherbrx = 2 local otherbry = 2
  77. local mybrushmode = 0 --0 circle, 1 square, 2 tri
  78. local otherbrushmode = 0
  79. local kmod = 0
  80. local startx = 0 local starty = 0
  81. local releasetype = 0
  82. local pausenextframe = false
  83. local datasent = 0
  84. local sendbuffer = 0.0167
  85. local otherfps = 60 local myfps = 60
  86. local fpstime = os.clock()
  87. local fpstimer = 0
  88. local fpscapped = false
  89. local init = true
  90.  
  91. local chatbox_hidden = false
  92. local chatbox_messages = {}
  93. local chatbox_focus = false
  94. local chatbox_textbox = ""
  95. local chatbox_newmessage = false
  96. local chatbox_cursorpos = 0
  97. local wheel = 0
  98.  
  99. local ZSIZE = 16
  100. local ZFACTOR = math.floor(256/ZSIZE)
  101. local zoom_en = 0
  102. local zoom_x = math.floor((612-ZSIZE)/2)
  103. local zoom_y = math.floor((384-ZSIZE)/2)
  104. local zoom_wx = 0
  105. local zoom_wy = 0
  106. local zoom_trig = 0
  107.  
  108. local GoLrule = {{0,0,0,0,0,0,0,0,0,2},{0,0,1,3,0,0,0,0,0,2},{0,0,1,3,0,0,2,0,0,2},{0,0,0,2,3,3,1,1,0,2},{0,1,1,2,0,1,2,0,0,2},{0,0,0,3,1,0,3,3,3,2},{0,1,0,3,0,3,0,2,1,2},{0,0,1,2,1,1,2,0,2,2},{0,0,1,3,0,2,0,2,1,2},{0,0,0,2,0,3,3,3,3,2},{0,0,0,3,3,0,0,0,0,2},{0,0,0,2,2,3,0,0,0,2},{0,0,1,3,0,1,3,3,3,2},{0,0,2,0,0,0,0,0,0,2},{0,1,1,3,1,1,0,0,0,2},{0,0,1,3,0,1,1,3,3,2},{0,0,1,1,3,3,2,2,2,2},{0,3,0,0,0,0,0,0,0,2},{0,3,0,3,0,3,0,3,0,2},{1,0,0,2,2,3,1,1,3,2},{0,0,0,3,1,1,0,2,1,4},{0,1,1,2,1,0,0,0,0,3},{0,0,2,1,1,1,1,2,2,6},{0,1,1,2,2,0,0,0,0,3},{0,0,2,0,2,0,3,0,0,3}}
  109. --get different lists for other language keyboards
  110. local keyboardshift = { {before=" qwertyuiopasdfghjklzxcvbnm1234567890-=.,/`|;'[]\\",after=" QWERTYUIOPASDFGHJKLZXCVBNM!@#$%^&*()_+><?~\\:\"{}|",},{before=" qwertyuiopasdfghjklzxcvbnm1234567890+,.-'´¨<",after=" QWERTYUIOPASDFGHJKLZXCVBNM!\"#¤%&/()=?;:_*`^>",} }
  111. local keyboardaltrg = { {nil},{before=" qwertyuiopasdfghjklzxcvbnm1234567890+,.-'¨<",after=" qwertyuiopasdfghjklzxcvbnm1@£$€6{[]}\\,.-'~|",},}
  112.  
  113. function shift(s)
  114. if keyboardshift[KEYBOARD]~=nil then
  115. return (s:gsub("(.)",function(c)return keyboardshift[KEYBOARD]["after"]:sub(keyboardshift[KEYBOARD]["before"]:find(c,1,true))end))
  116. else return s end
  117. end
  118. function altgr(s)
  119. if keyboardaltgr[KEYBOARD]~=nil then
  120. return (s:gsub("(.)",function(c)return keyboardaltgr[KEYBOARD]["after"]:sub(keyboardaltgr[KEYBOARD]["before"]:find(c,1,true))end))
  121. else return s end
  122. end
  123. local energytypes = { [18]=true, [31]=true, [136]=true, }
  124. local validwalls = { [222]=true, [223]=true, [224]=true, [225]=true, [227]=true, [228]=true, [229]=true, [230]=true, [231]=true, [232]=true, [233]=true, [234]=true, [235]=true, [240]=true, [242]=true, [245]=true, }
  125. local tools = { [236]=true, [237]=true, [238]=true, [239]=true, }
  126. local disabled = { [226]=true,[236]=true,[239]=true,[241]=true,[243]=true,[244]=true,[246]=true,}
  127. local setctype = { [9]=true,[74]=true,[83]=true,[85]=true,[93]=true,[153]=true,}
  128.  
  129. function step()
  130. if init then init=false onstartup() end
  131. local currenttime = os.clock()
  132. tpt.drawtext(240,10,statustext,255,255,0)
  133. tpt.drawtext(135,10,"Data sent: "..datasent)
  134. tpt.drawtext(85,10,pingtext)
  135.  
  136. if infoalpha > 0 then tpt.drawtext(240,20,infotext,255,255,255,infoalpha) infoalpha = infoalpha-5 end
  137. if tpt.get_name() == "" then statustext = "You need to login first" end --return end
  138. if pausenextframe then pausenextframe=false tpt.set_pause(1) end
  139. --check for new connections
  140. if serverclient == nil and client == nil then
  141. statustext = "Waiting... or type '/c ip port' right in here! \\/"
  142. serverclient, err = tcp:accept()
  143. if serverclient~= nil then serverclient:settimeout(0)
  144. statustext = "Got a connection..." tpt.set_pause(1) clearsim() lastpacket=os.clock() chatbox_messages = {}
  145. send("n " .. tpt.get_name() .. "|clear|" .. "pause 1|" .. "s " .. myleft .. " " .. myright .. "|b "..mybrx.." ".. mybry.." "..mybrushmode.. "|ver " ..version)--send name,clear and pause,version
  146. end
  147. end
  148. --check streams for data
  149. if serverclient~=nil then
  150. data, err = serverclient:receive('*l')
  151. if data~=nil then readdata(data) end
  152. elseif client~=nil then
  153. data, err = client:receive('*l')
  154. if data~=nil then readdata(data) end
  155. end
  156. --timeout/ping
  157. if (serverclient~=nil or client~=nil) then
  158. local timeout = currenttime-lastpacket
  159. local pingtimeout = currenttime-lastping
  160. if timeout>15 then
  161. if serverclient ~= nil then serverclient:close() serverclient=nil end
  162. if client ~= nil then client:close() client=nil end
  163. infotext = "Lost connection to " .. otheruser infoalpha = 255
  164. otheruser = "" pingtext = ""
  165. end
  166. if pingtimeout>2 then
  167. lastping = currenttime
  168. send("ping")
  169. end
  170. end
  171. --update brush selections
  172. if myleft~=tpt.selectedl or myright~=tpt.selectedr then
  173. myleft = tpt.selectedl
  174. myright = tpt.selectedr
  175. send("s " .. myleft .. " " .. myright)
  176. end
  177. --new brush size sync
  178. if usenewbrush and (mybrx~=tpt.brushx or mybry~=tpt.brushy) then
  179. mybrx = tpt.brushx
  180. mybry = tpt.brushy
  181. send("b " .. mybrx .. " " .. mybry)
  182. end
  183. --fps sync
  184. if fpstimer>=60 then
  185. fpstimer = 0
  186. myfps = math.floor(60/(currenttime-fpstime))
  187. fpstime = currenttime
  188. send("fps " .. myfps)
  189. end
  190. fpstimer = fpstimer + 1
  191. if otheruser~="" then tpt.drawtext(16,27,otheruser .. " FPS: " .. otherfps) end
  192.  
  193. update_chatbox()
  194.  
  195. send("")--try sending buffer
  196. end
  197.  
  198. function onstartup()
  199. tcp = socket.bind("*",PORT,0)
  200. tcp:settimeout(0)
  201. end
  202. --some luasocket shortcuts
  203. function socket.bind(host, port, backlog)
  204. local sock, err = socket.tcp()
  205. if not sock then return nil, err end
  206. sock:setoption("reuseaddr", true)
  207. local res, err = sock:bind(host, port)
  208. if not res then return nil, err end
  209. res, err = sock:listen(backlog)
  210. if not res then return nil, err end
  211. return sock
  212. end
  213. function socket.connect(address, port, laddress, lport)
  214. local sock, err = socket.tcp()
  215. if not sock then return nil, err end
  216. if laddress then
  217. local res, err = sock:bind(laddress, lport, -1)
  218. if not res then return nil, err end
  219. end
  220. local res, err = sock:connect(address, port)
  221. if not res then return nil, err end
  222. return sock
  223. end
  224.  
  225. local datahandlers = {
  226. b = function(words) otherbrx=tonumber(words[2]) otherbry=tonumber(words[3]) if words[4]~=nil then otherbrushmode=tonumber(words[4]) end end,
  227. d = function(words) --draw left click
  228. local n = tonumber(words[2])
  229. x = n%1024
  230. y = math.floor(n/1024)
  231. if tonumber(words[3])~=nil then
  232. drawstuff(x,y,otherbrx,otherbry,sleft,true,otherbrushmode)
  233. else
  234. create_line(lastmx,lastmy,x,y,otherbrx,otherbry,sleft,otherbrushmode)
  235. end
  236. lastmx = x
  237. lastmy = y end,
  238. r = function(words)
  239. local n = tonumber(words[2])
  240. x = n%1024
  241. y = math.floor(n/1024)
  242. if tonumber(words[3])~=nil then
  243. drawstuff(x,y,otherbrx,otherbry,sright,true,otherbrushmode)
  244. else
  245. create_line(lastmx,lastmy,x,y,otherbrx,otherbry,sright,otherbrushmode)
  246. end
  247. lastmx = x
  248. lastmy = y end,
  249. l = function(words) --line left
  250. create_line(tonumber(words[2]),tonumber(words[3]),tonumber(words[4]),tonumber(words[5]),otherbrx,otherbry,sleft,otherbrushmode) end,
  251. lr = function(words) --line right
  252. create_line(tonumber(words[2]),tonumber(words[3]),tonumber(words[4]),tonumber(words[5]),otherbrx,otherbry,sright,otherbrushmode) end,
  253. bo = function(words) --box left
  254. create_box(tonumber(words[2]),tonumber(words[3]),tonumber(words[4]),tonumber(words[5]),sleft) end,
  255. br = function(words) --box right
  256. create_box(tonumber(words[2]),tonumber(words[3]),tonumber(words[4]),tonumber(words[5]),sright) end,
  257. s = function(words) --selected elements
  258. sleft = tonumber(words[2])
  259. sright = tonumber(words[3]) end,
  260. clear = function(words)
  261. clearsim()
  262. infotext = otheruser .. " cleared the screen"
  263. infoalpha = 255 end,
  264. pause = function(words)
  265. if words[2] ~= nil then
  266. tpt.set_pause(tonumber(words[2]))
  267. else
  268. tpt.toggle_pause()
  269. end
  270. infotext = otheruser .. " toggled pause"
  271. infoalpha = 255 end,
  272. n = function(words) --username
  273. otheruser = words[2]
  274. statustext = "Connected with " .. otheruser end,
  275. fps = function(words) --fps sync
  276. otherfps = tonumber(words[2])
  277. --if otherfps<myfps then fpscapped=true tpt.setfpscap(math.max(math.min(otherfps+1,60),3)) --fpscap sync fails epicly
  278. --elseif fpscapped then if otherfps>=59 then fpscapped=false end tpt.setfpscap(math.max(math.min(otherfps+1,60),3)) end
  279. sendbuffer = math.min(1/otherfps,0.1) end,
  280. f = function(words) --framestep, syncs pause as well
  281. pausenextframe = true
  282. tpt.set_pause(0) end,
  283. ch = function(words) --chat
  284. table.insert(chatbox_messages, "o:".. command:sub(4))
  285. if chatbox_hidden then chatbox_newmessage = true end end,
  286. ping = function(words)
  287. send("pong") end,
  288. pong = function(words)
  289. pingtext = "Ping: " .. math.ceil((os.clock()-lastping)*1000) end,
  290. ver = function(words)
  291. otherversion = tonumber(words[2])
  292. if otherversion>version then statustext = otheruser.." has a newer version" end end,
  293. ff = function(words)
  294. x= tonumber(words[2]) y=tonumber(words[3]) c=tonumber(words[4])
  295. floodparts(x,y,c,-1,-1) end,
  296. }
  297. --function that you can call from other scripts to recieve new packets and run functions
  298. function newdatahandler(mess,func)
  299. datahandlers[mess]=func
  300. end
  301. --newdatahandler("waffle",function(words) tpt.create(200,200,1) end)
  302.  
  303. function readdata(data)
  304. lastsent = data
  305. lastpacket = os.clock()
  306. local i = string.find(data,"|")
  307. --go through all commands from the line
  308. --infotext=lastsent infoalpha=255
  309. while data~=nil do
  310. if i~=nil then
  311. command = string.sub(data,1,i-1)
  312. --cut the first command off
  313. data = string.sub(data,i+1)
  314. i = string.find(data,"|")
  315. else command=data data=nil --no data left
  316. end
  317. local words = {}
  318. for word in string.gmatch(command, "%w+") do table.insert(words,word) end
  319. --switch table for reading data, yay!
  320. if type(datahandlers[words[1]])=="function" then datahandlers[words[1]](words) end
  321. end
  322. end
  323.  
  324. function split_message(mess)
  325. local message=mess
  326. local width=tpt.textwidth(message)
  327. local lines = {}
  328. local k=1
  329. while width>152 do
  330. local j=15
  331. local nextwidth = tpt.textwidth(message:sub(1,j))
  332. while nextwidth<=152 do
  333. j=j+1
  334. nextwidth = tpt.textwidth(message:sub(1,j))
  335. end
  336. j=j-1
  337. lines[k]=message:sub(1,j)
  338. message=message:sub(j+1)
  339. width=tpt.textwidth(message)
  340. k=k+1
  341. end
  342. lines[k]=message
  343. return lines
  344. end
  345.  
  346. function update_chatbox()
  347. --icon on right
  348. if chatbox_hidden then
  349. if chatbox_newmessage then tpt.drawrect(613,135,15,15,255,0,0) else tpt.drawrect(613,135,15,15,200,200,200) end
  350. tpt.drawline(614,142,627,142,255,255,255)
  351. tpt.drawline(614,142,617,139,255,255,255)
  352. tpt.drawline(614,142,617,145,255,255,255)
  353. else
  354. chatbox_newmessage=false
  355. tpt.drawrect(613,135,15,15,200,200,200)
  356. tpt.drawline(614,142,627,142,255,255,255)
  357. tpt.drawline(627,142,624,139,255,255,255)
  358. tpt.drawline(627,142,624,145,255,255,255)
  359. end
  360. --the main box
  361. if not chatbox_hidden then
  362. tpt.fillrect(455,27,156,157,0,0,0,160)
  363. tpt.drawrect(455,27,156,157,255,255,255,95)
  364. tpt.drawrect(456,28,154,155,255,255,255,255)
  365. tpt.drawline(457,169,609,169,255,255,255,200)
  366. while #chatbox_messages >15 do table.remove(chatbox_messages,1) end
  367. local i = 0
  368. local offset = 0
  369. while chatbox_messages[i+1]~= nil do
  370. local mess = chatbox_messages[i+1]
  371. if mess:find("o:") then --other user message brighter than self
  372. local lines = split_message(mess:sub(3))
  373. for k=1,#lines do
  374. tpt.drawtext(458,30 + (i+offset+(k-1))*9,lines[k])
  375. if k==#lines then offset=offset+(k-1) end
  376. end
  377. else
  378. local lines = split_message(mess)
  379. for k=1,#lines do
  380. tpt.drawtext( 609 - tpt.textwidth(lines[k]) ,30 + (i+offset+(k-1))*9,lines[k],200,200,200)
  381. if k==#lines then offset=offset+(k-1) end
  382. end
  383. end
  384. if i+offset>14 then table.remove(chatbox_messages,1) end --crappy line handling
  385. i = i+1
  386. end
  387. --display only last 152 length of textbox
  388. local width=tpt.textwidth(chatbox_textbox)
  389. local display_textbox = chatbox_textbox
  390. local display_cursorpos = chatbox_cursorpos
  391. while width>152 do
  392. display_textbox = display_textbox:sub(2)
  393. width=tpt.textwidth(display_textbox)
  394. display_cursorpos = display_cursorpos - 1
  395. end
  396. tpt.drawtext(458,173,display_textbox)
  397. if chatbox_focus then
  398. local cursoradjust=tpt.textwidth(display_textbox:sub(1,display_cursorpos))+1
  399. tpt.drawline(457+cursoradjust,171,457+cursoradjust,183,255,255,255)
  400. tpt.drawrect(456,169,154,14,255,255,0)
  401. end
  402. end
  403. end
  404.  
  405. function create(x,y,c,small)
  406. local t = c%256
  407. local v = math.floor(c/256)
  408. if t==237 or t==238 then --heat and cool!
  409. local temp = tpt.get_property("type",x,y)>0 and tpt.get_property("temp",x,y) or nil
  410. if t==237 and temp~=nil and temp<9999 then
  411. local heatchange = 4 --implement more temp changes later (ctrl-shift)
  412. tpt.set_property("temp",math.min(temp+heatchange,9999),x,y)
  413. elseif t==238 and temp~=nil and temp>0 then
  414. local heatchange = 4
  415. tpt.set_property("temp",math.max(temp-heatchange,0),x,y)
  416. end
  417. return
  418. end
  419. if small then --set ctype for CLNE types if smallish brush
  420. if not setctype[c] then
  421. local cm = tpt.get_property("type",x,y)
  422. if setctype[cm] then
  423. if (cm==74 or cm==153) and (c==35 or c==36) then return end --don't give PCLN ctypes of PSCN or NSCN
  424. tpt.set_property("ctype",c,x,y)
  425. return
  426. end
  427. end
  428. end
  429. if t==0 then
  430. tpt.delete(x,y)
  431. else
  432. local i = tpt.create(x,y,t)
  433. --special case for GoL creation
  434. if t==78 and i>=0 then tpt.set_property("ctype",v,i) tpt.set_property("tmp",GoLrule[(v+2)][10],i) end
  435. end
  436. end
  437.  
  438. function create_line(x1,y1,x2,y2,rx,ry,c,brush) -- Taken From Powder Toy Source Code
  439. if c == 87 or c == 158 then return end --never do lines of FIGH and LIGH
  440. local cp = math.abs(y2-y1)>math.abs(x2-x1)
  441. local x = 0 local y = 0 local dx = 0 local dy = 0 local sy = 0 local e = 0.0 local de = 0.0 local first = true
  442. if cp then y = x1 x1 = y1 y1 = y y = x2 x2 = y2 y2 = y end
  443. if x1 > x2 then y = x1 x1 = x2 x2 = y y = y1 y1 = y2 y2 = y end
  444. dx = x2 - x1 dy = math.abs(y2 - y1) if dx ~= 0 then de = dy/dx end
  445. y = y1 if y1 < y2 then sy = 1 else sy = -1 end
  446. for x = x1, x2 do
  447. if cp then
  448. drawstuff(y,x,rx,ry,c,first,brush)
  449. else
  450. drawstuff(x,y,rx,ry,c,first,brush)
  451. end
  452. first = false
  453. e = e + de
  454. if e >= 0.5 then
  455. y = y + sy
  456. e = e - 1
  457. if y1<y2 then
  458. if y>y2 then return end
  459. elseif y<y2 then return end
  460. if (rx+ry)==0 or c>=222 then
  461. if cp then
  462. drawstuff(y,x,rx,ry,c,first,brush)
  463. else
  464. drawstuff(x,y,rx,ry,c,first,brush)
  465. end
  466. end
  467. end
  468. end
  469. end
  470.  
  471. function create_box(x1,y1,x2,y2,c)
  472. local i = 0 local j = 0
  473. if x1>x2 then i=x2 x2=x1 x1=i end
  474. if y1>y2 then j=y2 y2=y1 y1=j end
  475. for j=y1, y2 do
  476. for i=x1, x2 do
  477. create(i,j,c)
  478. end
  479. end
  480. end
  481.  
  482. function incurrentbrush(i,j,rx,ry,brush)
  483. if brush==0 then
  484. return (math.pow(i,2)*math.pow(ry,2)+math.pow(j,2)*math.pow(rx,2)<=math.pow(rx,2)*math.pow(ry,2))
  485. elseif brush==1 then
  486. return (math.abs(i)<=rx and math.abs(j)<=ry)
  487. elseif brush==2 then
  488. return ((math.abs((rx+2*i)*ry+rx*j) + math.abs(2*rx*(j-ry)) + math.abs((rx-2*i)*ry+rx*j))<=(4*rx*ry))
  489. else
  490. return false
  491. end
  492. end
  493.  
  494. function drawstuff(x,y,rx,ry,c,fill,brush) -- Draws or erases elements
  495. local energycheck = energytypes[c]
  496. local small = (rx+ry)<=16
  497. if c == 87 or c == 158 then create(x,y,c) return end --only draw one pixel of FIGH and LIGH
  498. --walls!
  499. local dw = false local b = 0
  500. if validwalls[c] then
  501. dw = true
  502. if c~=230 then b = c-100 end
  503. end
  504. if tools[c] then fill = true end
  505. if dw then
  506. local r=math.floor(rx/4)
  507. local wx = math.floor(x/4)- math.floor(r/2)
  508. local wy = math.floor(y/4)- math.floor(r/2)
  509. if b==125 then
  510. wx = wx + math.floor(r/2)
  511. wy = wy + math.floor(r/2)
  512. for v=-1,1 do
  513. for u=-1,1 do
  514. if (wx+u>=0 and wx+u<153 and wy+v>=0 and wy+v<96 and tpt.get_wallmap(wx+u,wy+v)==125) then
  515. return
  516. end end end
  517. tpt.set_wallmap(wx,wy,b)
  518. return
  519. end
  520. tpt.set_wallmap(wx,wy,r+1,r+1,b)
  521. return
  522. end
  523. if rx<=0 then--0 radius loop prevention
  524. for j=y-ry,y+ry do
  525. if valid(x,j,energycheck,c) then
  526. create(x,j,c,small) end
  527. end
  528. return
  529. end
  530. local tempy = y local oldy = y
  531. if brush==2 then tempy=y+ry end
  532. for i = x - rx, x do
  533. oldy = tempy
  534. local check = incurrentbrush(i-x,tempy-y,rx,ry,brush)
  535. if check then
  536. while check do
  537. tempy = tempy - 1
  538. check = incurrentbrush(i-x,tempy-y,rx,ry,brush)
  539. end
  540. tempy = tempy + 1
  541. if fill then
  542. local jmax = 2*y - tempy
  543. if brush == 2 then jmax=y+ry end
  544. for j = tempy, jmax do
  545. if valid(i,j,energycheck,c) then
  546. create(i,j,c,small) end
  547. if i~=x and valid(x+x-i,j,energycheck,c) then
  548. create(x+x-i,j,c,small) end
  549. end
  550. else
  551. if (oldy ~= tempy and brush~=1) or i==x-rx then oldy = oldy - 1 end
  552. for j = tempy, oldy+1 do
  553. local i2=2*x-i local j2 = 2*y-j
  554. if brush==2 then j2=y+ry end
  555. if valid(i,j,energycheck,c) then
  556. create(i,j,c,small) end
  557. if i2~=i and valid(i2,j,energycheck,c) then
  558. create(i2,j,c,small) end
  559. if j2~=j and valid(i,j2,energycheck,c) then
  560. create(i,j2,c,small) end
  561. if i2~=i and j2~=j and valid(i2,j2,energycheck,c) then
  562. create(i2,j2,c,small) end
  563. end
  564. end
  565. end
  566. end
  567. end
  568. function valid(x,y,energycheck,c)
  569. if x >= 0 and x < 612 and y >= 0 and y < 384 then
  570. if energycheck then
  571. if energytypes[tpt.get_property("type",x,y)] then return false end
  572. end
  573. return true end
  574. end
  575. function floodparts(x,y,c,cm,bm)
  576. local x1=x local x2=x
  577. if cm==-1 then
  578. if c==0 then
  579. cm = tpt.get_property("type",x,y)
  580. if cm==0 then return false end
  581. else
  582. cm = 0
  583. end
  584. end
  585. --wall check here
  586. while x1>=4 do
  587. if (tpt.get_property("type",x1-1,y)~=cm) then break end
  588. x1 = x1-1
  589. end
  590. while x2<=608 do
  591. if (tpt.get_property("type",x2+1,y)~=cm) then break end
  592. x2 = x2+1
  593. end
  594. for x=x1, x2 do
  595. if c==0 then tpt.delete(x,y) end
  596. if c>0 and c<222 then create(x,y,c) end
  597. end
  598. if y>=5 then
  599. for x=x1,x2 do
  600. if tpt.get_property("type",x,y-1)==cm then
  601. if not floodparts(x,y-1,c,cm,bm) then
  602. return false
  603. end end end
  604. end
  605. if y<379 then
  606. for x=x1,x2 do
  607. if tpt.get_property("type",x,y+1)==cm then
  608. if not floodparts(x,y+1,c,cm,bm) then
  609. return false
  610. end end end
  611. end
  612. return true
  613. end
  614.  
  615. function clearsim()
  616. tpt.start_getPartIndex()
  617. while tpt.next_getPartIndex() do
  618. local index = tpt.getPartIndex()
  619. tpt.set_property("type",0,index)
  620. end
  621. tpt.reset_velocity(0,0,153,96)
  622. tpt.set_pressure(0,0,153,96,0)
  623. tpt.set_wallmap(0,0,153,96,0)
  624. end
  625.  
  626. function connect(ip,port)
  627. if tpt.get_name() == "" then tpt.log("You need to be logged in") return end
  628. client, err = socket.connect(ip,port)
  629. if client~= nil then
  630. tpt.log("Connected")
  631. client:setoption("keepalive",true)
  632. client:settimeout(0)
  633. lastpacket=os.clock()
  634. tpt.set_console(0)
  635. chatbox_messages = {}
  636. send("n "..tpt.get_name().."|s "..myleft.." "..myright.."|b ".. mybrx.." "..mybry.." "..mybrushmode.."|ver "..version)--send name
  637. else
  638. tpt.log("Fail")
  639. end
  640. end
  641.  
  642. local messagebuffer = ""
  643. function send(message)
  644. local timesincelast = os.clock()-lastpsent
  645. if messagebuffer == "" then messagebuffer=message return end
  646. if (message~="") then
  647. messagebuffer = messagebuffer.."|"..message
  648. end
  649. if (timesincelast<= sendbuffer or (message=="" and messagebuffer=="")) then
  650. return
  651. end
  652. lastpsent = os.clock()
  653. if client~= nil then
  654. local sent = client:send(messagebuffer .. "\n")
  655. if sent then datasent = datasent + sent end
  656. elseif serverclient~= nil then
  657. local sent = serverclient:send(messagebuffer .. "\n")
  658. if sent then datasent = datasent + sent end
  659. else
  660. --tpt.log("No client")
  661. end
  662. messagebuffer = ""
  663. end
  664.  
  665. function mouse_coords_window_to_sim(window_x,window_y)
  666. if (zoom_en>0 and window_x>=zoom_wx and window_y>=zoom_wy and window_x<(zoom_wx+ZFACTOR*ZSIZE) and window_y<(zoom_wy+ZFACTOR*ZSIZE)) then
  667. return (math.floor((window_x-zoom_wx)/ZFACTOR)+zoom_x) , (math.floor((window_y-zoom_wy)/ZFACTOR)+zoom_y)
  668. else
  669. return window_x,window_y
  670. end
  671. end
  672.  
  673. local releasestrings = {[1]="l ",[2]="lr ",[3]="bo ",[4]="br "}
  674. function mouseclicky(mousex,mousey,button,event,mouse_wheel)
  675. wheel = mouse_wheel --wheel should be set to 0 after all used per frame (if used outside this function)
  676. --no need for wheel checks to change brush size, we can get the size directly
  677. --tpt.drawtext(200,200,tostring(button))
  678. if zoom_trig>0 then
  679. ZSIZE = ZSIZE+wheel
  680. if ZSIZE>60 then ZSIZE=60 end
  681. if ZSIZE<2 then ZSIZE=2 end
  682. ZFACTOR = math.floor(256/ZSIZE)
  683. if zoom_en<2 then zoom_en=1 end
  684. end
  685. if event==2 and zoom_trig>0 and zoom_en<2 then
  686. local x = mousex-math.floor(ZSIZE/2) local y = mousey-math.floor(ZSIZE/2)
  687. if x<0 then x=0 end if y<0 then y=0 end
  688. if x>612-ZSIZE then x=612-ZSIZE end if y>384-ZSIZE then y=384-ZSIZE end
  689. zoom_x = x
  690. zoom_y = y
  691. zoom_wx = (x<306) and 612-ZSIZE*ZFACTOR or 0
  692. zoom_wy = 0
  693. zoom_en = 2
  694. zoom_trig=0
  695. return true
  696. end
  697. if zoom_trig>0 then return true end
  698. --because this function will now trigger on mouse wheel, the event can possibly be 0
  699. if event==0 then return true end
  700. if disabled[myleft] and button==1 or disabled[myright] and button==4 then
  701. infotext = "This element does NOT send to your partner" infoalpha=255 return true
  702. end
  703. mousex,mousey = mouse_coords_window_to_sim(mousex,mousey)
  704. if releasetype > 0 then
  705. if event==2 then
  706. send(releasestrings[releasetype] .. startx .. " " .. starty .. " " .. mousex .. " " .. mousey)
  707. releasetype = 0
  708. end
  709. return true
  710. end
  711. if (event==2) then
  712. return true
  713. end
  714.  
  715. if not chatbox_hidden and mousex>=457 and mousex<=609 and mousey>=170 and mousey<=182 then
  716. if event==3 and not chatbox_focus then return true end
  717. chatbox_focus = true
  718. --tpt.set_shortcuts(0)
  719. return false
  720. elseif event~=3 then
  721. --tpt.set_shortcuts(1)
  722. chatbox_focus = false
  723. end
  724.  
  725. if (mousey > 404 and event == 1) then
  726. --clear button
  727. if (mousex >= 486 and mousex <= 502) then
  728. send("clear")
  729. return true
  730. --pause button
  731. elseif (mousex >= 613) then
  732. send("pause")
  733. return true
  734. end
  735. end
  736. if (mousex > 612 and event == 1) then
  737. --chat hide button
  738. if (mousey>=135 and mousey<=150) then
  739. chatbox_hidden = not chatbox_hidden
  740. if not chatbox_hidden then chatbox_focus = true end
  741. end
  742. end
  743. if (mousey >= 384 or mousex >= 612) then
  744. return true
  745. end
  746. if (button == 1) then
  747. if (kmod == 1) then startx,starty = mousex,mousey releasetype=1 return true end
  748. if (kmod == 64) then startx,starty = mousex,mousey releasetype=3 return true end
  749. if (kmod == 65) then if(sleft==0 and tpt.get_property("type",mousex,mousey)~=0) then send("ff "..mousex.." "..mousey.." "..sleft) end return true end
  750. send("d " .. (mousex + mousey*1024) .. (event==1 and " 1" or "") )
  751. elseif (button == 4) then
  752. if (kmod == 1) then startx,starty = mousex,mousey releasetype=2 return true end
  753. if (kmod == 64) then startx,starty = mousex,mousey releasetype=4 return true end
  754. if (kmod == 65) then if(sright==0 and tpt.get_property("type",mousex,mousey)~=0) then send("ff "..mousex.." "..mousey.." "..sright) end return true end
  755. send("r " .. (mousex + mousey*1024) .. (event==1 and " 1" or "") )
  756. end
  757. end
  758.  
  759. function movechatcursor(amount)
  760. chatbox_cursorpos = chatbox_cursorpos+amount
  761. if chatbox_cursorpos>string.len(chatbox_textbox) then chatbox_cursorpos = string.len(chatbox_textbox) return end
  762. if chatbox_cursorpos<0 then chatbox_cursorpos = 0 return end
  763. end
  764. function chatkeyprocess(key,nkey)
  765. --replace some keys for specific keyboard layouts, make a list later
  766. if KEYBOARD==2 then if key=="=" then key="´" end if key=="\\" then key="'" end if key=="]" then key="¨" end end
  767. if nkey==275 then movechatcursor(1) return false end
  768. if nkey==276 then movechatcursor(-1) return false end
  769. if nkey==27 then chatbox_focus=false return false end
  770. if nkey==8 then chatbox_textbox = chatbox_textbox:sub(1,chatbox_cursorpos-1)..chatbox_textbox:sub(chatbox_cursorpos+1) movechatcursor(-1) return false end
  771. if nkey==127 then chatbox_textbox = chatbox_textbox:sub(1,chatbox_cursorpos)..chatbox_textbox:sub(chatbox_cursorpos+2) return false end
  772. if (nkey==13 or nkey==271) and chatbox_textbox~="" then --enter, about to send, check for commands
  773. if otheruser=="" and chatbox_textbox:find("/c") then
  774. local ip = chatbox_textbox:sub(4,chatbox_textbox:find(" ",4))
  775. local port = chatbox_textbox:sub(chatbox_textbox:find(" ",4)+1)
  776. if tonumber(port) then connect(ip,tonumber(port)) else infotext="Bad command" infoalpha=255 end
  777. chatbox_textbox = "" chatbox_cursorpos = 0
  778. return false end
  779. send("ch "..chatbox_textbox) table.insert(chatbox_messages,chatbox_textbox) chatbox_textbox = "" return false
  780. end
  781. --tpt.drawtext(200,210,nkey)
  782. if nkey<32 or nkey>=127 then return false end
  783. local addkey = (kmod==1 or kmod==2) and shift(key) or key
  784. if (math.floor(kmod/512))==1 then addkey=altgr(key) end
  785. if tpt.textwidth(chatbox_textbox .. addkey)<760 then chatbox_textbox=chatbox_textbox:sub(1,chatbox_cursorpos)..addkey..chatbox_textbox:sub(chatbox_cursorpos+1) movechatcursor(1) end
  786.  
  787. return false
  788. end
  789. function keyclicky(key,nkey,modifier,event)
  790. kmod = modifier%1024--ignore numlock and caps lock for now
  791. --tpt.drawtext(200,200,nkey)
  792. --ignore releases and modifiers
  793. if (event==2 or (nkey>=300 and nkey<=308)) then return true end
  794. if chatbox_focus then
  795. return chatkeyprocess(key,nkey)
  796. end
  797. if key=="z" then
  798. if event==1 then
  799. if kmod==256 then zoom_trig= (zoom_trig>=1 and 0 or 2)
  800. else zoom_trig=1 end
  801. end
  802. if event==2 and zoom_trig==1 then zoom_trig = 0 end
  803. if zoom_trig==0 and zoom_en==1 then zoom_en=0 end--might go in step
  804. if zoom_en==2 then zoom_en=1 end
  805. end
  806. if key==" " then send("pause") end
  807. if key=="f" then send("f") end
  808. if nkey==9 then mybrushmode=(mybrushmode+1)%3 send("b "..mybrx.." "..mybry.." "..mybrushmode) end --tab
  809. if nkey == 91 then --Left bracket
  810. if kmod == 256 or kmod == 512 then mybrx=mybrx-1 mybry=mybry-1 --alt
  811. elseif kmod == 1 or kmod == 2 then mybrx=mybrx-1 --shift
  812. elseif kmod == 64 or kmod == 128 then mybry=mybry-1 --ctrl
  813. else mybrx=mybrx-math.ceil((mybrx/5)+.1) mybry=mybry-math.ceil((mybry/5)+.1)
  814. end
  815. if mybrx < 0 then mybrx = 0 end
  816. if mybry < 0 then mybry = 0 end
  817. if zoom_trig>0 then
  818. ZSIZE = ZSIZE-1
  819. if ZSIZE<2 then ZSIZE=2 end
  820. ZFACTOR = math.floor(256/ZSIZE)
  821. end
  822. send("b " .. mybrx .. " " .. mybry)
  823. elseif nkey == 93 then --Right bracket
  824. if kmod == 256 or kmod == 512 then mybrx=mybrx+1 mybry=mybry+1 --alt
  825. elseif kmod == 1 or kmod == 2 then mybrx=mybrx+1 --shift
  826. elseif kmod == 64 or kmod == 128 then mybry=mybry+1 --ctrl
  827. else mybrx=mybrx+math.ceil((mybrx/5)+.1) mybry=mybry+math.ceil((mybry/5)+.1)
  828. end
  829. if mybrx > 800 then mybrx = 800 end
  830. if mybry > 800 then mybry = 800 end
  831. if zoom_trig>0 then
  832. ZSIZE = ZSIZE+1
  833. if ZSIZE>60 then ZSIZE=60 end
  834. ZFACTOR = math.floor(256/ZSIZE)
  835. end
  836. send("b " .. mybrx .. " " .. mybry)
  837. end
  838. return true
  839. end
  840.  
  841. tpt.register_keypress(keyclicky)
  842. tpt.register_mouseclick(mouseclicky)
  843. tpt.register_step(step)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement