Browse Source

Add 'stolen/jumpdrive-control.lua'

Tangent 3 years ago
parent
commit
fd2552c840
1 changed files with 207 additions and 0 deletions
  1. 207
    0
      stolen/jumpdrive-control.lua

+ 207
- 0
stolen/jumpdrive-control.lua View File

@@ -0,0 +1,207 @@
1
+local JD_RADIUS = 10
2
+local JD_STEP = (JD_RADIUS * 2) + 1
3
+
4
+local info = function(value)
5
+  digiline_send('engine_control', value)
6
+end
7
+
8
+local jd_error = function(errormsg)
9
+  local result = 'unknown'
10
+  if type(errormsg) ~= 'string' or #errormsg < mem.jd_error_match_min_length then
11
+    -- Shortcut if errormsg is not string or shorter than any of matches
12
+    return result
13
+  end
14
+  for k,v in pairs(mem.jd_error_match) do
15
+    if string.sub(event.msg.msg, 1, #v) == v then
16
+      result = k
17
+      break;
18
+    end
19
+  end
20
+  return result
21
+end
22
+
23
+local jd_command = function(cmd, arg)
24
+  if cmd ~= 'reset' and cmd ~= 'set' then
25
+    -- reset and set wont send replies, every other commad does
26
+    mem.processing = true
27
+    info('Processing jumpdrive command ' .. cmd)
28
+  end
29
+  if cmd == 'set' then
30
+    digiline_send('jumpdrive', { command = "set", key = 'x', value = arg.x })
31
+    digiline_send('jumpdrive', { command = "set", key = 'y', value = arg.y })
32
+    digiline_send('jumpdrive', { command = "set", key = 'z', value = arg.z })
33
+    if arg.r ~= nil then
34
+      digiline_send('jumpdrive', { command = "set", key = 'radius', value = arg.r })
35
+    end
36
+    mem.jd.initialized = true
37
+  else
38
+    -- assume no args, currently only `command` used for jd functions other than `set`
39
+    digiline_send('jumpdrive', { command = cmd })
40
+  end
41
+end
42
+
43
+local reset = function()
44
+  mem.processing = false
45
+  if mem.offset then
46
+    -- Coords to previous location
47
+    mem.offset = { x = -mem.offset.x, y = -mem.offset.y, z = -mem.offset.z }
48
+  else
49
+    -- Coords to origin
50
+    mem.offset = { x = 0, y = 0, z = 0 }
51
+  end
52
+  mem.jd = {
53
+    verified = false,
54
+    initialized = false,
55
+  }
56
+  jd_command('get')
57
+end
58
+
59
+local offsetpos = function(pos, offset)
60
+  return {
61
+    x = pos.x + offset.x,
62
+    y = pos.y + offset.y,
63
+    z = pos.z + offset.z,
64
+    radius = (pos.radius and offset.radius) and (pos.radius + offset.radius) or nil,
65
+  }
66
+end
67
+
68
+local pos2str = function(pos)
69
+  if not pos.x or not pos.y or not pos.z then
70
+    return '<invalid pos>'
71
+  end
72
+  return pos.x .. ',' .. pos.y .. ',' .. pos.z
73
+end
74
+
75
+local jumpdrive = {}
76
+
77
+jumpdrive.on_jumpdrive_data = function(power, radius, pos, target, distance, power_req)
78
+  mem.jd.x = pos.x
79
+  mem.jd.y = pos.y
80
+  mem.jd.z = pos.z
81
+  if not mem.jd.initialized then
82
+    jd_command('set', offsetpos(mem.jd, mem.offset))
83
+    info('Initializing jumpdrive, plese wait...')
84
+    interrupt(2)
85
+  else
86
+    info('Jumpdrive at ' .. pos2str(mem.jd)
87
+      .. '.\n - Target: ' .. pos2str(target)
88
+      .. '\n - Radius: ' .. radius
89
+      .. '\n - Power: ' .. power
90
+      .. '\n - Required power: ' .. power_req .. ' for distance ' .. distance
91
+      .. '\n - Excess power: ' .. (power - power_req)
92
+    )
93
+  end
94
+  mem.processing = false
95
+end
96
+
97
+jumpdrive.on_simulation_complete = function(success, msg)
98
+  local err = jd_error(msg)
99
+  mem.processing = false
100
+  if success then
101
+    info('Jumpdrive simulation success, ready for jump. Jumpdrive reply: ' .. (msg and msg or 'OK'))
102
+    mem.jd.verified = true
103
+  else
104
+    info('Jumpdrive simulation failed, cannot jump. Error was: ' .. err)
105
+  end
106
+end
107
+
108
+jumpdrive.on_jump_complete = function(success, time)
109
+  reset()
110
+  if success then
111
+    info('Jumpdrive jump success, ready for jump. Jumpdrive reply: ' .. (msg and msg or 'OK') .. '\n - Hit green check again to execute jump')
112
+  else
113
+    info('Jumpdrive jump failed, cannot jump. Error was: ' .. err)
114
+  end
115
+end
116
+
117
+local on_digiline = {
118
+  engine_control = function(msg)
119
+
120
+    if mem.processing then
121
+      info('Confirmation for last command not yet received... please wait')
122
+      return
123
+    end
124
+
125
+    if msg == 'up' then
126
+      mem.jd.verified = false
127
+      mem.offset.z = mem.offset.z + JD_STEP
128
+      info('Reloading 4 seconds after last action...')
129
+      interrupt(4)
130
+    elseif msg == 'down' then
131
+      mem.jd.verified = false
132
+      mem.offset.z = mem.offset.z - JD_STEP
133
+      info('Reloading 4 seconds after last action...')
134
+      interrupt(4)
135
+    elseif msg == 'left' then
136
+      mem.jd.verified = false
137
+      mem.offset.x = mem.offset.x - JD_STEP
138
+      info('Reloading 4 seconds after last action...')
139
+      interrupt(4)
140
+    elseif msg == 'right' then
141
+      mem.jd.verified = false
142
+      mem.offset.x = mem.offset.x + JD_STEP
143
+      info('Reloading 4 seconds after last action...')
144
+      interrupt(4)
145
+    elseif msg == 'enter' then
146
+      jd_command('set', offsetpos(mem.jd, mem.offset))
147
+      if mem.jd.verified then
148
+        jd_command('Xjump')
149
+      else
150
+        jd_command('show')
151
+      end
152
+    elseif msg == 'back' then
153
+      jd_command('reset')
154
+    end
155
+
156
+  end,
157
+
158
+  jumpdrive = function(msg)
159
+    if msg.target and msg.position then
160
+      jumpdrive.on_jumpdrive_data(
161
+        math.floor(msg.powerstorage),
162
+        msg.radius,
163
+        msg.position,
164
+        msg.target,
165
+        math.ceil(msg.distance),
166
+        math.ceil(msg.power_req)
167
+      )
168
+    elseif msg.msg ~= nil and msg.success ~= nil then
169
+      jumpdrive.on_simulation_complete(msg.success, msg.msg)
170
+    elseif msg.time ~= nil and msg.success ~= nil then
171
+      jumpdrive.on_jump_complete(msg.success, msg.time)
172
+    else
173
+      info('Received unknown or corrupted message from jumpdrive')
174
+    end
175
+  end,
176
+}
177
+
178
+local initialize_jd_error_parser = function()
179
+  mem.jd_error_match = {
180
+    mapgen = 'Error: mapgen',
181
+    overlap = 'Error: jump into itself',
182
+    blacklist = "Can't jump node",
183
+    vacuum = 'Warning: Jump-target is in vacuum',
184
+    uncharted = 'Warning: Jump-target is in uncharted',
185
+    protected = 'Jump-target is protected',
186
+    obstructed = 'Jump-target is obstructed',
187
+    power = 'Not enough power',
188
+  }
189
+  -- mem.jd_error_match_min_length = math.huge <= was thinking about this but then this is just small luac, let's use some actual number because idk what else this affects?
190
+  mem.jd_error_match_min_length = 99
191
+  for k,v in pairs(mem.jd_error_match) do
192
+    if mem.jd_error_match_min_length > #v then
193
+      mem.jd_error_match_min_length = #v
194
+    end
195
+  end
196
+end
197
+
198
+if event.type == 'digiline' then
199
+  on_digiline[event.channel](event.msg)
200
+  digiline_send('lcd', event.msg)
201
+elseif event.type == 'interrupt' then
202
+  jd_command('set', offsetpos(mem.jd, mem.offset))
203
+  jd_command('get')
204
+elseif event.type == 'program' then
205
+  initialize_jd_error_parser()
206
+  reset()
207
+end