Skip to content

Commit 4b8d3b3

Browse files
committed
0.6.2
* Remove e2 preprocessor usage for e2 core, allowing for linting and a simpler ci. * Add runtime ``@strict`` only errors if you try and use xwa method functions on an invalid object * Fix issue where WebAudio messages wouldn't go through in the same tick for a client. This would sometimes leave webaudios alive on your client while they were purged on the server.
1 parent 2d85272 commit 4b8d3b3

7 files changed

Lines changed: 696 additions & 224 deletions

File tree

.github/workflows/linter.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,9 @@ on:
77
push:
88
paths:
99
- 'lua/**'
10-
- '!lua/entities/gmod_wire_expression2/**' # Ignore E2 path since it uses preprocessor stuff.
1110
pull_request:
1211
paths:
1312
- 'lua/**'
14-
- '!lua/entities/gmod_wire_expression2/**'
1513
workflow_dispatch:
1614

1715

@@ -26,8 +24,5 @@ jobs:
2624
curl -o glualint.zip -L https://github.com/FPtje/GLuaFixer/releases/download/1.18.2/glualint-1.18.2-linux.zip
2725
unzip glualint.zip
2826
29-
- name: Remove E2 Extension Folder
30-
run: rm -r lua/entities/gmod_wire_expression2/
31-
3227
- name: Lint Code
3328
run: ./glualint lua

definitions.lua

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,52 @@
1+
---@diagnostic disable:lowercase-global
2+
13
---@type boolean
24
SERVER = nil
35

46
---@type boolean
57
CLIENT = nil
68

7-
E2Helper = {}
9+
E2Helper = {}
10+
E2Lib = {}
11+
12+
wire_expression2_funcs = {}
13+
14+
---@param msg string
15+
---@param level integer?
16+
---@param trace table
17+
---@param can_catch boolean? Default true
18+
function E2Lib.raiseException(msg, level, trace, can_catch)
19+
end
20+
21+
---@param name string
22+
---@param value number
23+
function E2Lib.registerConstant(name, value, literal)
24+
25+
end
26+
27+
---@param num integer
28+
function __e2setcost(num) end
29+
30+
---@param name string
31+
---@param id string
32+
---@param def any
33+
function registerType(name, id, def, ...)
34+
35+
end
36+
37+
---@param name string name of the function
38+
---@param pars string params
39+
---@param rets string ret
40+
---@param func function
41+
---@param cost number?
42+
---@param argnames table?
43+
function registerOperator(name, pars, rets, func, cost, argnames)
44+
45+
end
46+
47+
48+
registerFunction = registerOperator
49+
50+
---@param name string
51+
---@param cb function
52+
function registerCallback(name, cb) end

lua/autorun/webaudio.lua

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,44 @@
77
-- If you ever change a setting of the Interface object, will add one of these flags to it.
88
-- This will be sent to the client to know what to read in the net message to save networking
99
local Modify = {
10-
volume = 1,
11-
time = 2,
12-
pos = 4,
13-
playing = 8,
14-
playback_rate = 16,
15-
direction = 32,
16-
parented = 64,
17-
radius = 128,
18-
looping = 256,
19-
mode = 512,
20-
21-
destroyed = 1024
10+
volume = 0b000000000001,
11+
time = 0b000000000010,
12+
pos = 0b000000000100,
13+
playing = 0b000000001000,
14+
playback_rate = 0b000000010000,
15+
direction = 0b000000100000,
16+
parented = 0b000001000000,
17+
radius = 0b000010000000,
18+
looping = 0b000100000000,
19+
mode = 0b001000000000,
20+
reserved = 0b010000000000, -- pan maybe?
21+
22+
destroyed = 0b100000000000,
23+
24+
all = 0b111111111111
2225
}
2326

27+
-- Bits needed to send a bitflag of all the modifications
28+
local MODIFY_LEN = math.ceil( math.log(Modify.all, 2) )
29+
30+
-- Max 1024 current streams
31+
local ID_LEN = math.ceil( math.log(1024, 2) )
32+
33+
local FFTSAMP_LEN = 8
34+
35+
local function toBinary(n, bits)
36+
bits = bits or 32
37+
38+
local t = {}
39+
for i = bits, 1, -1 do
40+
-- Basically go by each bit and use bit32.extract. Inlined the function here with width as 1.
41+
-- https://github.com/AlberTajuelo/bitop-lua/blob/8146f0b323f55f72eacbb2a8310922d50ae75ddf/src/bitop/funcs.lua#L92
42+
t[bits - i] = bit.band(bit.rshift(n, i), 1)
43+
end
44+
45+
return "0b" .. table.concat(t)
46+
end
47+
2448
local function hasModifyFlag(first, ...)
2549
return bit.band(first, ...) ~= 0
2650
end
@@ -85,6 +109,7 @@ end
85109

86110
--- Initiate WebAudio struct for both realms
87111
---@class WebAudio
112+
---@field url string # SHARED
88113
---@field stopwatch Stopwatch # SERVER
89114
---@field radius number # SHARED
90115
---@field radius_sqr number # SHARED
@@ -105,6 +130,10 @@ end
105130
_G.WebAudio = {}
106131
WebAudio.__index = WebAudio
107132

133+
WebAudio.MODIFY_LEN = MODIFY_LEN
134+
WebAudio.ID_LEN = ID_LEN
135+
WebAudio.FFTSAMP_LEN = FFTSAMP_LEN
136+
108137
---@alias WebAudioMode 0|1
109138

110139
---@type WebAudioMode
@@ -169,7 +198,7 @@ function WebAudio:IsDestroyed()
169198
end
170199

171200
--- Destroys a webaudio object and makes it the same (value wise) as WebAudio.getNULL()
172-
--- @param transmit boolean If SERVER, should we transmit the destruction to the client? Default true
201+
--- @param transmit boolean? If SERVER, should we transmit the destruction to the client? Default true
173202
function WebAudio:Destroy(transmit)
174203
if self:IsDestroyed() then return end
175204
if transmit == nil then transmit = true end
@@ -280,15 +309,6 @@ function WebAudioStatic.getNULL()
280309
return setmetatable({ destroyed = true }, WebAudio)
281310
end
282311

283-
-- Bit lengths
284-
local ID_LEN = 10
285-
local MODIFY_LEN = 11
286-
local FFTSAMP_LEN = 8
287-
288-
WebAudio.ID_LEN = ID_LEN
289-
WebAudio.MODIFY_LEN = MODIFY_LEN
290-
WebAudio.FFTSAMP_LEN = FFTSAMP_LEN
291-
292312
--- Same as net.ReadUInt but doesn't need the bit length in order to adapt our code more easily.
293313
---- @return number # # UInt10
294314
function WebAudioStatic.readID()
@@ -437,7 +457,7 @@ local function createWebAudio(_, url, owner, bassobj, id)
437457
self.needs_info = SERVER -- Whether this stream still needs information from the client.
438458
self.length = -1
439459
self.filename = ""
440-
self.fft = {} -- SERVER will receive this every think by default.
460+
self.fft = {}
441461

442462
if CLIENT then
443463
self.bass = bassobj
@@ -456,7 +476,7 @@ local function createWebAudio(_, url, owner, bassobj, id)
456476
WebAudio.writeID(self.id)
457477
net.WriteString(self.url)
458478
net.WriteEntity(self.owner)
459-
self:Broadcast() -- Defined in wa_interface
479+
self:Broadcast(false) -- Defined in wa_interface
460480
end
461481

462482
WebAudios[self.id] = self
@@ -660,8 +680,9 @@ concommand.Add("wa_list", function()
660680
local stream_list, n = {}, 0
661681
for id, stream in WebAudio.getIterator() do
662682
local owner = stream.owner
663-
if IsValid(owner) then
683+
if IsValid(owner) and owner:IsPlayer() then
664684
n = n + 1
685+
---@diagnostic disable-next-line (Emmylua definitions don't cover the Player class well.)
665686
stream_list[n] = string.format("[%d] %s(%s): '%s'", stream.id, owner:GetName(), owner:SteamID64() or "multirun", stream.url)
666687
end
667688
end
@@ -685,6 +706,7 @@ if CLIENT then
685706
local owner = stream.owner
686707
if owner and owner:IsValid() and stream.pos then
687708
local pos = stream.pos:ToScreen()
709+
---@diagnostic disable-next-line (Emmylua definitions don't cover the Player class well.)
688710
local txt = string.format("[%u] %s (%s)", id, owner:GetName(), owner:SteamID64() or "multirun")
689711
draw.DrawText( txt, "DermaDefault", pos.x, pos.y, Color_Aqua, TEXT_ALIGN_CENTER)
690712
end
@@ -715,6 +737,7 @@ WebAudio.Common = {
715737

716738
Modify = Modify,
717739
hasModifyFlag = hasModifyFlag,
740+
toBinary = toBinary,
718741
getFlags = getFlags,
719742

720743
--- Convars

lua/entities/gmod_wire_expression2/core/custom/cl_webaudio.lua

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,32 @@ local function desc(name, description)
55
tbl[name] = description
66
end
77

8+
--#region Base
89
desc("webAudio(s)", "Returns a WebAudio object of that URL as long as it is whitelisted by the server. Has a 500 ms cooldown between calls. If you can't create a webAudio object, will error, so check webAudioCanCreate before calling this!")
910
desc("webAudiosLeft()", "Returns the number of WebAudio objects you can create in total for your player")
1011
desc("webAudioCanCreate()", "Returns whether you can create a WebAudio object. Checks cooldown and whether you have another slot for a webaudio stream left.")
1112
desc("webAudioCanCreate(s)", "Same as webAudioCanCreate() but also checks if a URL is whitelisted on the server to use.")
13+
--#endregion
1214

13-
--- Misc
15+
--#region Misc
1416
desc("nowebaudio()", "Returns an invalid webaudio object")
17+
desc("toString(xwa)", "Returns the something like ``WebAudio [<ID>]`` with <ID> being the ID of the stream")
18+
desc("toString(xwa:)", "Returns the something like ``WebAudio [<ID>]`` with <ID> being the ID of the stream")
19+
--#endregion
1520

16-
--- Permissions
21+
--#region Permissions
1722
desc("webAudioEnabled()", "Returns whether WebAudio playing is enabled on the server for E2")
1823
desc("webAudioAdminOnly()", "Returns whether WebAudio playing is restricted to admins or super admins. 0 for everyone, 1 for admins, 2 for superadmins")
24+
--#endregion
1925

20-
--- WebAudio Methods
26+
--#region Special Methods
2127
desc("update(xwa:)", "Sends all of the information of the object given by functions like setPos and setTime to the client. You need to call this after running functions without running ``:play()`` or ``:pause()`` on them since those sync with the client. Returns 1 if could update, 0 if hit transmission quota")
2228
desc("destroy(xwa:)", "Destroys the WebAudio object, rendering it useless. It will silently fail when trying to use it from here on! This gives you another slot to make a WebAudio object. Check if an object is destroyed with isValid!")
2329
desc("pause(xwa:)", "Pauses the stream where it is currently playing, Returns 1 or 0 if could successfully do so, because of quota. Automatically calls updates self internally.")
2430
desc("play(xwa:)", "Starts the stream or continues where it left off after pausing, Returns 1 or 0 if could successfully do so from quota. Automatically updates self internally.")
31+
--#endregion
2532

26-
-- Modify Object
33+
--#region Modify Object
2734
desc("setDirection(wxa:v)", "Sets the direction in which the WebAudio stream is playing towards without updating it. Remember to call ``self:update()`` when you are done modifying the object!")
2835
desc("setPos(xwa:v)", "Sets the 3D Position of the WebAudio stream without updating it. Remember to call ``self:update()`` when you are done modifying the object!")
2936
desc("setVolume(xwa:n)", "Sets the volume of the WebAudio stream, in percent format. 200 is 2x as loud as normal, 100 is default. Will error if it is past ``wa_volume_max``")
@@ -34,31 +41,39 @@ desc("setParent(xwa:)", "Unparents the stream")
3441
desc("setRadius(xwa:n)", "Sets the radius in which to the stream will be heard in. Default is 200 and (default) max is 1500.")
3542
desc("setLooping(xwa:n)", "If n is not 0, sets the stream to loop. Else stops looping.")
3643
desc("set3DEnabled(xwa:n)", "If n is not 0, sets the stream to be 3D. By default streams are 3D. Else, sets the audio to play directly on clients (mono audio).")
44+
--#endregion
3745

38-
-- is* Getters
46+
--#region is* Getters
3947
desc("isValid(xwa:)", "Returns 1 or 0 for whether the webaudio object is valid (If it is not destroyed & Not invalid from quota)")
4048
desc("isParented(xwa:)", "Returns 1 or 0 for whether the webaudio object is parented or not. Note that if the stream is parented, you cannot set it's position!")
49+
--#endregion
4150

42-
--- Getters
51+
--#region Getters
4352
desc("getPos(xwa:)", "Returns the current position of the WebAudio object. This does not work with parenting.")
4453
desc("getVolume(xwa:)", "Returns the volume of the WebAudio object set by setVolume")
4554
desc("getRadius(xwa:)", "Returns the radius of the WebAudio object set by setRadius")
4655
desc("getLooping(xwa:)", "Returns if the stream is looping, set by setLooping")
4756
desc("get3DEnabled(xwa:)", "Returns if the stream's 3D is enabled, set by set3DEnabled")
57+
--#endregion
4858

49-
-- Replicated Clientside behavior on server
59+
--#region Replicated Clientside behavior on server
5060
desc("getTime(xwa:)", "Returns the playback time of the stream in seconds.")
5161
desc("getState(xwa:)", "Returns the state of the stream. 0 is Stopped, 1 is Playing, 2 is Paused. See the CHANNEL_* constants")
62+
--#endregion
5263

53-
-- Info received from client
64+
--#region Info received from client
5465
desc("getLength(xwa:)", "Returns the playback duration of the stream in seconds. Will return -1 if couldn't get length.")
5566
desc("getFileName(xwa:)", "Returns the file name of the WebAudio stream. Will usually be the URL you give, but not always. Will return \"\" if we haven't received the name yet.")
5667
desc("getFFT(xwa:)", "Returns the fast fourier transform of the webaudio stream. It is an array of 64 numbers or less, ranging from 0 to 255")
68+
--#endregion
5769

58-
-- Aliases
70+
--#region Aliases
5971
desc("unparent(xwa:)", "Alias of xwa:setParent(), Unparents the stream")
6072
desc("parentTo(xwa:e)", "Alias of xwa:setParent(), Parents the stream to entity e")
73+
--#endregion
6174

75+
--#region Ignore System
6276
desc("setIgnored(xwa:en)", "If n is not 0, blocks the given user from hearing the stream. Else, unblocks the user.")
6377
desc("setIgnored(xwa:rn)", "If n is not 0, sets the stream to ignore certain players. Else, unblocks them.")
6478
desc("getIgnored(xwa:e)", "Returns if the user is blocked from hearing the stream. Note this also counts if they purged the webaudio stream themself, but doesn't count if they have webaudio disabled. Set by setIgnored")
79+
--#endregion

0 commit comments

Comments
 (0)