mt-lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
data/std/net/stun.mt
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import std.async as aio
|
|
2
|
+
import std.binary as bin
|
|
3
|
+
import std.bytes as bytes
|
|
4
|
+
import std.crypto as crypto
|
|
5
|
+
import std.fmt as fmt
|
|
6
|
+
import std.net as net
|
|
7
|
+
import std.string as string
|
|
8
|
+
|
|
9
|
+
const google_stun: str = "stun.l.google.com"
|
|
10
|
+
const google_stun_port: int = 19302
|
|
11
|
+
|
|
12
|
+
const stun_magic_cookie: uint = 0x2112A442
|
|
13
|
+
const stun_header_len: ptr_uint = 20
|
|
14
|
+
|
|
15
|
+
const err_tid_failed: int = -1
|
|
16
|
+
const err_packet_too_small: int = -2
|
|
17
|
+
const err_not_binding_response: int = -3
|
|
18
|
+
const err_bad_cookie: int = -4
|
|
19
|
+
const err_tid_mismatch: int = -5
|
|
20
|
+
const err_no_xor_address: int = -6
|
|
21
|
+
const err_address_failed: int = -7
|
|
22
|
+
const err_send_failed: int = -8
|
|
23
|
+
const err_recv_failed: int = -9
|
|
24
|
+
const err_timeout: int = -10
|
|
25
|
+
const err_bind_failed: int = -11
|
|
26
|
+
|
|
27
|
+
public struct StunResult:
|
|
28
|
+
public_address: net.SocketAddress
|
|
29
|
+
|
|
30
|
+
public struct Error:
|
|
31
|
+
code: int
|
|
32
|
+
message: string.String
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
extending Error:
|
|
36
|
+
public editable function release() -> void:
|
|
37
|
+
this.message.release()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
extending StunResult:
|
|
41
|
+
public editable function release() -> void:
|
|
42
|
+
this.public_address.release()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
function stun_error(code: int, msg: str) -> Error:
|
|
46
|
+
return Error(code = code, message = string.String.from_str(msg))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
function transaction_id_from_bytes(data: bytes.Bytes) -> array[ubyte, 12]:
|
|
50
|
+
let span = data.as_span()
|
|
51
|
+
var tid = zero[array[ubyte, 12]]
|
|
52
|
+
var i: ptr_uint = 0
|
|
53
|
+
while i < 12z:
|
|
54
|
+
tid[i] = span[i]
|
|
55
|
+
i += 1
|
|
56
|
+
return tid
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
public function build_binding_request(tid: array[ubyte, 12]) -> bytes.Bytes:
|
|
60
|
+
var w = bin.Writer.with_capacity(stun_header_len)
|
|
61
|
+
w.write_ubyte(0x00)
|
|
62
|
+
w.write_ubyte(0x01)
|
|
63
|
+
w.write_ubyte(0x00)
|
|
64
|
+
w.write_ubyte(0x00)
|
|
65
|
+
w.write_ubyte(0x21)
|
|
66
|
+
w.write_ubyte(0x12)
|
|
67
|
+
w.write_ubyte(0xA4)
|
|
68
|
+
w.write_ubyte(0x42)
|
|
69
|
+
var i: ptr_uint = 0
|
|
70
|
+
while i < 12z:
|
|
71
|
+
w.write_ubyte(tid[i])
|
|
72
|
+
i += 1
|
|
73
|
+
return w.finish()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
function read_ushort_be(data: span[ubyte], offset: ptr_uint) -> ushort:
|
|
77
|
+
let hi = uint<-data[offset]
|
|
78
|
+
let lo = uint<-data[offset + 1z]
|
|
79
|
+
return ushort<-((hi << 8) | lo)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
function read_uint_be(data: span[ubyte], offset: ptr_uint) -> uint:
|
|
83
|
+
let b0 = uint<-data[offset]
|
|
84
|
+
let b1 = uint<-data[offset + 1z]
|
|
85
|
+
let b2 = uint<-data[offset + 2z]
|
|
86
|
+
let b3 = uint<-data[offset + 3z]
|
|
87
|
+
return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
function format_ipv4(addr: uint) -> string.String:
|
|
91
|
+
let a = (addr & 0xFFu)
|
|
92
|
+
let b = ((addr >> 8u) & 0xFFu)
|
|
93
|
+
let c = ((addr >> 16u) & 0xFFu)
|
|
94
|
+
let d = ((addr >> 24u) & 0xFFu)
|
|
95
|
+
var s = string.String.with_capacity(16)
|
|
96
|
+
fmt.append_uint(ref_of(s), d)
|
|
97
|
+
s.append(".")
|
|
98
|
+
fmt.append_uint(ref_of(s), c)
|
|
99
|
+
s.append(".")
|
|
100
|
+
fmt.append_uint(ref_of(s), b)
|
|
101
|
+
s.append(".")
|
|
102
|
+
fmt.append_uint(ref_of(s), a)
|
|
103
|
+
let result = string.String.from_str(s.as_str())
|
|
104
|
+
s.release()
|
|
105
|
+
return result
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
public function parse_binding_response(
|
|
109
|
+
packet: bytes.Bytes,
|
|
110
|
+
expected_tid: array[ubyte, 12]
|
|
111
|
+
) -> Result[StunResult, Error]:
|
|
112
|
+
let data = packet.as_span()
|
|
113
|
+
if data.len < stun_header_len:
|
|
114
|
+
return Result[StunResult, Error].failure(error = stun_error(
|
|
115
|
+
err_packet_too_small,
|
|
116
|
+
"packet too small for STUN header"
|
|
117
|
+
))
|
|
118
|
+
|
|
119
|
+
let msg_type = read_ushort_be(data, 0z)
|
|
120
|
+
if msg_type != 0x0101:
|
|
121
|
+
return Result[StunResult, Error].failure(error = stun_error(
|
|
122
|
+
err_not_binding_response,
|
|
123
|
+
"not a binding success response"
|
|
124
|
+
))
|
|
125
|
+
|
|
126
|
+
var attr_len: ptr_uint = read_ushort_be(data, 2z)
|
|
127
|
+
let cookie = read_uint_be(data, 4z)
|
|
128
|
+
if cookie != stun_magic_cookie:
|
|
129
|
+
return Result[StunResult, Error].failure(error = stun_error(err_bad_cookie, "invalid magic cookie"))
|
|
130
|
+
|
|
131
|
+
var j: ptr_uint = 0
|
|
132
|
+
while j < 12z:
|
|
133
|
+
if data[8z + j] != expected_tid[j]:
|
|
134
|
+
return Result[StunResult, Error].failure(error = stun_error(err_tid_mismatch, "transaction ID mismatch"))
|
|
135
|
+
j += 1
|
|
136
|
+
|
|
137
|
+
var offset: ptr_uint = stun_header_len
|
|
138
|
+
while attr_len >= 4z:
|
|
139
|
+
if offset + 4z > data.len:
|
|
140
|
+
break
|
|
141
|
+
let attr_type = read_ushort_be(data, offset)
|
|
142
|
+
let alen = ptr_uint<-read_ushort_be(data, offset + 2z)
|
|
143
|
+
let padded = (alen + 3z) & (~3z)
|
|
144
|
+
if offset + 4z + alen > data.len:
|
|
145
|
+
break
|
|
146
|
+
|
|
147
|
+
if attr_type == 0x0020 and alen >= 8z and data[offset + 5z] == 0x01:
|
|
148
|
+
let xport = read_ushort_be(data, offset + 6z)
|
|
149
|
+
let port = xport ^ ushort<-((stun_magic_cookie >> 16u) & 0xFFFFu)
|
|
150
|
+
let xaddr = read_uint_be(data, offset + 8z)
|
|
151
|
+
let ip = xaddr ^ stun_magic_cookie
|
|
152
|
+
var ip_str = format_ipv4(ip)
|
|
153
|
+
defer ip_str.release()
|
|
154
|
+
let addr_result = net.ipv4(ip_str.as_str(), int<-port)
|
|
155
|
+
match addr_result:
|
|
156
|
+
Result.failure:
|
|
157
|
+
return Result[StunResult, Error].failure(error = stun_error(
|
|
158
|
+
err_address_failed,
|
|
159
|
+
"failed to construct address"
|
|
160
|
+
))
|
|
161
|
+
Result.success as addr_payload:
|
|
162
|
+
return Result[StunResult, Error].success(value = StunResult(public_address = addr_payload.value))
|
|
163
|
+
|
|
164
|
+
offset = offset + 4z + padded
|
|
165
|
+
attr_len = attr_len - 4z - padded
|
|
166
|
+
|
|
167
|
+
return Result[StunResult, Error].failure(error = stun_error(
|
|
168
|
+
err_no_xor_address,
|
|
169
|
+
"no XOR-MAPPED-ADDRESS attribute found"
|
|
170
|
+
))
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
public async function resolve_public_address(
|
|
174
|
+
socket: net.UdpSocket,
|
|
175
|
+
stun_server: net.SocketAddress
|
|
176
|
+
) -> Result[StunResult, Error]:
|
|
177
|
+
let rand_result = crypto.random_bytes(12)
|
|
178
|
+
match rand_result:
|
|
179
|
+
Result.failure:
|
|
180
|
+
return Result[StunResult, Error].failure(error = stun_error(
|
|
181
|
+
err_tid_failed,
|
|
182
|
+
"failed to generate transaction ID"
|
|
183
|
+
))
|
|
184
|
+
Result.success as rp:
|
|
185
|
+
let tid = transaction_id_from_bytes(rp.value)
|
|
186
|
+
rp.value.release()
|
|
187
|
+
var request = build_binding_request(tid)
|
|
188
|
+
defer request.release()
|
|
189
|
+
let send_result = await socket.send_to(request.as_span(), stun_server)
|
|
190
|
+
match send_result:
|
|
191
|
+
Result.failure:
|
|
192
|
+
return Result[StunResult, Error].failure(error = stun_error(
|
|
193
|
+
err_send_failed,
|
|
194
|
+
"failed to send STUN request"
|
|
195
|
+
))
|
|
196
|
+
Result.success:
|
|
197
|
+
pass
|
|
198
|
+
|
|
199
|
+
var frame: uint = 0
|
|
200
|
+
let recv_task = socket.recv_from(512)
|
|
201
|
+
while frame < 40:
|
|
202
|
+
if aio.completed(recv_task):
|
|
203
|
+
let recv_result = aio.result(recv_task)
|
|
204
|
+
match recv_result:
|
|
205
|
+
Result.failure:
|
|
206
|
+
return Result[StunResult, Error].failure(error = stun_error(err_recv_failed, "recv failed"))
|
|
207
|
+
Result.success as dp:
|
|
208
|
+
var datagram = dp.value
|
|
209
|
+
let parse_result = parse_binding_response(datagram.data, tid)
|
|
210
|
+
datagram.data.release()
|
|
211
|
+
datagram.source.release()
|
|
212
|
+
match parse_result:
|
|
213
|
+
Result.failure:
|
|
214
|
+
continue
|
|
215
|
+
Result.success as srp:
|
|
216
|
+
return Result[StunResult, Error].success(value = srp.value)
|
|
217
|
+
await aio.sleep(50)
|
|
218
|
+
frame += 1
|
|
219
|
+
|
|
220
|
+
return Result[StunResult, Error].failure(error = stun_error(err_timeout, "STUN request timed out"))
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
public async function resolve_public_address_on(
|
|
224
|
+
runtime: aio.Runtime,
|
|
225
|
+
local_addr: net.SocketAddress,
|
|
226
|
+
stun_server: net.SocketAddress
|
|
227
|
+
) -> Result[StunResult, Error]:
|
|
228
|
+
let bind_result = net.udp_bind_on(runtime, local_addr)
|
|
229
|
+
match bind_result:
|
|
230
|
+
Result.failure:
|
|
231
|
+
return Result[StunResult, Error].failure(
|
|
232
|
+
error = stun_error(err_bind_failed, "failed to bind socket")
|
|
233
|
+
)
|
|
234
|
+
Result.success as bp:
|
|
235
|
+
var socket = bp.value
|
|
236
|
+
defer socket.release()
|
|
237
|
+
return await resolve_public_address(socket, stun_server)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
public async function resolve(
|
|
241
|
+
stun_server: net.SocketAddress
|
|
242
|
+
) -> Result[StunResult, Error]:
|
|
243
|
+
let local_result = net.ipv4("0.0.0.0", 0)
|
|
244
|
+
match local_result:
|
|
245
|
+
Result.failure:
|
|
246
|
+
return Result[StunResult, Error].failure(
|
|
247
|
+
error = stun_error(err_bind_failed, "failed to create local address")
|
|
248
|
+
)
|
|
249
|
+
Result.success as la:
|
|
250
|
+
var local_addr = la.value
|
|
251
|
+
defer local_addr.release()
|
|
252
|
+
return await resolve_public_address_on(aio.current_runtime(), local_addr, stun_server)
|
data/std/net/sync.mt
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import std.net.mux as mux
|
|
2
|
+
import std.net.session as sess
|
|
3
|
+
import std.vec as vec
|
|
4
|
+
|
|
5
|
+
public struct SyncValue[T]:
|
|
6
|
+
value: T
|
|
7
|
+
dirty: bool
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
extending SyncValue[T]:
|
|
11
|
+
public editable function set(new_value: T) -> void:
|
|
12
|
+
this.value = new_value
|
|
13
|
+
this.dirty = true
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
public function get() -> T:
|
|
17
|
+
return this.value
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
public editable function mark_clean() -> void:
|
|
21
|
+
this.dirty = false
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
public function has_changed() -> bool:
|
|
25
|
+
return this.dirty
|
|
26
|
+
|
|
27
|
+
public struct SyncList[T]:
|
|
28
|
+
items: vec.Vec[T]
|
|
29
|
+
dirty: bool
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
extending SyncList[T]:
|
|
33
|
+
public editable function push(item: T) -> void:
|
|
34
|
+
this.items.push(item)
|
|
35
|
+
this.dirty = true
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
public editable function clear() -> void:
|
|
39
|
+
this.items.clear()
|
|
40
|
+
this.dirty = true
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
public function len() -> ptr_uint:
|
|
44
|
+
return this.items.len()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
public function get(index: ptr_uint) -> ptr[T]?:
|
|
48
|
+
return this.items.get(index)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
public function at(index: ptr_uint) -> Option[T]:
|
|
52
|
+
return this.items.at(index)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
public editable function mark_clean() -> void:
|
|
56
|
+
this.dirty = false
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
public function has_changed() -> bool:
|
|
60
|
+
return this.dirty
|
|
61
|
+
|
|
62
|
+
public struct Lerp:
|
|
63
|
+
previous: float
|
|
64
|
+
target: float
|
|
65
|
+
elapsed: float
|
|
66
|
+
duration: float
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
extending Lerp:
|
|
70
|
+
public editable function set_target(new_target: float, dur: float) -> void:
|
|
71
|
+
this.previous = this.target
|
|
72
|
+
this.target = new_target
|
|
73
|
+
this.elapsed = 0.0
|
|
74
|
+
this.duration = dur
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
public editable function tick(dt: float) -> void:
|
|
78
|
+
this.elapsed = this.elapsed + dt
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
public function current() -> float:
|
|
82
|
+
if this.duration <= 0.0:
|
|
83
|
+
return this.target
|
|
84
|
+
var t: float = this.elapsed / this.duration
|
|
85
|
+
if t > 1.0:
|
|
86
|
+
t = 1.0
|
|
87
|
+
return this.previous + (this.target - this.previous) * t
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
public function has_arrived() -> bool:
|
|
91
|
+
return this.elapsed >= this.duration
|
|
92
|
+
|
|
93
|
+
public struct CompressedUshort:
|
|
94
|
+
min: float
|
|
95
|
+
max: float
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
extending CompressedUshort:
|
|
99
|
+
public function encode(value: float) -> ushort:
|
|
100
|
+
var clamped: float = value
|
|
101
|
+
if clamped < this.min:
|
|
102
|
+
clamped = this.min
|
|
103
|
+
if clamped > this.max:
|
|
104
|
+
clamped = this.max
|
|
105
|
+
let ratio = (clamped - this.min) / (this.max - this.min)
|
|
106
|
+
return ushort<-(ratio * 65535.0)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
public function decode(encoded: ushort) -> float:
|
|
110
|
+
let ratio = float<-encoded / 65535.0
|
|
111
|
+
return this.min + ratio * (this.max - this.min)
|
|
112
|
+
|
|
113
|
+
public struct CompressedUbyte:
|
|
114
|
+
min: float
|
|
115
|
+
max: float
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
extending CompressedUbyte:
|
|
119
|
+
public function encode(value: float) -> ubyte:
|
|
120
|
+
var clamped: float = value
|
|
121
|
+
if clamped < this.min:
|
|
122
|
+
clamped = this.min
|
|
123
|
+
if clamped > this.max:
|
|
124
|
+
clamped = this.max
|
|
125
|
+
let ratio = (clamped - this.min) / (this.max - this.min)
|
|
126
|
+
return ubyte<-(ratio * 255.0)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
public function decode(encoded: ubyte) -> float:
|
|
130
|
+
let ratio = float<-encoded / 255.0
|
|
131
|
+
return this.min + ratio * (this.max - this.min)
|
|
132
|
+
|
|
133
|
+
public struct TickBuffer[T]:
|
|
134
|
+
entries: vec.Vec[T]
|
|
135
|
+
base_tick: uint
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
extending TickBuffer[T]:
|
|
139
|
+
public editable function push(tick: uint, value: T) -> void:
|
|
140
|
+
let offset: ptr_uint = ptr_uint<-(tick - this.base_tick)
|
|
141
|
+
while offset >= this.entries.len():
|
|
142
|
+
this.entries.push(value)
|
|
143
|
+
return
|
|
144
|
+
let ptr = this.entries.get(offset) else:
|
|
145
|
+
return
|
|
146
|
+
unsafe:
|
|
147
|
+
read(ptr) = value
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
public function get(tick: uint) -> Option[T]:
|
|
151
|
+
if tick < this.base_tick:
|
|
152
|
+
return Option[T].none()
|
|
153
|
+
let offset: ptr_uint = ptr_uint<-(tick - this.base_tick)
|
|
154
|
+
if offset >= this.entries.len():
|
|
155
|
+
return Option[T].none()
|
|
156
|
+
let ptr = this.entries.get(offset) else:
|
|
157
|
+
return Option[T].none()
|
|
158
|
+
return Option[T].some(value = unsafe: read(ptr))
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
public function earliest_tick() -> uint:
|
|
162
|
+
return this.base_tick
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
public function latest_tick() -> uint:
|
|
166
|
+
return this.base_tick + uint<-this.entries.len()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
public async function broadcast(
|
|
170
|
+
session: ref[mux.MuxedSession],
|
|
171
|
+
channel_id: ubyte,
|
|
172
|
+
type_id: ushort,
|
|
173
|
+
payload: span[ubyte],
|
|
174
|
+
send_flags: ubyte
|
|
175
|
+
) -> void:
|
|
176
|
+
var i: ptr_uint = 0
|
|
177
|
+
while i < session.session.peers.len():
|
|
178
|
+
let peer_ptr = session.session.peers.get(i) else:
|
|
179
|
+
break
|
|
180
|
+
let peer_id = unsafe: read(peer_ptr).peer_id
|
|
181
|
+
if unsafe: read(peer_ptr).channel_state != sess.ConnectionState.disconnected:
|
|
182
|
+
let _ = await session.mux_send(peer_id, channel_id, type_id, payload, send_flags)
|
|
183
|
+
i += 1
|