nonogamer9

test

Oct 10th, 2026 (edited)
50
0
Never
2
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 57.34 KB | None | 0 0
  1. --[[
  2. ClassiCube 1.3.8 -> OpenComputers (single file, braille raycaster)
  3.  
  4. This is NOT a line-by-line translation of the C client (that needs OpenGL, a
  5. filesystem, sockets and ~130k lines). It is a self-contained Lua re-implementation
  6. of the parts of ClassiCube that matter for singleplayer, ported from the 1.3.8
  7. sources:
  8. * java.util.Random-compatible RNG, ImprovedNoise / OctaveNoise / CombinedNoise
  9. * "Notchy" classic map generator (Generator.c): heightmap, strata, caves, ore
  10. veins, water/lava flood fill, sand/gravel/grass surface, flowers, mushrooms, trees
  11. * classic block IDs 0..49 and CPE blocks 50..65, collide types, face shading
  12. (top 1.0, Z 0.8, X 0.6, bottom 0.5) and classic sun/shadow lighting (heightmap)
  13. * player physics (EntityComponents.c): gravity .08, drag .91/.98/.91, jump .42,
  14. ground friction .6, water/lava drag, liquid jump, fly / noclip / speed hacks
  15. * block picking with 5 block reach, default hotbar, sand/gravel falling
  16. Rendering is a voxel DDA raycaster drawn with braille characters (2x4 dots per cell).
  17.  
  18. REQUIREMENTS : OpenOS, GPU+screen (tier 3 recommended), keyboard. ~2 MB RAM is plenty
  19. for the default 64x32x64 world. Run: classicube
  20.  
  21. CONTROLS
  22. W A S D move Space jump / swim up / fly up
  23. Arrows look Left Shift fly down
  24. Q / click break block E / right-click place block
  25. 1-9 / wheel select hotbar slot [ ] change block in slot
  26. F fly X noclip Z (hold) speed
  27. R respawn G new world Esc / Ctrl+C quit
  28.  
  29. Original ClassiCube license (BSD-3-Clause):
  30. Copyright (c) 2014 - 2024, UnknownShadow200. All rights reserved.
  31. Redistribution and use in source and binary forms, with or without modification,
  32. are permitted provided that the following conditions are met:
  33. 1. Redistributions of source code must retain the above copyright notice, this
  34. list of conditions and the following disclaimer.
  35. 2. Redistributions in binary form must reproduce the above copyright notice, this
  36. list of conditions and the following disclaimer in the documentation and/or
  37. other materials provided with the distribution.
  38. 3. Neither the name of ClassiCube nor the names of its contributors may be used to
  39. endorse or promote products derived from this software without specific prior
  40. written permission.
  41. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  42. EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED. (full text: ClassiCube license.txt)
  43. ]]
  44.  
  45. local component = require("component")
  46. local computer = require("computer")
  47. local unicode = require("unicode")
  48. local gpu = component.gpu
  49.  
  50. local floor, abs, sqrt, sin, cos, tan = math.floor, math.abs, math.sqrt, math.sin, math.cos, math.tan
  51. local min, max, huge, pi, exp = math.min, math.max, math.huge, math.pi, math.exp
  52. local byte, char, sub, concat, rep, fmt = string.byte, string.char, string.sub, table.concat, string.rep, string.format
  53.  
  54. ---------------------------------------------------------------------------------------
  55. -- Configuration (tweak for your hardware)
  56. ---------------------------------------------------------------------------------------
  57. local CFG = {
  58. WIDTH = 64, HEIGHT = 32, LENGTH = 64, -- world size X, Y, Z (ClassiCube "normal" is 128x64x128: needs lots of RAM)
  59. SEED = nil, -- nil = random
  60. RES_W = 80, RES_H = 25, -- text resolution to use (clamped to the GPU maximum)
  61. VIEW = 28, -- view distance in blocks
  62. FOV = 70, -- horizontal field of view (degrees)
  63. Q_MOVE = 1, -- vertical rays per braille cell while moving (1, 2 or 4); OC Lua is slow, raise if fast
  64. Q_STILL = 4, -- ... and when standing still (a sharp frame is drawn after you stop)
  65. REACH = 5,
  66. LOOK = 110, -- arrow-key turn speed, degrees / second
  67. }
  68.  
  69. local W, H, L = CFG.WIDTH, CFG.HEIGHT, CFG.LENGTH
  70. local EYE, HW, HT = 1.625, 0.3, 1.8 -- player eye height, half width, height (ClassiCube human model)
  71.  
  72. local function trunc(v) if v >= 0 then return floor(v) end return -floor(-v) end
  73.  
  74. ---------------------------------------------------------------------------------------
  75. -- Cooperative yielding (OpenComputers kills programs that run ~5 s without yielding)
  76. ---------------------------------------------------------------------------------------
  77. local pump
  78. local lastYield = computer.uptime()
  79. local function maybeYield()
  80. if computer.uptime() - lastYield > 1.5 then
  81. pump(0)
  82. lastYield = computer.uptime()
  83. end
  84. end
  85.  
  86. ---------------------------------------------------------------------------------------
  87. -- java.util.Random compatible RNG (ExtMath.c). 48 bit LCG done in 24 bit halves so it
  88. -- is exact on Lua 5.2 (doubles) as well as Lua 5.3 (integers).
  89. ---------------------------------------------------------------------------------------
  90. local Mlo, Mhi, P24 = 0xECE66D, 0x5DE, 16777216
  91. local function xor24(a, b)
  92. local r, bit = 0, 1
  93. for _ = 1, 24 do
  94. local x, y = a % 2, b % 2
  95. if x ~= y then r = r + bit end
  96. a = (a - x) / 2; b = (b - y) / 2; bit = bit * 2
  97. end
  98. return r
  99. end
  100. local function newRng(seed)
  101. seed = floor(seed) % 4294967296
  102. return { lo = xor24(seed % P24, Mlo), hi = xor24(floor(seed / P24), Mhi) }
  103. end
  104. local function rstep(r)
  105. local sl, sh = r.lo, r.hi
  106. local t = sl * Mlo + 11
  107. r.lo = t % P24
  108. r.hi = (sh * Mlo + sl * Mhi + floor(t / P24)) % P24
  109. end
  110. local POW2 = {}
  111. for i = 0, 20 do POW2[2 ^ i] = true end
  112. local function rnext(r, n) -- Random_Next: [0, n)
  113. rstep(r)
  114. local bits = r.hi * 128 + floor(r.lo / 131072) -- seed >> 17
  115. if POW2[n] then return floor(n * bits / 2147483648) end
  116. return bits % n
  117. end
  118. local function rfloat(r) rstep(r); return r.hi / 16777216 end
  119.  
  120. ---------------------------------------------------------------------------------------
  121. -- Perlin noise (Generator.c)
  122. ---------------------------------------------------------------------------------------
  123. local GX, GY = {}, {}
  124. for i = 0, 15 do
  125. local sh = 2 ^ (i * 2)
  126. GX[i] = floor(0x46552222 / sh) % 4 - 1
  127. GY[i] = floor(0x2222550A / sh) % 4 - 1
  128. end
  129. local function perm(r)
  130. local p = {}
  131. for i = 0, 255 do p[i] = i end
  132. for i = 0, 255 do
  133. local j = i + rnext(r, 256 - i)
  134. p[i], p[j] = p[j], p[i]
  135. end
  136. return p
  137. end
  138. local function inoise(p, x, y)
  139. local xi, yi = floor(x), floor(y)
  140. local X, Y = xi % 256, yi % 256
  141. x = x - xi; y = y - yi
  142. local u = x * x * x * (x * (x * 6 - 15) + 10)
  143. local v = y * y * y * (y * (y * 6 - 15) + 10)
  144. local A = p[X] + Y
  145. local B = p[(X + 1) % 256] + Y
  146. local h = p[p[A % 256]] % 16
  147. local g22 = GX[h] * x + GY[h] * y
  148. h = p[p[B % 256]] % 16
  149. local g12 = GX[h] * (x - 1) + GY[h] * y
  150. local c1 = g22 + u * (g12 - g22)
  151. h = p[p[(A + 1) % 256]] % 16
  152. local g21 = GX[h] * x + GY[h] * (y - 1)
  153. h = p[p[(B + 1) % 256]] % 16
  154. local g11 = GX[h] * (x - 1) + GY[h] * (y - 1)
  155. local c2 = g21 + u * (g11 - g21)
  156. return c1 + v * (c2 - c1)
  157. end
  158. local function octInit(r, n) local o = { n = n }; for i = 1, n do o[i] = perm(r) end; return o end
  159. local function octCalc(o, x, y)
  160. local amp, fr, sum = 1, 1, 0
  161. for i = 1, o.n do
  162. sum = sum + inoise(o[i], x * fr, y * fr) * amp
  163. amp = amp * 2; fr = fr * 0.5
  164. end
  165. return sum
  166. end
  167. local function combInit(r, a, b) local n1 = octInit(r, a); local n2 = octInit(r, b); return { n1, n2 } end
  168. local function combCalc(c, x, y) local off = octCalc(c[2], x, y); return octCalc(c[1], x + off, y) end
  169.  
  170. ---------------------------------------------------------------------------------------
  171. -- Blocks (BlockID.h / Block.c)
  172. ---------------------------------------------------------------------------------------
  173. local NAMES = { [0] = "Air", "Stone", "Grass", "Dirt", "Cobblestone", "Wood", "Sapling", "Bedrock", "Water",
  174. "Still water", "Lava", "Still lava", "Sand", "Gravel", "Gold ore", "Iron ore", "Coal ore", "Log", "Leaves",
  175. "Sponge", "Glass", "Red", "Orange", "Yellow", "Lime", "Green", "Teal", "Aqua", "Cyan", "Blue", "Indigo",
  176. "Violet", "Magenta", "Pink", "Black", "Gray", "White", "Dandelion", "Rose", "Brown shroom", "Red shroom",
  177. "Gold", "Iron", "Double slab", "Slab", "Brick", "TNT", "Bookshelf", "Mossy rocks", "Obsidian",
  178. "Cobblestone slab", "Rope", "Sandstone", "Snow", "Fire", "Light pink", "Forest green", "Brown",
  179. "Deep blue", "Turquoise", "Ice", "Ceramic tile", "Magma", "Pillar", "Crate", "Stone brick" }
  180. local MAXBLOCK = 65
  181.  
  182. -- COL: 0 passable, 1 solid, 2 water, 3 lava
  183. local COL, SPRITE, NOLIGHT = {}, {}, {}
  184. for b = 0, MAXBLOCK do COL[b] = 1 end
  185. for _, b in ipairs { 0, 6, 37, 38, 39, 40, 51, 54 } do COL[b] = 0 end
  186. for _, b in ipairs { 6, 37, 38, 39, 40, 51, 54 } do SPRITE[b] = true end
  187. COL[8], COL[9], COL[10], COL[11] = 2, 2, 3, 3
  188. for _, b in ipairs { 0, 6, 18, 20, 37, 38, 39, 40, 51, 54 } do NOLIGHT[b] = true end
  189.  
  190. ---------------------------------------------------------------------------------------
  191. -- Procedural 8x8 textures (4 bytes per texel: r g b a)
  192. ---------------------------------------------------------------------------------------
  193. local function th(x, y, s)
  194. local h = (x * 7919 + y * 104729 + s * 1299709) % 65536
  195. h = (h * h + h * 31 + 17) % 1021
  196. return h / 1021
  197. end
  198. local function cc(v) v = floor(v + 0.5); if v < 0 then return 0 elseif v > 255 then return 255 end; return v end
  199. local function mk(fn)
  200. local t = {}
  201. for y = 0, 7 do
  202. for x = 0, 7 do
  203. local r, g, b, a = fn(x, y)
  204. t[#t + 1] = char(cc(r), cc(g), cc(b), a or 255)
  205. end
  206. end
  207. return concat(t)
  208. end
  209. local function noisy(r, g, b, var, s)
  210. return mk(function(x, y) local d = (th(x, y, s) - 0.5) * var; return r + d, g + d, b + d end)
  211. end
  212. local function spr(fn)
  213. return mk(function(x, y)
  214. local r, g, b = fn(x, y)
  215. if r then return r, g, b, 255 end
  216. return 0, 0, 0, 0
  217. end)
  218. end
  219.  
  220. local TOP, SIDE, BOT = {}, {}, {}
  221. local function setT(b, top, side, bot)
  222. TOP[b] = top; SIDE[b] = side or top; BOT[b] = bot or side or top
  223. end
  224.  
  225. local function cobble(s, moss)
  226. return mk(function(x, y)
  227. local row = floor(y / 4)
  228. local m = (y % 4 == 0) or ((x + row * 2) % 4 == 0)
  229. local d = (th(x, y, s) - 0.5) * 30
  230. if moss and th(x, y, s + 50) > 0.6 then return 70 + d, 130 + d, 55 + d end
  231. local v = m and 80 or 128
  232. return v + d, v + d, v + d
  233. end)
  234. end
  235. local function oreTex(sr, sg, sb, s)
  236. return mk(function(x, y)
  237. local d = (th(x, y, s) - 0.5) * 34
  238. if th(floor(x / 2), floor(y / 2), s + 7) > 0.7 and th(x, y, s + 3) > 0.25 then return sr, sg, sb end
  239. return 128 + d, 128 + d, 128 + d
  240. end)
  241. end
  242. local function metalBlock(r, g, b, s)
  243. return mk(function(x, y)
  244. local edge = (x == 0 or y == 0 or x == 7 or y == 7)
  245. local d = (th(x, y, s) - 0.5) * 14
  246. if edge then return r * 0.82 + d, g * 0.82 + d, b * 0.82 + d end
  247. return r + d, g + d, b + d
  248. end)
  249. end
  250.  
  251. setT(1, noisy(128, 128, 128, 34, 1))
  252. setT(2, noisy(100, 170, 55, 36, 3),
  253. mk(function(x, y)
  254. local d = (th(x, y, 4) - 0.5) * 30
  255. if y < 2 or (y == 2 and th(x, y, 5) > 0.5) then return 100 + d, 170 + d, 55 + d end
  256. return 134 + d, 96 + d, 67 + d
  257. end),
  258. noisy(134, 96, 67, 30, 2))
  259. setT(3, noisy(134, 96, 67, 30, 2))
  260. setT(4, cobble(6))
  261. setT(5, mk(function(x, y)
  262. local d = (th(x, y, 8) - 0.5) * 14
  263. if y % 4 == 3 then return 120 + d, 92 + d, 50 + d end
  264. return 170 + d, 135 + d, 80 + d
  265. end))
  266. setT(6, spr(function(x, y)
  267. if y <= 4 and x >= 2 and x <= 5 and th(x, y, 9) > 0.2 then return 50, 150, 45 end
  268. if (x == 3 or x == 4) and y >= 5 then return 100, 75, 40 end
  269. end))
  270. setT(7, noisy(70, 70, 70, 60, 5))
  271. setT(8, noisy(48, 96, 230, 8, 21)); setT(9, TOP[8])
  272. local lava = mk(function(x, y)
  273. local d = th(x, y, 22)
  274. return 220 + d * 35, 80 + d * 120, 10
  275. end)
  276. setT(10, lava); setT(11, lava)
  277. setT(12, noisy(220, 210, 160, 18, 7))
  278. setT(13, noisy(135, 130, 128, 80, 24))
  279. setT(14, oreTex(255, 215, 60, 10))
  280. setT(15, oreTex(216, 175, 147, 11))
  281. setT(16, oreTex(35, 35, 35, 12))
  282. setT(17, mk(function(x, y) -- log top
  283. local c = max(abs(x - 3.5), abs(y - 3.5))
  284. if c >= 3 then return 105, 82, 52 end
  285. if floor(c) % 2 == 0 then return 160, 128, 78 end
  286. return 140, 108, 64
  287. end), mk(function(x, y) -- log side
  288. local d = (th(x, 0, 12) - 0.5) * 40
  289. return 105 + d, 82 + d, 52 + d
  290. end))
  291. setT(18, mk(function(x, y)
  292. if th(x, y, 13) < 0.2 then return 0, 0, 0, 0 end
  293. local d = (th(x, y, 14) - 0.5) * 50
  294. return 50 + d, 140 + d, 35 + d
  295. end))
  296. setT(19, mk(function(x, y)
  297. local d = (th(x, y, 15) - 0.5) * 30
  298. if th(x, y, 16) > 0.8 then return 150, 150, 30 end
  299. return 205 + d, 205 + d, 60 + d
  300. end))
  301. setT(20, mk(function(x, y)
  302. if x == 0 or y == 0 or x == 7 or y == 7 then return 215, 235, 240 end
  303. return 0, 0, 0, 0
  304. end))
  305. local WOOL = {
  306. [21] = { 196, 52, 52 }, [22] = { 216, 128, 48 }, [23] = { 226, 216, 56 }, [24] = { 118, 198, 40 },
  307. [25] = { 64, 146, 52 }, [26] = { 50, 148, 110 }, [27] = { 60, 182, 176 }, [28] = { 56, 150, 206 },
  308. [29] = { 56, 86, 206 }, [30] = { 96, 64, 196 }, [31] = { 142, 68, 196 }, [32] = { 196, 64, 172 },
  309. [33] = { 226, 128, 150 }, [34] = { 32, 32, 32 }, [35] = { 128, 128, 128 }, [36] = { 232, 232, 232 },
  310. [55] = { 240, 175, 195 }, [56] = { 40, 110, 40 }, [57] = { 110, 70, 40 }, [58] = { 25, 35, 120 },
  311. [59] = { 40, 200, 170 } }
  312. for b, c in pairs(WOOL) do setT(b, noisy(c[1], c[2], c[3], 16, 30 + b)) end
  313. setT(37, spr(function(x, y)
  314. if (x == 3 or x == 4) and y >= 3 then return 50, 140, 40 end
  315. if y <= 3 and x >= 2 and x <= 5 and not ((x == 2 or x == 5) and (y == 0 or y == 3)) then return 245, 225, 40 end
  316. end))
  317. setT(38, spr(function(x, y)
  318. if (x == 3 or x == 4) and y >= 3 then return 50, 140, 40 end
  319. if y <= 3 and x >= 2 and x <= 5 and not ((x == 2 or x == 5) and (y == 0 or y == 3)) then return 215, 40, 40 end
  320. end))
  321. setT(39, spr(function(x, y)
  322. if y >= 5 and (x == 3 or x == 4) then return 215, 205, 185 end
  323. if y >= 2 and y <= 4 and x >= 1 and x <= 6 then return 140, 100, 70 end
  324. end))
  325. setT(40, spr(function(x, y)
  326. if y >= 5 and (x == 3 or x == 4) then return 225, 215, 195 end
  327. if y >= 2 and y <= 4 and x >= 1 and x <= 6 then return 205, 50, 45 end
  328. end))
  329. setT(41, metalBlock(250, 222, 80, 41))
  330. setT(42, metalBlock(222, 222, 222, 42))
  331. local slabTop = noisy(165, 165, 165, 20, 43)
  332. local slabSide = mk(function(x, y)
  333. local d = (th(x, y, 44) - 0.5) * 24
  334. if y == 3 or y == 4 then return 105 + d, 105 + d, 105 + d end
  335. return 150 + d, 150 + d, 150 + d
  336. end)
  337. setT(43, slabTop, slabSide); setT(44, slabTop, slabSide)
  338. setT(45, mk(function(x, y)
  339. local d = (th(x, y, 45) - 0.5) * 22
  340. local row = floor(y / 4)
  341. if y % 4 == 0 or (x + row * 4) % 8 == 0 then return 190, 185, 175 end
  342. return 150 + d, 75 + d, 60 + d
  343. end))
  344. setT(46, noisy(150, 110, 70, 16, 46), mk(function(x, y)
  345. local d = (th(x, y, 47) - 0.5) * 16
  346. if y == 3 or y == 4 then return 236 + d, 230 + d, 220 + d end
  347. return 200 + d, 45 + d, 35 + d
  348. end), noisy(150, 110, 70, 16, 46))
  349. local planks = TOP[5]
  350. setT(47, planks, mk(function(x, y)
  351. if y == 0 or y == 7 or y == 3 or y == 4 then return 150, 118, 70 end
  352. local k = floor(th(floor(x / 2), floor(y / 3.5), 48) * 6)
  353. local cols = { { 180, 50, 50 }, { 50, 90, 180 }, { 60, 150, 70 }, { 200, 170, 60 }, { 140, 70, 160 }, { 90, 60, 40 } }
  354. local c = cols[k + 1] or cols[1]
  355. return c[1], c[2], c[3]
  356. end), planks)
  357. setT(48, cobble(49, true))
  358. setT(49, mk(function(x, y)
  359. local d = (th(x, y, 50) - 0.5) * 30
  360. if th(x, y, 51) > 0.85 then return 80, 60, 130 end
  361. return 25 + d, 15 + d, 45 + d
  362. end))
  363. setT(50, TOP[4])
  364. setT(51, spr(function(x, y) if x == 3 or x == 4 then return 150, 120, 70 end end))
  365. local sand2 = noisy(215, 200, 150, 16, 52)
  366. setT(52, sand2, mk(function(x, y)
  367. local d = (th(x, y, 53) - 0.5) * 14
  368. if y % 4 == 3 then return 190 + d, 175 + d, 125 + d end
  369. return 215 + d, 200 + d, 150 + d
  370. end), sand2)
  371. setT(53, noisy(245, 248, 250, 10, 54))
  372. setT(54, spr(function(x, y)
  373. if th(x, y, 55) + y / 9 > 0.55 and y > 0 then return 245, 110 + y * 16, 20 end
  374. end))
  375. setT(60, noisy(160, 200, 255, 16, 60))
  376. setT(61, mk(function(x, y)
  377. if x == 0 or y == 0 or x == 4 or y == 4 then return 170, 170, 170 end
  378. return 235, 235, 235
  379. end))
  380. setT(62, mk(function(x, y)
  381. local d = th(x, y, 62)
  382. if d > 0.7 then return 255, 150, 30 end
  383. return 70 + d * 60, 20, 15
  384. end))
  385. setT(63, mk(function(x, y)
  386. if x == 0 or x == 7 then return 170, 170, 170 end
  387. return 225 + (th(x, y, 63) - 0.5) * 12, 225, 225
  388. end), noisy(225, 225, 225, 12, 63))
  389. setT(64, mk(function(x, y)
  390. local d = (th(x, y, 64) - 0.5) * 14
  391. if x == 0 or y == 0 or x == 7 or y == 7 or x == y or x + y == 7 then return 120 + d, 85 + d, 45 + d end
  392. return 175 + d, 140 + d, 85 + d
  393. end))
  394. setT(65, mk(function(x, y)
  395. local d = (th(x, y, 65) - 0.5) * 20
  396. if y % 4 == 0 or (x + floor(y / 4) * 4) % 8 == 0 then return 95, 95, 95 end
  397. return 135 + d, 135 + d, 135 + d
  398. end))
  399.  
  400. -- average colour of each block (for the hotbar)
  401. local AVGP = {}
  402. for b = 1, MAXBLOCK do
  403. local tx = SIDE[b]
  404. local sr, sg, sb, n = 0, 0, 0, 0
  405. if tx then
  406. for i = 0, 63 do
  407. local r, g, bl, a = byte(tx, i * 4 + 1, i * 4 + 4)
  408. if a > 0 then sr = sr + r; sg = sg + g; sb = sb + bl; n = n + 1 end
  409. end
  410. end
  411. if n == 0 then n = 1 end
  412. AVGP[b] = floor(sr / n) * 65536 + floor(sg / n) * 256 + floor(sb / n)
  413. end
  414.  
  415. ---------------------------------------------------------------------------------------
  416. -- World storage: one string of W bytes per (y, z) row. rows[y*L + z + 1]
  417. ---------------------------------------------------------------------------------------
  418. local CH = {}
  419. for i = 0, 255 do CH[i] = char(i) end
  420. local rows = {}
  421. local hm = {} -- light heightmap: top light-blocking y per column
  422. local function getb(x, y, z) return byte(rows[y * L + z + 1], x + 1) end
  423. local function setb(x, y, z, b)
  424. local i = y * L + z + 1
  425. local s = rows[i]
  426. rows[i] = sub(s, 1, x) .. CH[b] .. sub(s, x + 2)
  427. end
  428. local function colHM(x, z)
  429. local y = H - 1
  430. while y >= 0 do
  431. if not NOLIGHT[byte(rows[y * L + z + 1], x + 1)] then break end
  432. y = y - 1
  433. end
  434. hm[z * W + x + 1] = y
  435. end
  436. local function computeHM()
  437. for z = 0, L - 1 do for x = 0, W - 1 do colHM(x, z) end; maybeYield() end
  438. end
  439.  
  440. ---------------------------------------------------------------------------------------
  441. -- "Notchy" map generator (Generator.c)
  442. ---------------------------------------------------------------------------------------
  443. local statusFn = function() end
  444.  
  445. local function generate(seed)
  446. local r = newRng(seed)
  447. local waterLevel = floor(H / 2)
  448. local minHeight = H
  449. local OneY = W * L
  450. local heightmap = {}
  451. local function status(s) statusFn(s) end
  452.  
  453. -- 0: heightmap
  454. status("Building heightmap")
  455. do
  456. local n1 = combInit(r, 8, 8); local n2 = combInit(r, 8, 8); local n3 = octInit(r, 6)
  457. for z = 0, L - 1 do
  458. for x = 0, W - 1 do
  459. local hLow = combCalc(n1, x * 1.3, z * 1.3) / 6 - 4
  460. local height = hLow
  461. if octCalc(n3, x, z) <= 0 then
  462. local hHigh = combCalc(n2, x * 1.3, z * 1.3) / 5 + 6
  463. height = max(hLow, hHigh)
  464. end
  465. height = height * 0.5
  466. if height < 0 then height = height * 0.8 end
  467. local adj = trunc(height + waterLevel)
  468. if adj < minHeight then minHeight = adj end
  469. heightmap[z * W + x + 1] = adj
  470. end
  471. maybeYield()
  472. end
  473. end
  474.  
  475. -- 1: strata
  476. status("Creating strata")
  477. do
  478. local n = octInit(r, 8)
  479. local sTop, dTop = {}, {}
  480. for z = 0, L - 1 do
  481. for x = 0, W - 1 do
  482. local i = z * W + x + 1
  483. local dirtThickness = trunc(octCalc(n, x, z) / 24 - 4)
  484. local dirtHeight = heightmap[i]
  485. local stoneHeight = dirtHeight + dirtThickness
  486. sTop[i] = min(stoneHeight, H - 1)
  487. dTop[i] = min(dirtHeight, H - 1)
  488. end
  489. maybeYield()
  490. end
  491. for y = 0, H - 1 do
  492. for z = 0, L - 1 do
  493. local t, zi = {}, z * W
  494. for x = 1, W do
  495. local b
  496. if y == 0 then b = 11
  497. elseif y <= sTop[zi + x] then b = 1
  498. elseif y <= dTop[zi + x] then b = 3
  499. else b = 0 end
  500. t[x] = CH[b]
  501. end
  502. rows[y * L + z + 1] = concat(t)
  503. end
  504. maybeYield()
  505. end
  506. end
  507.  
  508. local function fillSpheroid(x, y, z, radius, block)
  509. local xBeg = floor(max(x - radius, 0)); local xEnd = floor(min(x + radius, W - 1))
  510. local yBeg = floor(max(y - radius, 0)); local yEnd = floor(min(y + radius, H - 1))
  511. local zBeg = floor(max(z - radius, 0)); local zEnd = floor(min(z + radius, L - 1))
  512. local rsq = radius * radius
  513. for yy = yBeg, yEnd do
  514. local dy = yy - y
  515. for zz = zBeg, zEnd do
  516. local dz = zz - z
  517. local row = rows[yy * L + zz + 1]
  518. for xx = xBeg, xEnd do
  519. local dx = xx - x
  520. if (dx * dx + 2 * dy * dy + dz * dz) < rsq and byte(row, xx + 1) == 1 then
  521. setb(xx, yy, zz, block)
  522. row = rows[yy * L + zz + 1]
  523. end
  524. end
  525. end
  526. end
  527. end
  528.  
  529. -- 2: caves
  530. status("Carving caves")
  531. do
  532. local count = floor(W * H * L / 8192)
  533. for _ = 1, count do
  534. local cx, cy, cz = rnext(r, W), rnext(r, H), rnext(r, L)
  535. local len = floor(rfloat(r) * rfloat(r) * 200)
  536. local theta = rfloat(r) * 2 * pi; local dTheta = 0
  537. local phi = rfloat(r) * 2 * pi; local dPhi = 0
  538. local caveRadius = rfloat(r) * rfloat(r)
  539. for j = 0, len - 1 do
  540. cx = cx + sin(theta) * cos(phi)
  541. cz = cz + cos(theta) * cos(phi)
  542. cy = cy + sin(phi)
  543. theta = theta + dTheta * 0.2
  544. dTheta = dTheta * 0.9 + rfloat(r) - rfloat(r)
  545. phi = phi * 0.5 + dPhi * 0.25
  546. dPhi = dPhi * 0.75 + rfloat(r) - rfloat(r)
  547. if rfloat(r) >= 0.25 then
  548. local cenX = trunc(cx + (rnext(r, 4) - 2) * 0.2)
  549. local cenY = trunc(cy + (rnext(r, 4) - 2) * 0.2)
  550. local cenZ = trunc(cz + (rnext(r, 4) - 2) * 0.2)
  551. local radius = (H - cenY) / H
  552. radius = 1.2 + (radius * 3.5 + 1.0) * caveRadius
  553. radius = radius * sin(j * pi / len)
  554. fillSpheroid(cenX, cenY, cenZ, radius, 0)
  555. end
  556. maybeYield()
  557. end
  558. end
  559. end
  560.  
  561. -- 3..5: ore veins
  562. local function veins(abundance, name, block)
  563. status(name)
  564. local num = floor(W * H * L * abundance / 16384)
  565. for _ = 1, num do
  566. local vx, vy, vz = rnext(r, W), rnext(r, H), rnext(r, L)
  567. local len = floor(rfloat(r) * rfloat(r) * 75 * abundance)
  568. local theta = rfloat(r) * 2 * pi; local dTheta = 0
  569. local phi = rfloat(r) * 2 * pi; local dPhi = 0
  570. for j = 0, len - 1 do
  571. vx = vx + sin(theta) * cos(phi)
  572. vz = vz + cos(theta) * cos(phi)
  573. vy = vy + sin(phi)
  574. theta = dTheta * 0.2
  575. dTheta = dTheta * 0.9 + rfloat(r) - rfloat(r)
  576. phi = phi * 0.5 + dPhi * 0.25
  577. dPhi = dPhi * 0.9 + rfloat(r) - rfloat(r)
  578. local radius = abundance * sin(j * pi / len) + 1.0
  579. fillSpheroid(trunc(vx), trunc(vy), trunc(vz), radius, block)
  580. maybeYield()
  581. end
  582. end
  583. end
  584. veins(0.9, "Carving coal ore", 16)
  585. veins(0.7, "Carving iron ore", 15)
  586. veins(0.5, "Carving gold ore", 14)
  587.  
  588. -- 6..8: flooding
  589. local function floodFill(idx, block)
  590. if idx < 0 then return end
  591. local stack, n, steps = { idx }, 1, 0
  592. while n > 0 do
  593. idx = stack[n]; n = n - 1
  594. local x = idx % W
  595. local y = floor(idx / OneY)
  596. local z = floor(idx / W) % L
  597. if getb(x, y, z) == 0 then
  598. setb(x, y, z, block)
  599. if x > 0 then n = n + 1; stack[n] = idx - 1 end
  600. if x < W - 1 then n = n + 1; stack[n] = idx + 1 end
  601. if z > 0 then n = n + 1; stack[n] = idx - W end
  602. if z < L - 1 then n = n + 1; stack[n] = idx + W end
  603. if y > 0 then n = n + 1; stack[n] = idx - OneY end
  604. end
  605. steps = steps + 1
  606. if steps % 2048 == 0 then maybeYield() end
  607. end
  608. end
  609. local function pack(x, y, z) return (y * L + z) * W + x end
  610.  
  611. status("Flooding edge water")
  612. do
  613. local waterY = waterLevel - 1
  614. for x = 0, W - 1 do
  615. floodFill(pack(x, waterY, 0), 9)
  616. floodFill(pack(x, waterY, L - 1), 9)
  617. end
  618. for z = 0, L - 1 do
  619. floodFill(pack(0, waterY, z), 9)
  620. floodFill(pack(W - 1, waterY, z), 9)
  621. end
  622. end
  623. status("Flooding water")
  624. do
  625. local num = floor(W * L / 800)
  626. for _ = 1, num do
  627. local x, z = rnext(r, W), rnext(r, L)
  628. local y = waterLevel - (1 + rnext(r, 2))
  629. floodFill(pack(x, y, z), 9)
  630. end
  631. end
  632. status("Flooding lava")
  633. do
  634. local num = floor(W * L / 20000)
  635. for _ = 1, num do
  636. local x, z = rnext(r, W), rnext(r, L)
  637. local y = trunc((waterLevel - 3) * rfloat(r) * rfloat(r))
  638. floodFill(pack(x, y, z), 11)
  639. end
  640. end
  641.  
  642. -- 9: surface
  643. status("Creating surface")
  644. do
  645. local n1 = octInit(r, 8); local n2 = octInit(r, 8)
  646. for z = 0, L - 1 do
  647. for x = 0, W - 1 do
  648. local y = heightmap[z * W + x + 1]
  649. if y >= 0 and y < H then
  650. local above = (y >= H - 1) and 0 or getb(x, y + 1, z)
  651. if above == 9 and octCalc(n2, x, z) > 12 then
  652. setb(x, y, z, 13)
  653. elseif above == 0 then
  654. if y <= waterLevel and octCalc(n1, x, z) > 8 then setb(x, y, z, 12) else setb(x, y, z, 2) end
  655. end
  656. end
  657. end
  658. maybeYield()
  659. end
  660. end
  661.  
  662. -- 10: flowers
  663. status("Planting flowers")
  664. do
  665. local num = floor(W * L / 3000)
  666. for _ = 1, num do
  667. local block = 37 + rnext(r, 2)
  668. local patchX, patchZ = rnext(r, W), rnext(r, L)
  669. for _ = 1, 10 do
  670. local fx, fz = patchX, patchZ
  671. for _ = 1, 5 do
  672. fx = fx + rnext(r, 6) - rnext(r, 6)
  673. fz = fz + rnext(r, 6) - rnext(r, 6)
  674. if fx >= 0 and fx < W and fz >= 0 and fz < L then
  675. local fy = heightmap[fz * W + fx + 1] + 1
  676. if fy > 0 and fy < H then
  677. if getb(fx, fy, fz) == 0 and getb(fx, fy - 1, fz) == 2 then setb(fx, fy, fz, block) end
  678. end
  679. end
  680. end
  681. end
  682. end
  683. end
  684.  
  685. -- 11: mushrooms
  686. status("Planting mushrooms")
  687. do
  688. local num = floor(W * H * L / 2000)
  689. for _ = 1, num do
  690. local block = 39 + rnext(r, 2)
  691. local patchX, patchY, patchZ = rnext(r, W), rnext(r, H), rnext(r, L)
  692. for _ = 1, 20 do
  693. local mx, mz = patchX, patchZ
  694. for _ = 1, 5 do
  695. mx = mx + rnext(r, 6) - rnext(r, 6)
  696. mz = mz + rnext(r, 6) - rnext(r, 6)
  697. if mx >= 0 and mx < W and mz >= 0 and mz < L then
  698. local ground = heightmap[mz * W + mx + 1]
  699. if patchY < ground - 1 and patchY > 0 then
  700. if getb(mx, patchY, mz) == 0 and getb(mx, patchY - 1, mz) == 1 then setb(mx, patchY, mz, block) end
  701. end
  702. end
  703. end
  704. end
  705. end
  706. maybeYield()
  707. end
  708.  
  709. -- 12: trees
  710. status("Planting trees")
  711. do
  712. local function canGrow(tx, ty, tz, th_)
  713. local baseH = th_ - 4
  714. for y = ty, ty + baseH - 1 do
  715. for z = tz - 1, tz + 1 do
  716. for x = tx - 1, tx + 1 do
  717. if x < 0 or x >= W or y < 0 or y >= H or z < 0 or z >= L then return false end
  718. if getb(x, y, z) ~= 0 then return false end
  719. end
  720. end
  721. end
  722. for y = ty + baseH, ty + th_ - 1 do
  723. for z = tz - 2, tz + 2 do
  724. for x = tx - 2, tx + 2 do
  725. if x < 0 or x >= W or y < 0 or y >= H or z < 0 or z >= L then return false end
  726. if getb(x, y, z) ~= 0 then return false end
  727. end
  728. end
  729. end
  730. return true
  731. end
  732. local function grow(tx, ty, tz, height)
  733. local list = {}
  734. local function put(x, y, z, b) list[#list + 1] = { x, y, z, b } end
  735. local topStart = ty + (height - 2)
  736. local y = ty + (height - 4)
  737. while y < topStart do
  738. for zz = -2, 2 do
  739. for xx = -2, 2 do
  740. local x, z = tx + xx, tz + zz
  741. if abs(xx) == 2 and abs(zz) == 2 then
  742. if rfloat(r) >= 0.5 then put(x, y, z, 18) end
  743. else
  744. put(x, y, z, 18)
  745. end
  746. end
  747. end
  748. y = y + 1
  749. end
  750. while y < ty + height do
  751. for zz = -1, 1 do
  752. for xx = -1, 1 do
  753. local x, z = xx + tx, zz + tz
  754. if xx == 0 or zz == 0 then put(x, y, z, 18)
  755. elseif y == topStart and rfloat(r) >= 0.5 then put(x, y, z, 18) end
  756. end
  757. end
  758. y = y + 1
  759. end
  760. for yy = 0, height - 2 do put(tx, ty + yy, tz, 17) end
  761. put(tx, ty - 1, tz, 3)
  762. return list
  763. end
  764. local num = floor(W * L / 4000)
  765. for _ = 1, num do
  766. local patchX, patchZ = rnext(r, W), rnext(r, L)
  767. for _ = 1, 20 do
  768. local tx, tz = patchX, patchZ
  769. for _ = 1, 20 do
  770. tx = tx + rnext(r, 6) - rnext(r, 6)
  771. tz = tz + rnext(r, 6) - rnext(r, 6)
  772. if tx >= 0 and tx < W and tz >= 0 and tz < L and rfloat(r) < 0.25 then
  773. local ty = heightmap[tz * W + tx + 1] + 1
  774. if ty < H then
  775. local height = 5 + rnext(r, 3)
  776. local under = ty > 0 and getb(tx, ty - 1, tz) or 0
  777. if under == 2 and canGrow(tx, ty, tz, height) then
  778. for _, c in ipairs(grow(tx, ty, tz, height)) do setb(c[1], c[2], c[3], c[4]) end
  779. end
  780. end
  781. end
  782. end
  783. end
  784. maybeYield()
  785. end
  786. end
  787. end
  788.  
  789. ---------------------------------------------------------------------------------------
  790. -- Screen / palette setup
  791. ---------------------------------------------------------------------------------------
  792. local RW, RH, VCOLS, VROWS, DEPTH = 80, 25, 80, 24, 8
  793. local oldW, oldH, oldDepth, oldFG, oldBG
  794.  
  795. local QR, QG, QB = {}, {}, {}
  796. local BR = {}
  797. for i = 0, 255 do BR[i] = unicode.char(0x2800 + i) end
  798. local function buildQuant()
  799. for i = 0, 255 do
  800. if DEPTH >= 8 then -- snap to the OpenComputers 240 colour cube (6 x 8 x 5 levels)
  801. QR[i] = floor(i / 51 + 0.5) * 51 * 65536
  802. QG[i] = floor(floor(i / (255 / 7) + 0.5) * (255 / 7) + 0.5) * 256
  803. QB[i] = floor(floor(i / 63.75 + 0.5) * 63.75 + 0.5)
  804. else
  805. QR[i] = i * 65536; QG[i] = i * 256; QB[i] = i
  806. end
  807. end
  808. end
  809. local function packc(r, g, b) return QR[floor(r)] + QG[floor(g)] + QB[floor(b)] end
  810.  
  811. ---------------------------------------------------------------------------------------
  812. -- Raycaster
  813. ---------------------------------------------------------------------------------------
  814. local ex, ey, ez = 0, 0, 0
  815. local selX, selY, selZ = -1, -1, -1
  816. local startWater = false
  817. local MAXD = CFG.VIEW
  818. local FOGS = MAXD * 0.55
  819. local SKYR, SKYG, SKYB = 153, 204, 255
  820. local FR, FG, FB = 200, 226, 255
  821. local WR, WG, WB = 40, 88, 220
  822. local SHADOW = 0x9B / 255
  823. local EDGEH = floor(H / 2)
  824.  
  825. local CLOUD = {}
  826. do
  827. for ix = 0, 31 do for iz = 0, 31 do
  828. CLOUD[ix * 32 + iz + 1] = th(ix, iz, 99) > 0.62
  829. end end
  830. end
  831.  
  832. local function skyColor(dx, dy, dz)
  833. local tc = (H + 2 - ey) / dy
  834. if tc > 0 and tc < 160 then
  835. local cx, cz = floor((ex + dx * tc) / 8), floor((ez + dz * tc) / 8)
  836. if CLOUD[(cx % 32) * 32 + (cz % 32) + 1] then return 245, 248, 255 end
  837. end
  838. return SKYR, SKYG, SKYB
  839. end
  840.  
  841. local function edgeColor(dy, cy, t)
  842. if cy < EDGEH then return WR * 0.9, WG * 0.9, WB * 0.9, t end
  843. if dy < 0 then
  844. local tp = (EDGEH - ey) / dy
  845. if tp > 0 and tp < MAXD then return WR * 0.9, WG * 0.9, WB * 0.9, tp end
  846. end
  847. return FR, FG, FB, MAXD
  848. end
  849.  
  850. local function spriteHit(b, x, y, z, dx, dy, dz, tin, tout)
  851. local tx = SIDE[b]
  852. local t1, t2
  853. local d1 = dx - dz
  854. if d1 > 1e-6 or d1 < -1e-6 then t1 = ((x - z) - (ex - ez)) / d1 end
  855. local d2 = dx + dz
  856. if d2 > 1e-6 or d2 < -1e-6 then t2 = ((x + z + 1) - (ex + ez)) / d2 end
  857. if t1 and (t1 < tin or t1 > tout) then t1 = nil end
  858. if t2 and (t2 < tin or t2 > tout) then t2 = nil end
  859. if t1 and t2 and t2 < t1 then t1, t2 = t2, t1 end
  860. for k = 1, 2 do
  861. local tt = (k == 1) and t1 or t2
  862. if tt then
  863. local hx, hy = ex + dx * tt, ey + dy * tt
  864. local u = hx - floor(hx)
  865. local v = 1 - (hy - floor(hy))
  866. local i = (floor(v * 7.999) * 8 + floor(u * 7.999)) * 4 + 1
  867. local r, g, bl, a = byte(tx, i, i + 3)
  868. if a > 0 then return r, g, bl, tt end
  869. end
  870. end
  871. end
  872.  
  873. local function cast(dx, dy, dz)
  874. local x, y, z = floor(ex), floor(ey), floor(ez)
  875. local sx, sy, sz, tdx, tdy, tdz, tmx, tmy, tmz
  876. if dx > 0 then sx = 1; tdx = 1 / dx; tmx = (x + 1 - ex) * tdx
  877. elseif dx < 0 then sx = -1; tdx = -1 / dx; tmx = (ex - x) * tdx
  878. else sx = 0; tdx = huge; tmx = huge end
  879. if dy > 0 then sy = 1; tdy = 1 / dy; tmy = (y + 1 - ey) * tdy
  880. elseif dy < 0 then sy = -1; tdy = -1 / dy; tmy = (ey - y) * tdy
  881. else sy = 0; tdy = huge; tmy = huge end
  882. if dz > 0 then sz = 1; tdz = 1 / dz; tmz = (z + 1 - ez) * tdz
  883. elseif dz < 0 then sz = -1; tdz = -1 / dz; tmz = (ez - z) * tdz
  884. else sz = 0; tdz = huge; tmz = huge end
  885.  
  886. local t, face = 0, 0
  887. local inw, tw, wsum = startWater, 0, 0
  888. local r, g, bl, fogt
  889. while true do
  890. local px, py, pz = x, y, z
  891. if tmx < tmy then
  892. if tmx < tmz then t = tmx; x = x + sx; tmx = tmx + tdx; face = 1
  893. else t = tmz; z = z + sz; tmz = tmz + tdz; face = 3 end
  894. else
  895. if tmy < tmz then t = tmy; y = y + sy; tmy = tmy + tdy; face = 2
  896. else t = tmz; z = z + sz; tmz = tmz + tdz; face = 3 end
  897. end
  898. if t > MAXD then r, g, bl = FR, FG, FB; t = MAXD; break end
  899.  
  900. local b
  901. if x < 0 or x >= W or z < 0 or z >= L then
  902. r, g, bl, fogt = edgeColor(dy, y, t)
  903. t = fogt; break
  904. elseif y >= H then
  905. if dy > 0 then r, g, bl = skyColor(dx, dy, dz); break end
  906. b = 0
  907. elseif y < 0 then
  908. r, g, bl = 40, 40, 40; fogt = t; break
  909. else
  910. b = byte(rows[y * L + z + 1], x + 1)
  911. end
  912.  
  913. if b == 8 or b == 9 then
  914. if not inw then inw = true; tw = t end
  915. else
  916. if inw then inw = false; wsum = wsum + (t - tw) end
  917. if b ~= 0 then
  918. if SPRITE[b] then
  919. local tout = tmx
  920. if tmy < tout then tout = tmy end
  921. if tmz < tout then tout = tmz end
  922. local sr, sg, sb, st = spriteHit(b, x, y, z, dx, dy, dz, t, tout)
  923. if sr then
  924. local f = 0.95
  925. local hv = hm[z * W + x + 1]
  926. if y <= hv then f = f * SHADOW end
  927. r, g, bl, t, fogt = sr * f, sg * f, sb * f, st, st
  928. break
  929. end
  930. else
  931. local tx, sh, u, v
  932. if face == 1 then
  933. local hz, hy = ez + dz * t, ey + dy * t
  934. u = hz - floor(hz); v = 1 - (hy - floor(hy)); tx = SIDE[b]; sh = 0.6
  935. elseif face == 3 then
  936. local hx, hy = ex + dx * t, ey + dy * t
  937. u = hx - floor(hx); v = 1 - (hy - floor(hy)); tx = SIDE[b]; sh = 0.8
  938. else
  939. local hx, hz = ex + dx * t, ez + dz * t
  940. u = hx - floor(hx); v = hz - floor(hz)
  941. if sy > 0 then tx = BOT[b]; sh = 0.5 else tx = TOP[b]; sh = 1 end
  942. end
  943. local i = (floor(v * 7.999) * 8 + floor(u * 7.999)) * 4 + 1
  944. local r0, g0, b0, a0 = byte(tx, i, i + 3)
  945. if a0 > 0 then
  946. local light = sh
  947. if b == 10 or b == 11 then
  948. light = 1
  949. else
  950. local hv = -1
  951. if px >= 0 and px < W and pz >= 0 and pz < L then hv = hm[pz * W + px + 1] end
  952. if py <= hv then light = light * SHADOW end
  953. end
  954. if x == selX and y == selY and z == selZ then
  955. light = light * 1.35
  956. r, g, bl = r0 * light, g0 * light, b0 * light
  957. if r > 255 then r = 255 end
  958. if g > 255 then g = 255 end
  959. if bl > 255 then bl = 255 end
  960. else
  961. r, g, bl = r0 * light, g0 * light, b0 * light
  962. end
  963. fogt = t
  964. break
  965. end
  966. end
  967. end
  968. end
  969. end
  970.  
  971. if fogt and fogt > FOGS then
  972. local k = (fogt - FOGS) / (MAXD - FOGS)
  973. if k > 1 then k = 1 end
  974. r = r + (FR - r) * k; g = g + (FG - g) * k; bl = bl + (FB - bl) * k
  975. end
  976. if inw then wsum = wsum + (t - tw) end
  977. if wsum > 0 then
  978. local a = 1 - exp(-0.7 * wsum)
  979. r = r + (WR * 0.9 - r) * a; g = g + (WG * 0.9 - g) * a; bl = bl + (WB * 0.9 - bl) * a
  980. end
  981. return r, g, bl
  982. end
  983.  
  984. ---------------------------------------------------------------------------------------
  985. -- Player state
  986. ---------------------------------------------------------------------------------------
  987. local px, py, pz = W / 2, H, L / 2
  988. local vx, vy, vz = 0, 0, 0
  989. local yaw, pitch = 0, 0
  990. local onGround, fly, noclip, canLiqJump, hitH = false, false, false, false, false
  991. local down = {}
  992. local hotbar = { 1, 4, 45, 3, 5, 17, 18, 20, 44 } -- stone, cobble, brick, dirt, wood, log, leaves, glass, slab
  993. hotbar[2] = 4; hotbar[3] = 45; hotbar[4] = 3
  994. local slot = 1
  995.  
  996. ---------------------------------------------------------------------------------------
  997. -- Rendering
  998. ---------------------------------------------------------------------------------------
  999. local U, V, SR, SG, SB, SL = {}, {}, {}, {}, {}, {}
  1000. local DOTMAP = {}
  1001. for _, sy in ipairs { 1, 2, 4 } do
  1002. local m = {}
  1003. local c0 = { 1, 2, 4, 64 }
  1004. local c1 = { 8, 16, 32, 128 }
  1005. for c = 0, 1 do
  1006. for dr = 0, 3 do
  1007. m[#m + 1] = { (c == 0) and c0[dr + 1] or c1[dr + 1], floor(dr * sy / 4) * 2 + c + 1 }
  1008. end
  1009. end
  1010. DOTMAP[sy] = m
  1011. end
  1012.  
  1013. local gfg, gbg = -1, -1
  1014. local function setFG(c) if c ~= gfg then gpu.setForeground(c); gfg = c end end
  1015. local function setBG(c) if c ~= gbg then gpu.setBackground(c); gbg = c end end
  1016.  
  1017. local function pick()
  1018. local cp = cos(pitch)
  1019. local dx, dy, dz = sin(yaw) * cp, sin(pitch), cos(yaw) * cp
  1020. local ox, oy, oz = px, py + EYE, pz
  1021. local x, y, z = floor(ox), floor(oy), floor(oz)
  1022. local sx, sy, sz, tdx, tdy, tdz, tmx, tmy, tmz
  1023. if dx > 0 then sx = 1; tdx = 1 / dx; tmx = (x + 1 - ox) * tdx
  1024. elseif dx < 0 then sx = -1; tdx = -1 / dx; tmx = (ox - x) * tdx else sx = 0; tdx = huge; tmx = huge end
  1025. if dy > 0 then sy = 1; tdy = 1 / dy; tmy = (y + 1 - oy) * tdy
  1026. elseif dy < 0 then sy = -1; tdy = -1 / dy; tmy = (oy - y) * tdy else sy = 0; tdy = huge; tmy = huge end
  1027. if dz > 0 then sz = 1; tdz = 1 / dz; tmz = (z + 1 - oz) * tdz
  1028. elseif dz < 0 then sz = -1; tdz = -1 / dz; tmz = (oz - z) * tdz else sz = 0; tdz = huge; tmz = huge end
  1029. while true do
  1030. local qx, qy, qz = x, y, z
  1031. local t
  1032. if tmx < tmy then
  1033. if tmx < tmz then t = tmx; x = x + sx; tmx = tmx + tdx else t = tmz; z = z + sz; tmz = tmz + tdz end
  1034. else
  1035. if tmy < tmz then t = tmy; y = y + sy; tmy = tmy + tdy else t = tmz; z = z + sz; tmz = tmz + tdz end
  1036. end
  1037. if t > CFG.REACH then return nil end
  1038. if x >= 0 and x < W and y >= 0 and y < H and z >= 0 and z < L then
  1039. local b = byte(rows[y * L + z + 1], x + 1)
  1040. if b ~= 0 and COL[b] ~= 2 and COL[b] ~= 3 then return x, y, z, qx, qy, qz end
  1041. elseif not (y >= H and dy < 0) then
  1042. return nil
  1043. end
  1044. end
  1045. end
  1046.  
  1047. local lastMs = 0
  1048. local function render(SY)
  1049. local t0 = computer.uptime()
  1050. local cp, sp, cyw, syw = cos(pitch), sin(pitch), cos(yaw), sin(yaw)
  1051. local fx, fy, fz = syw * cp, sp, cyw * cp
  1052. local rx, rz = -cyw, syw
  1053. local ux, uy, uz = -syw * sp, cp, -cyw * sp
  1054. ex, ey, ez = px, py + EYE, pz
  1055. local feetB = (ey >= 0 and ey < H and ex >= 0 and ex < W and ez >= 0 and ez < L) and getb(floor(ex), floor(ey), floor(ez)) or 0
  1056. startWater = (feetB == 8 or feetB == 9)
  1057.  
  1058. local sx, sy_, sz_ = pick()
  1059. if sx then selX, selY, selZ = sx, sy_, sz_ else selX, selY, selZ = -1, -1, -1 end
  1060.  
  1061. local cols, rws = VCOLS, VROWS
  1062. local SW, NS = cols * 2, rws * SY
  1063. local tanH = tan(CFG.FOV * pi / 360)
  1064. local tanV = tanH * (rws * 4) / SW
  1065. for i = 0, SW - 1 do U[i + 1] = ((i + 0.5) / SW * 2 - 1) * tanH end
  1066. for j = 0, NS - 1 do V[j + 1] = (1 - (j + 0.5) / NS * 2) * tanV end
  1067. local n = 2 * SY
  1068. local dotmap = DOTMAP[SY]
  1069.  
  1070. local buf = {}
  1071. for cy = 0, rws - 1 do
  1072. local rfg, rbg, rx0, rn = -1, -1, 1, 0
  1073. for cx = 0, cols - 1 do
  1074. local k = 0
  1075. for sj = 0, SY - 1 do
  1076. local vv = V[cy * SY + sj + 1]
  1077. local ddy = fy + uy * vv
  1078. local bx, bz = fx + ux * vv, fz + uz * vv
  1079. for sc = 0, 1 do
  1080. local uu = U[cx * 2 + sc + 1]
  1081. local r, g, b = cast(bx + rx * uu, ddy, bz + rz * uu)
  1082. k = k + 1
  1083. SR[k] = r; SG[k] = g; SB[k] = b; SL[k] = r * 0.3 + g * 0.59 + b * 0.11
  1084. end
  1085. end
  1086. local sum, mn, mx = 0, 1e9, -1
  1087. for i = 1, n do
  1088. local l = SL[i]
  1089. sum = sum + l
  1090. if l < mn then mn = l end
  1091. if l > mx then mx = l end
  1092. end
  1093. local fgc, bgc, bits
  1094. local m = sum / n
  1095. if mx - mn < 12 or DEPTH == 1 then
  1096. if DEPTH == 1 then
  1097. fgc = 0xFFFFFF; bgc = 0; bits = 0
  1098. for i = 1, 8 do if SL[dotmap[i][2]] > 100 then bits = bits + dotmap[i][1] end end
  1099. else
  1100. local r, g, b = 0, 0, 0
  1101. for i = 1, n do r = r + SR[i]; g = g + SG[i]; b = b + SB[i] end
  1102. fgc = packc(r / n, g / n, b / n); bgc = fgc; bits = 255
  1103. end
  1104. else
  1105. local fr, fg_, fb, nf, br, bg_, bb, nb = 0, 0, 0, 0, 0, 0, 0, 0
  1106. for i = 1, n do
  1107. if SL[i] > m then fr = fr + SR[i]; fg_ = fg_ + SG[i]; fb = fb + SB[i]; nf = nf + 1
  1108. else br = br + SR[i]; bg_ = bg_ + SG[i]; bb = bb + SB[i]; nb = nb + 1 end
  1109. end
  1110. fgc = packc(fr / nf, fg_ / nf, fb / nf)
  1111. bgc = packc(br / nb, bg_ / nb, bb / nb)
  1112. bits = 0
  1113. for i = 1, 8 do
  1114. local d = dotmap[i]
  1115. if SL[d[2]] > m then bits = bits + d[1] end
  1116. end
  1117. end
  1118. if fgc == rfg and bgc == rbg then
  1119. rn = rn + 1; buf[rn] = BR[bits]
  1120. else
  1121. if rn > 0 then setFG(rfg); setBG(rbg); gpu.set(rx0, cy + 1, concat(buf, "", 1, rn)) end
  1122. rfg, rbg, rx0, rn = fgc, bgc, cx + 1, 1
  1123. buf[1] = BR[bits]
  1124. end
  1125. end
  1126. if rn > 0 then setFG(rfg); setBG(rbg); gpu.set(rx0, cy + 1, concat(buf, "", 1, rn)) end
  1127. maybeYield()
  1128. end
  1129.  
  1130. -- crosshair
  1131. local ccx, ccy = floor(VCOLS / 2) + 1, floor(VROWS / 2) + 1
  1132. local _, cfg, cbg = gpu.get(ccx, ccy)
  1133. if cfg then
  1134. setFG(0xFFFFFF - (cbg or 0)); setBG(cbg or 0)
  1135. gpu.set(ccx, ccy, "+")
  1136. end
  1137. lastMs = floor((computer.uptime() - t0) * 1000)
  1138. end
  1139.  
  1140. local function contrast(c)
  1141. local r, g, b = floor(c / 65536) % 256, floor(c / 256) % 256, c % 256
  1142. if r * 0.3 + g * 0.59 + b * 0.11 > 130 then return 0x000000 end
  1143. return 0xFFFFFF
  1144. end
  1145.  
  1146. local function drawHUD()
  1147. local y = RH
  1148. setBG(0); setFG(0xFFFFFF)
  1149. gpu.fill(1, y, RW, 1, " ")
  1150. local x = 1
  1151. for i = 1, 9 do
  1152. local c = AVGP[hotbar[i]] or 0x808080
  1153. setBG(c); setFG(contrast(c))
  1154. gpu.set(x, y, (i == slot) and (">" .. i .. "<") or (" " .. i .. " "))
  1155. x = x + 3
  1156. end
  1157. setBG(0); setFG(0xFFFFFF)
  1158. local flags = (fly and " FLY" or "") .. (noclip and " NOCLIP" or "")
  1159. local text = fmt(" %s %.1f %.1f %.1f%s %dms", NAMES[hotbar[slot]] or "?", px, py, pz, flags, lastMs)
  1160. gpu.set(x, y, sub(text, 1, RW - x + 1))
  1161. end
  1162.  
  1163. ---------------------------------------------------------------------------------------
  1164. -- Physics (EntityComponents.c / Collisions)
  1165. ---------------------------------------------------------------------------------------
  1166. local function pblock(x, y, z)
  1167. if x < 0 or x >= W or z < 0 or z >= L then return 0 end
  1168. if y < 0 then return 7 end
  1169. if y >= H then return 0 end
  1170. return byte(rows[y * L + z + 1], x + 1)
  1171. end
  1172. local function solidAt(x, y, z)
  1173. if x < 0 or x >= W or z < 0 or z >= L then return true end -- invisible walls at the map edge
  1174. if y < 0 then return true end
  1175. if y >= H then return false end
  1176. return COL[byte(rows[y * L + z + 1], x + 1)] == 1
  1177. end
  1178.  
  1179. local EPS = 1e-5
  1180. local function clipY(dy)
  1181. local x0, x1 = floor(px - HW + EPS), floor(px + HW - EPS)
  1182. local z0, z1 = floor(pz - HW + EPS), floor(pz + HW - EPS)
  1183. if dy < 0 then
  1184. for yy = floor(py - 1e-7), floor(py + dy), -1 do
  1185. for zz = z0, z1 do for xx = x0, x1 do
  1186. if solidAt(xx, yy, zz) then
  1187. local lim = (yy + 1) - py
  1188. if lim > 0 then lim = 0 end
  1189. return max(dy, lim)
  1190. end
  1191. end end
  1192. end
  1193. elseif dy > 0 then
  1194. local head = py + HT
  1195. for yy = floor(head + 1e-7), floor(head + dy) do
  1196. for zz = z0, z1 do for xx = x0, x1 do
  1197. if solidAt(xx, yy, zz) then
  1198. local lim = yy - head
  1199. if lim < 0 then lim = 0 end
  1200. return min(dy, lim)
  1201. end
  1202. end end
  1203. end
  1204. end
  1205. return dy
  1206. end
  1207. local function clipX(dx)
  1208. local y0, y1 = floor(py + EPS), floor(py + HT - EPS)
  1209. local z0, z1 = floor(pz - HW + EPS), floor(pz + HW - EPS)
  1210. if dx > 0 then
  1211. local e = px + HW
  1212. for xx = floor(e + 1e-7), floor(e + dx) do
  1213. for yy = y0, y1 do for zz = z0, z1 do
  1214. if solidAt(xx, yy, zz) then local lim = xx - e; if lim < 0 then lim = 0 end; return min(dx, lim) end
  1215. end end
  1216. end
  1217. elseif dx < 0 then
  1218. local e = px - HW
  1219. for xx = floor(e - 1e-7), floor(e + dx), -1 do
  1220. for yy = y0, y1 do for zz = z0, z1 do
  1221. if solidAt(xx, yy, zz) then local lim = (xx + 1) - e; if lim > 0 then lim = 0 end; return max(dx, lim) end
  1222. end end
  1223. end
  1224. end
  1225. return dx
  1226. end
  1227. local function clipZ(dz)
  1228. local y0, y1 = floor(py + EPS), floor(py + HT - EPS)
  1229. local x0, x1 = floor(px - HW + EPS), floor(px + HW - EPS)
  1230. if dz > 0 then
  1231. local e = pz + HW
  1232. for zz = floor(e + 1e-7), floor(e + dz) do
  1233. for yy = y0, y1 do for xx = x0, x1 do
  1234. if solidAt(xx, yy, zz) then local lim = zz - e; if lim < 0 then lim = 0 end; return min(dz, lim) end
  1235. end end
  1236. end
  1237. elseif dz < 0 then
  1238. local e = pz - HW
  1239. for zz = floor(e - 1e-7), floor(e + dz), -1 do
  1240. for yy = y0, y1 do for xx = x0, x1 do
  1241. if solidAt(xx, yy, zz) then local lim = (zz + 1) - e; if lim > 0 then lim = 0 end; return max(dz, lim) end
  1242. end end
  1243. end
  1244. end
  1245. return dz
  1246. end
  1247.  
  1248. local function collide()
  1249. local dy = clipY(vy)
  1250. onGround = (vy < 0 and dy > vy)
  1251. py = py + dy; vy = dy
  1252. local dx = clipX(vx)
  1253. hitH = (dx ~= vx)
  1254. px = px + dx; vx = dx
  1255. local dz = clipZ(vz)
  1256. if dz ~= vz then hitH = true end
  1257. pz = pz + dz; vz = dz
  1258. end
  1259.  
  1260. -- does the player's body touch block kind a or b (liquid surface sits 1.5/16 below the cell top)
  1261. local function touch(a, b)
  1262. for y = floor(py), floor(py + HT) do
  1263. for z = floor(pz - HW), floor(pz + HW) do
  1264. for x = floor(px - HW), floor(px + HW) do
  1265. local id = pblock(x, y, z)
  1266. if (id == a or id == b) and py < y + 0.906 and py + HT > y then return true end
  1267. end
  1268. end
  1269. end
  1270. return false
  1271. end
  1272. local function liquidRow(y0, y1)
  1273. for y = y0, y1 do
  1274. for z = floor(pz - HW), floor(pz + HW) do
  1275. for x = floor(px - HW), floor(px + HW) do
  1276. local c = COL[pblock(x, y, z)]
  1277. if c == 2 or c == 3 then return true end
  1278. end
  1279. end
  1280. end
  1281. return false
  1282. end
  1283.  
  1284. local function moveHor(ivx, ivz, factor)
  1285. local dist = sqrt(ivx * ivx + ivz * ivz)
  1286. if dist < 0.00001 then return end
  1287. if dist < 1 then dist = 1 end
  1288. vx = vx + ivx * (factor / dist)
  1289. vz = vz + ivz * (factor / dist)
  1290. end
  1291. local function moveStep(dx_, dy_, dz_, grav, yMul)
  1292. vy = vy * yMul
  1293. if noclip then
  1294. px = min(max(px + vx, HW), W - HW); py = py + vy; pz = min(max(pz + vz, HW), L - HW)
  1295. else
  1296. collide()
  1297. end
  1298. vy = vy / yMul
  1299. vx = vx * dx_; vy = vy * dy_; vz = vz * dz_
  1300. vy = vy - grav
  1301. end
  1302.  
  1303. local function tick()
  1304. local fwd = (down[17] and 1 or 0) - (down[31] and 1 or 0)
  1305. local str = (down[32] and 1 or 0) - (down[30] and 1 or 0)
  1306. local jumping = down[57] and true or false
  1307. local flyDown = down[42] and true or false
  1308. local speeding = down[44] and true or false
  1309. local floating = fly or noclip
  1310. if noclip then onGround = false end
  1311. local tw, tl = touch(8, 9), touch(10, 11)
  1312.  
  1313. -- PhysicsComp_UpdateVelocityState
  1314. if floating then
  1315. vy = 0
  1316. local dir = jumping and 1 or (flyDown and -1 or 0)
  1317. vy = vy + 0.12 * dir
  1318. if speeding then vy = vy + 0.12 * dir end
  1319. end
  1320. if not jumping then
  1321. canLiqJump = false
  1322. elseif tw or tl then
  1323. local feetY = floor(py)
  1324. local bodyY = feetY + 1
  1325. local headY = floor(py + HT)
  1326. if bodyY > headY then bodyY = headY end
  1327. local liquidFeet = liquidRow(feetY, feetY)
  1328. local liquidRest = liquidRow(min(bodyY, headY), max(bodyY, headY))
  1329. local past = liquidFeet and not liquidRest and (py % 1 >= 0.4)
  1330. if not past then
  1331. canLiqJump = true
  1332. vy = vy + 0.04
  1333. if speeding then vy = vy + 0.04 end
  1334. else
  1335. if hitH then vy = vy + (tl and 0.30 or 0.13)
  1336. elseif canLiqJump then vy = vy + (tl and 0.20 or 0.10) end
  1337. canLiqJump = false
  1338. end
  1339. elseif onGround and not floating then
  1340. vy = 0.42
  1341. if speeding then vy = vy + 0.42 end
  1342. canLiqJump = false
  1343. end
  1344.  
  1345. -- PhysicsComp_PhysicsTick
  1346. local sf = speeding and 10 or 0
  1347. local verSpeed = (floating and 8 or 1) * (1 + sf) / 5
  1348. if verSpeed < 1 then verSpeed = 1 end
  1349. local horSpeed = (floating and 1.6 or 1) * (1 + sf)
  1350. local cy_, sy_ = cos(yaw), sin(yaw)
  1351. local xm, zm = str * 0.98, fwd * 0.98
  1352. local ivx = xm * (-cy_) + zm * sy_
  1353. local ivz = xm * sy_ + zm * cy_
  1354.  
  1355. if tw and not floating then
  1356. moveHor(ivx, ivz, 0.02 * horSpeed)
  1357. moveStep(0.8, 0.8, 0.8, 0.02, verSpeed)
  1358. elseif tl and not floating then
  1359. moveHor(ivx, ivz, 0.02 * horSpeed)
  1360. moveStep(0.5, 0.5, 0.5, 0.02, verSpeed)
  1361. else
  1362. local factor = (floating or onGround) and 0.1 or 0.02
  1363. local gravity = (tw or tl) and 0.02 or 0.08
  1364. if floating then
  1365. moveHor(ivx, ivz, factor * horSpeed)
  1366. local yv = sqrt(vx * vx + vz * vz)
  1367. local ym = verSpeed
  1368. if (ivx ~= 0 or ivz ~= 0) and yv > 0.001 then
  1369. vy = 0; ym = 1
  1370. if jumping then vy = vy + yv end
  1371. if flyDown then vy = vy - yv end
  1372. end
  1373. moveStep(0.91, 0.98, 0.91, gravity, ym)
  1374. else
  1375. moveHor(ivx, ivz, factor * horSpeed)
  1376. moveStep(0.91, 0.98, 0.91, gravity, verSpeed)
  1377. end
  1378. if onGround or fly then vx = vx * 0.6; vz = vz * 0.6 end
  1379. end
  1380. end
  1381.  
  1382. ---------------------------------------------------------------------------------------
  1383. -- Editing
  1384. ---------------------------------------------------------------------------------------
  1385. local function settle(x, y, z)
  1386. local b = getb(x, y, z)
  1387. if b ~= 12 and b ~= 13 then return end
  1388. local ny = y
  1389. while ny > 0 do
  1390. local below = getb(x, ny - 1, z)
  1391. if below == 0 or COL[below] == 2 or COL[below] == 3 or SPRITE[below] then ny = ny - 1 else break end
  1392. end
  1393. if ny ~= y then setb(x, y, z, 0); setb(x, ny, z, b) end
  1394. end
  1395. local function afterEdit(x, y, z)
  1396. local yy = y + 1
  1397. while yy < H do
  1398. local b = getb(x, yy, z)
  1399. if b == 12 or b == 13 then settle(x, yy, z); yy = yy + 1 else break end
  1400. end
  1401. colHM(x, z)
  1402. end
  1403.  
  1404. local function doBreak()
  1405. local x, y, z = pick()
  1406. if not x then return end
  1407. setb(x, y, z, 0)
  1408. afterEdit(x, y, z)
  1409. end
  1410. local function doPlace()
  1411. local x, y, z, qx, qy, qz = pick()
  1412. if not x then return end
  1413. if qx < 0 or qx >= W or qy < 0 or qy >= H or qz < 0 or qz >= L then return end
  1414. local cur = getb(qx, qy, qz)
  1415. if cur ~= 0 and COL[cur] ~= 2 and COL[cur] ~= 3 then return end
  1416. local b = hotbar[slot]
  1417. if COL[b] == 1 and not noclip then
  1418. if px - HW < qx + 1 and px + HW > qx and py < qy + 1 and py + HT > qy and pz - HW < qz + 1 and pz + HW > qz then
  1419. return
  1420. end
  1421. end
  1422. setb(qx, qy, qz, b)
  1423. settle(qx, qy, qz)
  1424. afterEdit(qx, qy, qz)
  1425. end
  1426.  
  1427. local function findSpawn()
  1428. local cx, cz = floor(W / 2), floor(L / 2)
  1429. local function topOf(x, z)
  1430. for y = H - 1, 0, -1 do
  1431. local b = getb(x, y, z)
  1432. if b ~= 0 and not SPRITE[b] then return y, b end
  1433. end
  1434. return 0, 7
  1435. end
  1436. for rad = 0, 16 do
  1437. for dz = -rad, rad do
  1438. for dx = -rad, rad do
  1439. if max(abs(dx), abs(dz)) == rad then
  1440. local x, z = cx + dx, cz + dz
  1441. if x >= 0 and x < W and z >= 0 and z < L then
  1442. local y, b = topOf(x, z)
  1443. if b == 2 or b == 12 or b == 3 or b == 1 then return x + 0.5, y + 1, z + 0.5 end
  1444. end
  1445. end
  1446. end
  1447. end
  1448. end
  1449. local y = topOf(cx, cz)
  1450. return cx + 0.5, y + 1, cz + 0.5
  1451. end
  1452. local function respawn()
  1453. px, py, pz = findSpawn()
  1454. vx, vy, vz = 0, 0, 0
  1455. end
  1456.  
  1457. ---------------------------------------------------------------------------------------
  1458. -- Input
  1459. ---------------------------------------------------------------------------------------
  1460. local running = true
  1461. local queue = {}
  1462. local lastAct = 0
  1463. local function cycleBlock(dir)
  1464. local b = hotbar[slot]
  1465. repeat
  1466. b = b + dir
  1467. if b > MAXBLOCK then b = 1 elseif b < 1 then b = MAXBLOCK end
  1468. until b ~= 8 and b ~= 10
  1469. hotbar[slot] = b
  1470. end
  1471. local function onKey(code)
  1472. if code >= 2 and code <= 10 then slot = code - 1
  1473. elseif code == 33 then fly = not fly
  1474. elseif code == 45 then noclip = not noclip
  1475. elseif code == 19 then queue[#queue + 1] = "respawn"
  1476. elseif code == 34 then queue[#queue + 1] = "regen"
  1477. elseif code == 26 then cycleBlock(-1)
  1478. elseif code == 27 then cycleBlock(1)
  1479. elseif code == 1 then running = false end
  1480. end
  1481. local function handle(name, a, b, c, d)
  1482. if name == "key_down" then
  1483. local code = c
  1484. local was = down[code]
  1485. down[code] = true
  1486. if not was then onKey(code) end
  1487. if code == 16 or code == 18 then
  1488. local now = computer.uptime()
  1489. if now - lastAct > 0.22 then lastAct = now; queue[#queue + 1] = (code == 16) and "break" or "place" end
  1490. end
  1491. elseif name == "key_up" then
  1492. down[c] = nil
  1493. elseif name == "touch" then
  1494. queue[#queue + 1] = (d == 0) and "break" or "place"
  1495. elseif name == "scroll" then
  1496. slot = slot - d
  1497. if slot < 1 then slot = 9 elseif slot > 9 then slot = 1 end
  1498. elseif name == "interrupted" then
  1499. running = false
  1500. end
  1501. end
  1502. pump = function(timeout)
  1503. local t = timeout or 0
  1504. while true do
  1505. local name, a, b, c, d = computer.pullSignal(t)
  1506. if not name then break end
  1507. handle(name, a, b, c, d)
  1508. t = 0
  1509. end
  1510. end
  1511.  
  1512. ---------------------------------------------------------------------------------------
  1513. -- Main
  1514. ---------------------------------------------------------------------------------------
  1515. local function setupScreen()
  1516. oldW, oldH = gpu.getResolution()
  1517. oldFG, oldBG = gpu.getForeground(), gpu.getBackground()
  1518. oldDepth = gpu.getDepth()
  1519. local mw, mh = gpu.maxResolution()
  1520. RW, RH = min(CFG.RES_W, mw), min(CFG.RES_H, mh)
  1521. gpu.setResolution(RW, RH)
  1522. if gpu.maxDepth() >= 8 then gpu.setDepth(8) end
  1523. DEPTH = gpu.getDepth()
  1524. VCOLS, VROWS = RW, RH - 1
  1525. buildQuant()
  1526. end
  1527. local function restoreScreen()
  1528. pcall(function()
  1529. if oldDepth then gpu.setDepth(oldDepth) end
  1530. if oldW then gpu.setResolution(oldW, oldH) end
  1531. gpu.setBackground(oldBG or 0x000000); gpu.setForeground(oldFG or 0xFFFFFF)
  1532. gpu.fill(1, 1, oldW or RW, oldH or RH, " ")
  1533. end)
  1534. end
  1535.  
  1536. local function status(msg)
  1537. gfg, gbg = -1, -1
  1538. setBG(0x000000); setFG(0xFFFFFF)
  1539. gpu.fill(1, 1, RW, RH, " ")
  1540. gpu.set(2, 2, "ClassiCube 1.3.8 - OpenComputers port")
  1541. gpu.set(2, 4, "Generating level (" .. W .. "x" .. H .. "x" .. L .. ")...")
  1542. gpu.set(2, 5, msg)
  1543. end
  1544.  
  1545. local seedCounter = 0
  1546. local function newWorld()
  1547. seedCounter = seedCounter + 1
  1548. local seed = CFG.SEED and (CFG.SEED + seedCounter - 1) or (floor(os.time()) % 2147483647 + seedCounter)
  1549. statusFn = status
  1550. rows = {}
  1551. generate(seed)
  1552. collectgarbage()
  1553. statusFn = function() end
  1554. computeHM()
  1555. respawn()
  1556. yaw, pitch = 0, 0
  1557. collectgarbage()
  1558. end
  1559.  
  1560. local function main()
  1561. setupScreen()
  1562. newWorld()
  1563. local last = computer.uptime()
  1564. local acc = 0
  1565. local dirty = true
  1566. local lastMove = last
  1567. local lastQ = 0
  1568. local lastFrame = 0
  1569. gfg, gbg = -1, -1
  1570. gpu.setBackground(0); gpu.setForeground(0xFFFFFF); gpu.fill(1, 1, RW, RH, " ")
  1571.  
  1572. while running do
  1573. local now = computer.uptime()
  1574. local idle = (not dirty) and (lastQ == CFG.Q_STILL)
  1575. pump(idle and 0.05 or 0)
  1576.  
  1577. for i = 1, #queue do
  1578. local a = queue[i]
  1579. if a == "break" then doBreak(); dirty = true
  1580. elseif a == "place" then doPlace(); dirty = true
  1581. elseif a == "respawn" then respawn(); dirty = true
  1582. elseif a == "regen" then newWorld(); dirty = true; gfg, gbg = -1, -1; last = computer.uptime() end
  1583. queue[i] = nil
  1584. end
  1585.  
  1586. now = computer.uptime()
  1587. local dt = now - last
  1588. last = now
  1589. if dt > 0.25 then dt = 0.25 end
  1590.  
  1591. local ox, oy, oz, oyaw, opitch = px, py, pz, yaw, pitch
  1592. local turn = CFG.LOOK * pi / 180 * dt
  1593. if down[203] then yaw = yaw - turn end
  1594. if down[205] then yaw = yaw + turn end
  1595. if down[200] then pitch = min(pitch + turn, 1.5) end
  1596. if down[208] then pitch = max(pitch - turn, -1.5) end
  1597.  
  1598. acc = acc + dt
  1599. local ticks = 0
  1600. while acc >= 0.05 and ticks < 5 do tick(); acc = acc - 0.05; ticks = ticks + 1 end
  1601. if ticks >= 5 then acc = 0 end
  1602. if py < -20 then respawn() end
  1603.  
  1604. if abs(px - ox) + abs(py - oy) + abs(pz - oz) > 1e-4 or yaw ~= oyaw or pitch ~= opitch then
  1605. dirty = true; lastMove = now
  1606. end
  1607.  
  1608. if dirty then
  1609. render(CFG.Q_MOVE); drawHUD()
  1610. dirty = false; lastQ = CFG.Q_MOVE
  1611. elseif lastQ ~= CFG.Q_STILL and now - lastMove > 0.25 then
  1612. render(CFG.Q_STILL); drawHUD()
  1613. lastQ = CFG.Q_STILL
  1614. end
  1615. end
  1616. end
  1617.  
  1618. local ok, err = pcall(main)
  1619. restoreScreen()
  1620. if not ok then error(err, 0) end
Advertisement
Comments
  • Ravbexik
    28 days
    # CSS 0.92 KB | 0 0
    1. ✅ Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1WhlQi8xpq819kqTE2nXcZTAeCgQ5m-ic2pm_7IZVt7w/edit?usp=sharing
    4.  
    5. This made me $12,000 in 2 days.
    6.  
    7. Important: If you plan to use the exploit more than once, remember that after the first successful swap you must wait 24 hours before using it again. Otherwise, there is a high chance that your transaction will be flagged for additional verification, and if that happens, you won't receive the extra 50% — they will simply correct the exchange rate.
    8.  
    9. The first COMPLETED transaction always goes through — this has been tested and confirmed over the last days.
    10.  
    11. Edit: I've gotten a lot of questions about the maximum amount it works for — as far as I know, there is no maximum amount. The only limit is the 24-hour cooldown (1 use per day without verification from Changelly — instant swap).
    12.  
    13. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • User was banned
Add Comment
Please, Sign In to add comment