-
Notifications
You must be signed in to change notification settings - Fork 333
E2 Guide: File Extension
The file extension allows you to create, read, and modify files locally stored on your computer. Because files are stored locally by you, this means they must be sent to the server using fileLoad
before they can be accessed. Files cannot be modified without a similar network transaction back using fileWrite
. file also contains fileList
to query what files exist in a directory.
Files are by default saved into e2files
in your Garry's Mod data directory, but can also be redirected using >
into these select directories:
-
>e2files
->e2files
-
>e2shared
->expression2/e2shared
-
>cpushared
->cpuchip/e2shared
-
>gpushared
->gpuchip/e2shared
-
>spushared
->spuchip/e2shared
An example usage would be fileWrite(">e2shared/test.txt", "Hello, World!")
, which would then write a file which you could access in the Expression 2 file browser under e2shared
.
Important
It is impossible in Garry's Mod to write to a file outside of the garrysmod/data
folder.
On top of this, the file extension can only read and write to the above directories. The extension cannot read files from the server.
Files can fail to load, create, or otherwise fail if these rules are not followed;
- Filename must end with
.txt
- File must be inside one of the above directories
- Files must be under the size limit (default 300KiB)
Warning
The examples here will write files to your e2files
directory. Make sure you're not overwriting anything important before trying these!
To show what a typical usage of file operations looks like, let's try writing to a file on the chip start and reading it back after it's written. fileWrite(string path, string data)
allows you to write to a file. If the file exists, it will be overwritten. There are no safeguards for file overwriting, so make sure you're not replacing important data when doing this!
@name File Write and Read
@trigger none
@strict
fileWrite("test.txt", "Hello, World! " + curtime())
Just to show that the file we're writing is being overwritten, we'll also add curtime()
to the end of its message, which will give it a "timestamp" every time this code is ran. Next, we'll add events to read the file once it finishes writing. We can use the event fileWritten
, which triggers right after a file finishes writing. The first parameter of fileWritten
is the path of the written file. We'll use that here to demonstrate its usage. The second parameter is the data that we just wrote, which we'll discard in this example. We'll then use fileLoad
on this path, which will load up test.txt
and trigger the fileLoaded
event when finished.
event fileWritten(Path:string, _:string) {
fileLoad(Path)
}
In the fileLoaded
event, the first parameter is the path to the file as a string, and the second is the contents of the file, also as a string. We'll just print out both with some simple formatting. We'll also print out curtime()
to see how much time has progressed between writing and loading.
event fileLoaded(Path:string, Data:string) {
print(format("%s: %s \nTime: %f", Path, Data, curtime()))
}
After running our code, we should see an output like this:
test.txt: Hello, World! 6030.6748046875
Time: 6031.094727
Full example code
@name File Write and Read
@trigger none
@strict
fileWrite("test.txt", "Hello, World! " + curtime())
event fileWritten(Path:string, _:string) {
fileLoad(Path)
}
event fileLoaded(Path:string, Data:string) {
print(format("%s: %s \nTime: %f", Path, Data, curtime()))
}
Important
These examples contain E2 functions that are only available on the Github release currently
Warning
The examples here will write files to your e2files
directory. Make sure you're not overwriting anything important before trying these!
You can queue multiple file operations at once and they will be processed sequentially. By default, you can queue 5 operations of loading, writing, and listing each. Exceeding the limit will throw a runtime error. To demonstrate the queue, let's try creating a lot of files, listing them, and then opening them all.
We'll start by programmatically creating all the files in a directory for this example. We'll name the files as manyfiles/<number>.txt
and contain a simple generic message. We'll also use fileCanWrite
to see if we can still write files, and break early if we can't.
@name File Queues
@persist List:array
@trigger none
@strict
for(I = 1, 10) {
if(fileCanWrite()) {
fileWrite(format("manyfiles/%d.txt", I), format("This is file #%d!", I))
} else { break }
}
With that out of the way, let's get onto the events. The first one we'll register is the fileWritten
event. We'll use this to make sure we're done writing everything before listing. We can ignore the parameters for this and instead use fileWriteQueued()
, which returns the number of elements in the corresponding queue. We'll check if it's 0 to confirm the queue is empty, and then use fileList
on "manyfiles/"
to get all the files inside that directory. Note that the slash is mandatory.
event fileWritten(_:string, _:string) {
if(fileWriteQueued() == 0) {
fileList("manyfiles/")
}
}
After that, we'll register the fileList
event, which triggers when a list is received. Like files, lists are also networked, so they don't happen instantly. The first parameter is the directory path. The second parameter is an array of strings of all the files and subdirectories in the directory. We'll loop over this array and read each file inside the directory, making sure to not run into any queue errors. Note that the filenames in the array are relative, so we'll concatenate them to the directory path to get the full path.
Note that we naively assume there are no subdirectories here.
event fileList(Path:string, Contents:array) {
foreach(_:number, Name:string = Contents) {
if(fileCanLoad()) {
fileLoad(Path + Name)
} else { break }
}
}
Finally, we'll copy the code in the previous example using event fileLoaded
to print the contents of the file and its path, except modified to not include time.
event fileLoaded(Path:string, Data:string) {
print(format("%s: %s", Path, Data))
}
After running our code, you should see an output like this:
manyfiles/1.txt: This is file #1!
manyfiles/2.txt: This is file #2!
manyfiles/3.txt: This is file #3!
manyfiles/4.txt: This is file #4!
manyfiles/5.txt: This is file #5!
Note that the queue is not asynchronous, so the queue will always execute in the order that you loaded files.
Full example code
@name File Queues
@trigger none
@strict
for(I = 1, 10) {
if(fileCanWrite()) {
fileWrite(format("manyfiles/%d.txt", I), format("This is file #%d!", I))
} else { break }
}
event fileWritten(_:string, _:string) {
if(fileWriteQueued() == 0) {
fileList("manyfiles/")
}
}
event fileList(Path:string, Contents:array) {
foreach(_:number, Name:string = Contents) {
if(fileCanLoad()) {
fileLoad(Path + Name)
} else { break }
}
}
event fileLoaded(Path:string, Data:string) {
print(format("%s: %s", Path, Data))
}
Please do not alter the e2 docs ...
pages manually.
They are autogenerated from the E2Helper. In the future, this will hopefully be its own dedicated website or tool.
Basic Features: core, debug, number, selfaware,
string, timer
🌎 World: angle, color, find, ranger, sound,
🔣 Math: bitwise, complex, matrix, quaternion, vector, vector2/4
📦 Entities: bone, constraint, egp, entity, hologram, npc
👨 Players: chat, console, player, weapon
📊 Data storage: array, files, globalvars, serialization, table
💬 Communication: datasignal, http, signal, wirelink,
❓ Informational: gametick, serverinfo, steamidconv, unitconv
Disabled by default: constraintcore, effects, propcore, remoteupload, wiring
Wire-Extras (repo): camera, ftrace, holoanim, light, stcontrol, tracesystem
- Home 🏠
- Syntax 🔣
- Directives 🎛️
- Editor 🖥️
- Events 🌟 (new!)
Click To Expand
- 🟥 SPU
- 🟥 Address Bus
- 🟥 Extended Bus
- 🟥 Plug/Socket
- 🟥 Port
- 🟥 Transfer Bus
- 🟩 GPU
- 🟥 Dynamic Memory
- 🟥 Flash EEPROM
- 🟥 ROM
- 🟧 Beacon Sensor
- 🟧 Locator
- 🟧 Target Finder
- 🟧 Waypoint
- 🟥 XYZ Beacon
- 🟩 CPU
- 🟩 Expression 2
- 🟩 Gates
- 🟥 PID
- 🟧 CD Disk
- 🟥 CD Ray
- 🟧 DHDD
- 🟥 Keycard
- 🟥 RAM-card
- 🟧 Satellite Dish
- 🟧 Store
- 🟧 Transferer
- 🟥 Wired Wirer
- 🟧 Adv Entity Marker
- 🟧 Damage Detector
- 🟧 Entity Marker
- 🟧 GPS
- 🟧 Gyroscope
- 🟥 HighSpeed Ranger
- 🟧 Laser Pointer Receiver
- 🟥 Microphone
- 🟧 Ranger
- 🟧 Speedometer
- 🟧 Water Sensor
- 🟧 7 Segment Display
- 🟥 Adv. Hud Indicator
- 🟧 Console Screen
- 🟧 Control Panel
- 🟧 Digital Screen
- 🟧 EGP v3
- 🟧 Fix RenderTargets
- 🟥 GPULib Switcher
- 🟧 Hud Indicator
- 🟧 Indicator
- 🟧 Lamp
- 🟧 Light
- 🟧 Oscilloscope
- 🟧 Pixel
- 🟧 Screen
- 🟧 Sound Emitter
- 🟧 Text Screen
- 🟩 Cam Controller
- 🟧 Colorer
- 🟧 FX Emitter
- 🟧 HighSpeed Holoemitter
- 🟧 HoloEmitter
- 🟧 HoloGrid
- 🟥 Interactable Holography Emitter
- 🟥 Materializer
- 🟥 Painter
- 🟧 Adv. Input
- 🟧 Button
- 🟧 Constant Value
- 🟥 Door Controller
- 🟧 Dual Input
- 🟧 Dynamic Button
- 🟧 Eye Pod
- 🟧 Graphics Tablet
- 🟧 Keyboard
- 🟥 Lever
- 🟧 Numpad
- 🟧 Numpad Input
- 🟧 Numpad Output
- 🟧 Plug
- 🟧 Pod Controller
- 🟧 Radio
- 🟧 Relay
- 🟧 Text Receiver
- 🟧 Two-way Radio
- 🟧 Vehicle Controller
- 🟥 Door
- 🟥 Adv. Dupe. Teleporter
- 🟥 Buoyancy
- 🟧 Clutch
- 🟧 Detonator
- 🟧 Explosives
- 🟧 Explosives (Simple)
- 🟥 Forcer
- 🟩 Freezer
- 🟧 Gimbal (Facer)
- 🟧 Grabber
- 🟧 Hoverball
- 🟧 Hoverdrive Controller
- 🟥 Hydraulic
- 🟧 Igniter
- 🟧 Nailer
- 🟩 Prop Spawner
- 🟥 Servo
- 🟥 Simple Servo
- 🟧 Thruster
- 🟥 Touchplate
- 🟥 Trail
- 🟩 Turret
- 🟩 User
- 🟥 Vector Thruster
- 🟥 Vehicle Exit Point
- 🟧 Weight (Adjustable)
- 🟧 Weld/Constraint Latch
- 🟥 Wheel
- 🟥 Wire Magnet
- 🟥 Wired Npc Controller
- 🟧 Debugger
- 🟥 GUI Wiring
- 🟥 Multi Wire
- 🟧 Namer
- 🟥 Simulate Data
- 🟩 Wiring
- 🟥 Beam Reader
- 🟥 Implanter
- 🟥 Reader
- 🟥 Target Filter
- 🟥 User Reader
Gates 🚥
Click To Expand
TBD