lt-script 1.0.3 → 1.0.6

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.
package/README.md CHANGED
@@ -6,269 +6,561 @@
6
6
  <img src="https://img.shields.io/badge/FiveM-Ready-green" alt="FiveM Ready">
7
7
  </p>
8
8
 
9
- **LT** is a modern, developer-friendly language that compiles to FiveM Lua. It brings TypeScript-like syntax, modern JavaScript features, and FiveM-specific sugar to the Lua ecosystem — making your scripts cleaner, safer, and more enjoyable to write.
9
+ **LT** is a modern, statically-typed superset of Lua designed specifically for **FiveM development**. It combines the elegance of TypeScript with the performance of Lua, adding FiveM-specific syntactic sugar to make your scripts robust, readable, and faster to write.
10
+
11
+ > **Goodbye boilerplate, hello productivity.**
12
+ > Write clean, type-safe code that compiles to optimized 100% vanilla Lua.
13
+
14
+ ---
10
15
 
11
16
  ## ✨ Why LT?
12
17
 
13
- Writing vanilla Lua for FiveM can be tedious. LT fixes that with:
18
+ * **🛡️ Type Safety**: Catch type mismatches and `nil` errors *before* you run the game.
19
+ * **⚡ Modern Syntax**: Use Arrow Functions, Destructuring, Spread syntax, and more.
20
+ * **🎮 FiveM-First**: Built-in keywords like `netevent`, `addcmd`, `thread`, and `wait`.
21
+ * **🔌 Zero Overhead**: Compiles to pure, readable Lua with no runtime dependencies.
14
22
 
15
- - **Modern Syntax**: Arrow functions, destructuring, spread operator, optional chaining
16
- - **FiveM Sugar**: Built-in `thread`, `wait`, `netevent`, `addcmd`, `export` keywords
17
- - **Type Safety**: Static type checking catches errors at compile time
18
- - **Clean Code**: No more boilerplate — just write what you mean
23
+ ---
19
24
 
20
25
  ## 📦 Installation
21
26
 
27
+ Prerequisites: [Node.js](https://nodejs.org/) (Version 16+)
28
+
22
29
  ```bash
30
+ # Global installation (Recommended)
23
31
  npm install -g lt-script
32
+
33
+ # OR run directly via npx
34
+ npx lt-script build .
24
35
  ```
25
36
 
37
+ ---
38
+
26
39
  ## 🚀 Quick Start
27
40
 
28
- Create a file called `main.lt`:
41
+ Create a `client.lt` file:
29
42
 
30
43
  ```typescript
31
- // Variables with modern scoping
32
- let health: number = 100
33
- const MAX_HEALTH = 200
44
+ // Define a type for player data
45
+ interface PlayerData {
46
+ id: number,
47
+ name: string,
48
+ health: number
49
+ }
34
50
 
35
- // Arrow functions
36
- let double = (x) => x * 2
51
+ // Variables with types
52
+ let active: boolean = false
53
+ const MAX_HEALTH = 100
37
54
 
38
- // String interpolation
39
- print("Health: $health / $MAX_HEALTH")
55
+ // FiveM Command
56
+ addcmd "heal" (source, args)
57
+ let amount = tonumber(args[1]) ?? MAX_HEALTH
58
+ SetEntityHealth(PlayerPedId(), amount)
59
+ print("Healed for ${amount}")
60
+ end
40
61
 
41
- // FiveM thread with wait
62
+ // Thread with loop
42
63
  thread
64
+ print("System active")
43
65
  loop (true)
44
66
  wait 1000
45
- print("Tick...")
67
+ if LocalPlayer.state?.isDead then
68
+ print("Player is dead!")
69
+ end
46
70
  end
47
71
  end
48
-
49
- // Register a command easily
50
- addcmd "heal" (source, args)
51
- health = MAX_HEALTH
52
- print("Player healed!")
53
- end
54
-
55
- // Network events without boilerplate
56
- netevent "player:spawn" (data)
57
- print("Player spawned: $data")
58
- end
59
72
  ```
60
73
 
61
- Compile it:
62
-
74
+ **Compile it:**
63
75
  ```bash
64
76
  ltc build .
65
77
  ```
66
78
 
67
- Output `main.lua`:
68
- ```lua
69
- local health = 100
70
- local MAX_HEALTH <const> = 200
79
+ ---
71
80
 
72
- local double = function(x) return x * 2 end
81
+ ## 📘 Language Reference
73
82
 
74
- print("Health: " .. tostring(health) .. " / " .. tostring(MAX_HEALTH))
83
+ ### 1. Variables & Types
75
84
 
76
- CreateThread(function()
77
- while true do
78
- Wait(1000)
79
- print("Tick...")
80
- end
81
- end)
85
+ LT supports explicit typing with compile-time validation.
82
86
 
83
- RegisterCommand("heal", function(source, args)
84
- health = MAX_HEALTH
85
- print("Player healed!")
86
- end, false)
87
-
88
- RegisterNetEvent("player:spawn")
89
- AddEventHandler("player:spawn", function(data)
90
- print("Player spawned: " .. tostring(data))
91
- end)
87
+ ```typescript
88
+ // Mutable variables
89
+ let score: number = 0
90
+ var playerName: string = "John" // Type inferred if omitted
91
+
92
+ // Constants (Compiles to Lua 5.4 <const>)
93
+ const MAX_PLAYERS = 32
94
+
95
+ // Available primitive types
96
+ let str: string = "hello"
97
+ let num: number = 42
98
+ let flag: boolean = true
99
+ let data: table = { key: "value" }
100
+ let pos: vector3 = <100.0, 200.0, 30.0>
101
+ let callback: function = () => print("hi")
102
+
103
+ // Arrays
104
+ let inventory: string[] = ["Apple", "Water"]
105
+ let numbers: number[] = [1, 2, 3]
92
106
  ```
93
107
 
94
- ## 🛠️ CLI Commands
108
+ ### 2. Interfaces & Type Aliases
95
109
 
96
- | Command | Description |
97
- |---------|-------------|
98
- | `ltc build <dir>` | Compile all `.lt` files in directory |
99
- | `ltc watch <dir>` | Watch mode — auto-compile on save |
110
+ Define complex data structures for compile-time validation.
100
111
 
101
- ## 🎯 Feature Highlights
102
-
103
- ### Variables & Constants
104
112
  ```typescript
105
- var globalVar = "I am global" // Global variable
106
- let localVar = 10 // Local variable
107
- const MAX = 100 // Constant (Lua 5.4 <const>)
108
- ```
113
+ // Interface - Object shape definition
114
+ interface VehicleConfig {
115
+ model: string,
116
+ price: number,
117
+ color: string
118
+ }
109
119
 
110
- ### Type System
111
- ```typescript
112
- // Explicit types
113
- let name: string = "John"
114
- let age: number = 25
115
- let active: boolean = true
120
+ // Type Alias - Alternative syntax
121
+ type PlayerPos = { x: number, y: number, z: number }
116
122
 
117
- // Type Aliases
118
- interface PlayerData = {
119
- name: string,
120
- level: number,
121
- isVip: boolean
123
+ // Usage with validation
124
+ const myCar: VehicleConfig = {
125
+ model: "sultan",
126
+ price: 50000,
127
+ color: "red"
122
128
  }
123
129
 
124
- func Calculate(a: number, b: number)
125
- return a + b
126
- end
127
- ```
130
+ // Arrays of interfaces
131
+ interface StoreConfig {
132
+ id: number,
133
+ position: vector3,
134
+ isOpen: boolean
135
+ }
128
136
 
129
- ### Arrow Functions
130
- ```typescript
131
- let add = (a, b) => a + b
132
- let greet = (name) => print("Hello, $name!")
137
+ const Stores: StoreConfig[] = [
138
+ { id: 1, position: <100.0, 200.0, 30.0>, isOpen: true },
139
+ { id: 2, position: <150.0, 250.0, 35.0>, isOpen: false }
140
+ ]
133
141
  ```
134
142
 
135
- ### Destructuring
143
+ > **Note:** Type validation ensures field types match. Assigning `number` to a `vector3` field will cause a compile error.
144
+
145
+ ### 3. Functions
146
+
136
147
  ```typescript
137
- let player = { name: "Alex", level: 50 }
138
- let { name, level } = player
148
+ // Standard function with typed parameters
149
+ func Add(a: number, b: number)
150
+ return a + b
151
+ end
152
+
153
+ // Default parameters
154
+ func Greet(name: string, prefix = "Hello")
155
+ print("${prefix}, ${name}!")
156
+ end
157
+
158
+ // Local function (Lua local function)
159
+ local function PrivateHelper()
160
+ return "internal"
161
+ end
139
162
 
140
- let coords = [100, 200, 300]
141
- let [x, y, z] = coords
163
+ // Arrow functions
164
+ let double = (x: number) => x * 2
165
+ let greet = (name) => print("Hello ${name}")
166
+
167
+ // Multi-line arrow
168
+ let process = (data) => {
169
+ let result = data * 2
170
+ return result
171
+ }
142
172
  ```
143
173
 
144
- ### Optional Chaining & Null Coalescing
174
+ ### 4. Control Flow
175
+
176
+ #### If / Else
145
177
  ```typescript
146
- let job = player?.metadata?.job?.label ?? "Unemployed"
178
+ // Note: 'then' keyword is required after condition
179
+ if health < 20 then
180
+ print("Low health!")
181
+ elseif health < 50 then
182
+ print("Medium health")
183
+ else
184
+ print("Full health")
185
+ end
147
186
  ```
148
187
 
149
- ### Vector Literals
188
+ #### Switch / Case
150
189
  ```typescript
151
- let pos = <100.0, 50.0, 20.0> // vector3
152
- let rot = <0.0, 90.0> // vector2
190
+ let job = "police"
191
+
192
+ switch job
193
+ case "police", "ambulance"
194
+ print("Government worker")
195
+ case "mechanic"
196
+ print("Service worker")
197
+ default
198
+ print("Civilian")
199
+ end
153
200
  ```
154
201
 
155
- ### Switch/Case
202
+ #### Guard Clauses
203
+ Clean up nested if-statements with early returns.
204
+
156
205
  ```typescript
157
- switch weather
158
- case "RAIN", "THUNDER"
159
- print("Stay inside!")
160
- case "CLEAR"
161
- print("Nice day!")
162
- default
163
- print("Unknown weather")
206
+ func RevivePlayer(player)
207
+ // Returns immediately if player is nil
208
+ guard player return
209
+
210
+ // Returns with custom logic if condition fails
211
+ guard player.isDead else
212
+ print("Player is already alive")
213
+ return
214
+ end
215
+
216
+ // Main logic
217
+ player.revive()
218
+ end
219
+
220
+ // Guard with return value
221
+ func GetPlayer(id)
222
+ let player = GetPlayerById(id)
223
+ guard player return nil
224
+ return player
164
225
  end
165
226
  ```
166
227
 
167
- ### For Loops
228
+ #### For Loops
168
229
  ```typescript
169
- // Range loop
170
- for i in 1..10 do
230
+ // Numeric for (start, end)
231
+ for i = 1, 10 do
171
232
  print(i)
172
233
  end
173
234
 
174
- // Range with step
175
- for i in 10..1 by -1 do
235
+ // Numeric for with step (start, end, step)
236
+ for i = 0, 100, 5 do
176
237
  print(i)
177
238
  end
178
239
 
179
- // C-style loop
180
- for i = 0, 100, 5 do
240
+ // Range for with step
241
+ for i in 1..10 by 2 do
181
242
  print(i)
182
243
  end
244
+
245
+ // For-in (pairs)
246
+ for key, value in pairs(myTable) do
247
+ print("${key}: ${value}")
248
+ end
249
+
250
+ // For-in (ipairs)
251
+ for index, item in ipairs(myArray) do
252
+ print("${index}: ${item}")
253
+ end
254
+ ```
255
+
256
+ #### While Loop
257
+ ```typescript
258
+ let count = 0
259
+ while count < 10 do
260
+ print(count)
261
+ count += 1
262
+ end
263
+ ```
264
+
265
+ ### 5. Modern Operators
266
+
267
+ #### Compound Assignment
268
+ ```typescript
269
+ let x = 10
270
+ x += 5
271
+ x -= 3
272
+ x *= 2
273
+ x /= 4
274
+ x %= 3
275
+ ```
276
+
277
+ #### Null Coalescing (`??`)
278
+ ```typescript
279
+ let name = playerName ?? "Unknown"
280
+ let health = GetHealth() ?? 100
183
281
  ```
184
282
 
185
- ### FiveM Specific
283
+ #### Optional Chaining (`?.`)
284
+ ```typescript
285
+ let state = LocalPlayer.state?.isDead
286
+ let nested = obj?.deep?.value
287
+ let arrItem = arr?[0]
288
+ ```
289
+
290
+ #### Ternary Operator
291
+ ```typescript
292
+ let status = isDead ? "Dead" : "Alive"
293
+ let label = count > 0 ? "${count} items" : "Empty"
294
+ ```
295
+
296
+ ### 6. Destructuring & Spread
297
+
298
+ ```typescript
299
+ // Object Destructuring
300
+ let { x, y, z } = GetEntityCoords(ped)
301
+ let { name, health } = playerData
302
+
303
+ // Array Destructuring
304
+ let [first, second] = GetValues()
305
+
306
+ // Object Spread (tables only)
307
+ let base = { a: 1, b: 2 }
308
+ let extended = { ...base, c: 3 }
309
+ ```
310
+
311
+ ### 7. String Interpolation
312
+
313
+ Use `${expression}` inside strings to embed values:
314
+
315
+ ```typescript
316
+ let name = "John"
317
+ let age = 25
318
+
319
+ print("Hello, ${name}!")
320
+ print("You are ${age} years old")
321
+ print("Next year you'll be ${age + 1}")
322
+
323
+ // Complex expressions
324
+ let player = { health: 100 }
325
+ print("Health: ${player.health}")
326
+ ```
327
+
328
+ ### 8. Vector Literals
329
+
330
+ ```typescript
331
+ // Vector3 (FiveM native)
332
+ let pos: vector3 = <100.0, 200.0, 30.0>
333
+
334
+ // Vector2
335
+ let screenPos: vector2 = <0.5, 0.5>
336
+
337
+ // Vector4 (includes heading)
338
+ let spawn: vector4 = <100.0, 200.0, 30.0, 90.0>
339
+ ```
340
+
341
+ ---
342
+
343
+ ## 🎮 FiveM Features
344
+
345
+ ### Thread & Loop
186
346
 
187
- #### Threads & Wait
188
347
  ```typescript
348
+ // Create a thread (Citizen.CreateThread)
189
349
  thread
190
- wait 1000
191
- print("After 1 second")
350
+ print("Thread started")
351
+
352
+ loop (true)
353
+ wait 0 // Run every frame
354
+
355
+ // Game logic here
356
+ let ped = PlayerPedId()
357
+ let health = GetEntityHealth(ped)
358
+
359
+ if health < 50 then
360
+ print("Low health warning!")
361
+ end
362
+ end
192
363
  end
193
364
  ```
194
365
 
195
- #### Events
366
+ ### Wait
367
+
196
368
  ```typescript
197
- netevent "myResource:sync" (data)
198
- -- RegisterNetEvent + AddEventHandler
369
+ // Wait in milliseconds
370
+ wait 1000 // Wait 1 second
371
+ wait 0 // Yield one frame
372
+ ```
373
+
374
+ ### Network Events
375
+
376
+ ```typescript
377
+ // Register + Handle network event (Client <-> Server)
378
+ netevent "bank:deposit" (amount)
379
+ print("Depositing ${amount}")
380
+ UpdateBankBalance(amount)
199
381
  end
200
382
 
201
- event "localEvent" (data)
202
- -- AddEventHandler only
383
+ // Local event handler
384
+ event "onClientResourceStart" (resName)
385
+ guard resName == GetCurrentResourceName() return
386
+ print("Resource started!")
203
387
  end
204
388
  ```
205
389
 
206
- #### Commands
390
+ ### Emit Events
391
+
392
+ ```typescript
393
+ // Emit to server
394
+ emit "server:event:name" (arg1, arg2)
395
+
396
+ // Explicit emit variants
397
+ emitServer "myevent" (data)
398
+ emitClient "myevent" (targetPlayer, data)
399
+ ```
400
+
401
+ ### Commands
402
+
207
403
  ```typescript
404
+ // Register a command (RegisterCommand wrapper)
208
405
  addcmd "teleport" (source, args)
209
- print("Teleporting...")
406
+ let x = tonumber(args[1]) ?? 0
407
+ let y = tonumber(args[2]) ?? 0
408
+ let z = tonumber(args[3]) ?? 0
409
+
410
+ SetEntityCoords(PlayerPedId(), x, y, z)
411
+ print("Teleported to ${x}, ${y}, ${z}")
210
412
  end
211
413
  ```
212
414
 
213
- #### Exports
415
+ ### Exports
416
+
214
417
  ```typescript
215
- export func GetPlayerData(id)
216
- return players[id]
418
+ // Export a function
419
+ export "GetPlayerMoney" ()
420
+ return playerMoney
217
421
  end
218
422
  ```
219
423
 
220
- #### Guard Statements
424
+ ### Timeout & Interval
425
+
221
426
  ```typescript
222
- guard player return // Early return if nil/false
223
- guard player.job == "police" return print("Access denied")
427
+ // Run once after delay
428
+ timeout 5000
429
+ print("5 seconds passed!")
430
+ end
224
431
 
225
- // Guard with else block
226
- guard isValid else
227
- print("Invalid state")
228
- return
432
+ // Run repeatedly
433
+ interval 1000
434
+ print("Every second")
229
435
  end
230
436
  ```
231
437
 
232
- #### Try/Catch
438
+ ### Try / Catch
439
+
233
440
  ```typescript
234
441
  try
235
- riskyOperation()
442
+ RiskyOperation()
236
443
  catch err
237
- print("Error: $err")
444
+ print("Error: ${err}")
445
+ end
446
+ ```
447
+
448
+ ---
449
+
450
+ ## ⚡ Complete Example: Store Robbery System
451
+
452
+ ```typescript
453
+ // 1. Type Definition
454
+ interface StoreConfig {
455
+ id: number,
456
+ position: vector3,
457
+ reward: number,
458
+ isOpen: boolean
459
+ }
460
+
461
+ // 2. Configuration
462
+ const Stores: StoreConfig[] = [
463
+ { id: 1, position: <120.5, -500.2, 30.0>, reward: 5000, isOpen: true },
464
+ { id: 2, position: <250.0, 300.0, 25.0>, reward: 10000, isOpen: true }
465
+ ]
466
+
467
+ let isRobbing = false
468
+
469
+ // 3. Main Game Loop
470
+ thread
471
+ loop (true)
472
+ wait 0
473
+
474
+ if isRobbing then
475
+ break
476
+ end
477
+
478
+ let ped = PlayerPedId()
479
+ let pos = GetEntityCoords(ped)
480
+
481
+ for _, store in ipairs(Stores) do
482
+ if not store.isOpen then
483
+ break
484
+ end
485
+
486
+ let distance = #(pos - store.position)
487
+ if distance < 2.0 then
488
+ ShowHelpText("Press ~INPUT_CONTEXT~ to rob")
489
+
490
+ if IsControlJustPressed(0, 38) then
491
+ StartRobbery(store)
492
+ end
493
+ end
494
+ end
495
+ end
496
+ end
497
+
498
+ // 4. Robbery Function
499
+ func StartRobbery(store: StoreConfig)
500
+ isRobbing = true
501
+
502
+ // Notify server
503
+ emit "robbery:start" (store.id)
504
+
505
+ // Play animation
506
+ TaskPlayAnim(PlayerPedId(), "anim_dict", "anim_name", 8.0, -8.0, -1, 0, 0, false, false, false)
507
+
508
+ wait 5000
509
+
510
+ ClearPedTasks(PlayerPedId())
511
+ isRobbing = false
512
+
513
+ print("Robbery complete! Reward: ${store.reward}")
514
+ end
515
+
516
+ // 5. Server Sync Handler
517
+ netevent "robbery:sync" (storeId, newState)
518
+ let store = Stores.find(s => s.id == storeId)
519
+ guard store return
520
+
521
+ store.isOpen = newState
522
+ let stateStr = newState ? "open" : "closed"
523
+ print("Store ${storeId} is now ${stateStr}")
238
524
  end
239
525
  ```
240
526
 
241
- ## 📁 Project Structure
527
+ ---
528
+
529
+ ## 🛠️ CLI Reference
530
+
531
+ | Command | Usage | Description |
532
+ |:--------|:------|:------------|
533
+ | **Build** | `ltc build ./` | Compiles all `.lt` files in the folder to `.lua` |
534
+ | **Watch** | `ltc watch ./` | Watches for file changes and recompiles instantly |
535
+ | **Version** | `ltc -v` | Displays the current compiler version |
536
+
537
+ ### Project Structure
538
+
539
+ LT automatically detects `src/` folders:
242
540
 
243
541
  ```
244
542
  my-resource/
245
543
  ├── src/
246
544
  │ ├── client.lt
247
545
  │ └── server.lt
248
- ├── client.lua (generated)
249
- ├── server.lua (generated)
250
- └── fxmanifest.lua
546
+ ├── client.lua ← Generated
547
+ └── server.lua ← Generated
251
548
  ```
252
549
 
253
- Run `ltc watch .` in your resource folder for automatic compilation.
550
+ ---
254
551
 
255
552
  ## 🔧 VS Code Extension
256
553
 
257
- Get syntax highlighting and IntelliSense for `.lt` files:
258
-
259
- **[LT Language Extension](https://marketplace.visualstudio.com/items?itemName=laot.lt-language)**
260
-
261
- - Syntax Highlighting
262
- - IntelliSense for Variables & Functions
263
- - **Native FiveM Autocompletion** (GetHashKey, CreateVehicle, etc.)
264
- - Snippets for common patterns
265
-
266
- ## 📜 License
554
+ Get the official **[LT Language Extension](https://marketplace.visualstudio.com/items?itemName=laot.lt-language)** for the best experience.
267
555
 
268
- MIT © [LaotScripts](https://github.com/laot7490)
556
+ **Features:**
557
+ * 🎨 Full Syntax Highlighting
558
+ * 🔍 Intelligent Autocompletion
559
+ * 📦 **FiveM Native Intellisense**
560
+ * ✨ Real-time Error Checking
269
561
 
270
562
  ---
271
563
 
272
564
  <p align="center">
273
- Made with ❤️ for the FiveM community
565
+ Made with ❤️ for the FiveM Community by <b>LaotScripts</b>
274
566
  </p>