From d81fdc86f39ae445d44c3f52a712d24c68c260fb Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Mon, 1 Sep 2025 09:48:32 -0400
Subject: [PATCH 01/10] Create E2Table class
---
.../gmod_wire_expression2/core/e2lib.lua | 179 +++++++++++++++++-
1 file changed, 174 insertions(+), 5 deletions(-)
diff --git a/lua/entities/gmod_wire_expression2/core/e2lib.lua b/lua/entities/gmod_wire_expression2/core/e2lib.lua
index 11ae13fc2b..20a0b7efb9 100644
--- a/lua/entities/gmod_wire_expression2/core/e2lib.lua
+++ b/lua/entities/gmod_wire_expression2/core/e2lib.lua
@@ -221,11 +221,6 @@ function E2Lib.setSubMaterial(ent, index, material)
duplicator.StoreEntityModifier(ent, "submaterial", { ["SubMaterialOverride_"..index] = material })
end
--- Returns a default e2 table instance.
-function E2Lib.newE2Table()
- return { n = {}, ntypes = {}, s = {}, stypes = {}, size = 0 }
-end
-
---@class E2Lambda
---@field fn fun(args: any[]): any
---@field arg_sig string
@@ -303,6 +298,180 @@ function Function:Unwrap(arg_sig, ctx)
end
end
+--- A wrapper for Lua tables for use in E2.
+--- When called as a function, will create a new `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
+--- Otherwise, returns an empty E2Table.
+--- The `typeids` argument is optional. It will be used for typeids instead of type inferral. Useful for table-based types.
+---@return E2Table
+---@class E2Table
+---@field n table A table containing only numeric keys
+---@field ntypes table A table with typeids corresponding to numeric keys
+---@field s table A table containing only string keys
+---@field stypes table A table with typeids corresponding to string keys
+---@field size number The size of the table. This is equivalent to `table.Count(self.n) + table.Count(self.s)`
+---@overload fun(data:{ [string|number]:any }?, typeids:{ [string|number]:any }?):E2Table
+local E2Table = {}
+E2Table.__index = E2Table
+
+local _e2table_infer_type_lut = {
+ TYPE_NUMBER = "n",
+ TYPE_STRING = "s",
+ TYPE_ENTITY = "e",
+ TYPE_VECTOR = "v",
+ TYPE_ANGLE = "a",
+ TYPE_PHYSOBJ = "b"
+}
+---Does a simple attempt at inferring the type of an object.
+local function _e2table_infer_type(v)
+ local tp = TypeID(v)
+ local easy_type = _e2table_infer_type_lut[tp]
+ if easy_type then return easy_type end
+ if istable(v) then
+ -- lame workaround that'll get fixed in 5 years or something
+ local mt = getmetatable(v)
+ if mt then
+ if mt == E2Table then
+ return "t"
+ elseif mt == Function then
+ return "f"
+ end
+ end
+ end
+end
+
+---Sets the key to the value and assigns it the typeid. Special types will require `typeid` to be set.
+---@param key string|number The key. Must be a string or number.
+---@param value any The value to be stored.
+---@param typeid string? The typeid of the value. Will be inferred if nil.
+function E2Table:Set(key, value, typeid)
+ if not typeid then
+ typeid = _e2table_infer_type(value) or error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key)))
+ end
+
+ if key then
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ if not dest_type[key] then self.size = self.size + 1 end
+ dest[key] = value
+ dest_type[key] = typeid
+ end
+end
+
+---Returns the typeid and value of the key, if it exists.
+---@param key string|number The key. Must be a string or number.
+---@return string? typeid The typeid of the key or nil if it doesn't exist.
+---@return any? value The value at the key if it exists.
+function E2Table:Get(key)
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ return dest_type[key], dest[key]
+end
+
+---Returns the typeid, value, source typeid table, source table
+local function _e2table_get_ext(self, key)
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ return dest_type[key], dest[key], dest_type, dest
+end
+
+---Returns the typeid and value of the key and removes it from the table.
+---This will not shift elements down the sequential part of the array.
+---@param key string|number The key. Must be a string or number.
+---@return string? typeid The typeid of the key or nil if it doesn't exist.
+---@return any? value The value at the key if it exists.
+function E2Table:Unset(key)
+ local typeid, value, dest_type, dest = _e2table_get_ext(self, key)
+
+ if typeid then
+ dest[key] = nil
+ dest_type[key] = nil
+ self.size = self.size - 1
+ end
+ return typeid, value
+end
+
+---Returns the typeid and value of the key and removes it from the table.
+---This *will* shift elements down the sequential part of the array.
+---@param key string|number The key. Must be a string or number.
+---@return string? typeid The typeid of the key or nil if it doesn't exist.
+---@return any? value The value at the key if it exists.
+function E2Table:Remove(key)
+ local typeid, value, dest_type, dest = _e2table_get_ext(self, key)
+
+ if typeid then
+ if isnumber(key) and table.remove(dest_type, key --[[@as number]]) then
+ -- table.remove will return nil if it fails, meaning we need to unset
+ ---@cast key number
+ table.remove(dest, key)
+ else
+ dest[key] = nil
+ dest_type[key] = nil
+ end
+ self.size = self.size - 1
+ end
+ return typeid, value
+end
+
+--- Returns an `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
+--- Otherwise, returns an empty E2Table.
+---@param data { [number|string]:any }? The data to store in the E2Table.
+---@param typeids { [number|string]:any }? Optional typeids. Does not need to include every typeid. Useful for table-based types.
+---@return E2Table
+local function newE2Table(data, typeids)
+ ---@cast E2Table -function
+ if data then
+ local n, ntypes, s, stypes, size = {}, {}, {}, {}, 0
+ for key, value in pairs(data) do
+ local dest, dest_types
+ if isnumber(key) then
+ dest = n
+ dest_types = ntypes
+ elseif isstring(key) then
+ dest = s
+ dest_types = stypes
+ else
+ error(string.format("Tried to create E2 table with invalid key type: %s, type: %s", tostring(key), type(key)))
+ end
+ local tp = typeids and typeids[key] or _e2table_infer_type(value)
+ if not tp then error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key))) end
+ dest[key] = value
+ dest_types[key] = tp
+ size = size + 1
+ end
+ return setmetatable({ n = n, ntypes = ntypes, s = s, stypes = stypes, size = size }, E2Table)
+ else
+ return setmetatable({ n = {}, ntypes = {}, s = {}, stypes = {}, size = 0 }, E2Table)
+ end
+end
+E2Table.New = newE2Table
+
+function E2Table:__call(data, typeids)
+ return newE2Table(data, typeids)
+end
+
+E2Lib.E2Table = E2Table
+
+--- Deprecated. Creates an empty `E2Table`. Use `E2Lib.E2Table` or `E2Lib.E2Table.New` instead.
+---@see E2Table
+---@deprecated
+local function newE2Table_compat()
+ return newE2Table()
+end
+
+E2Lib.newE2Table = newE2Table_compat -- Deprecated, backwards compat
+
-- Returns a cloned table of the variable given if it is a table.
-- TODO: Ditch this system for instead having users provide a function that returns the default value.
-- Would be much more efficient and avoid type checks.
From 52b76a48d6a896d98c1fd991f17d5e4d470d9034 Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Mon, 1 Sep 2025 10:21:10 -0400
Subject: [PATCH 02/10] Update prop to new API
---
.../core/custom/prop.lua | 56 ++++++++-----------
1 file changed, 22 insertions(+), 34 deletions(-)
diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua
index 86ee6ca7e3..3a2a3fc017 100644
--- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua
+++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua
@@ -21,6 +21,8 @@ local setAng = WireLib.setAng
local typeIDToString = WireLib.typeIDToString
local castE2ValueToLuaValue = E2Lib.castE2ValueToLuaValue
+local newE2Table = E2Lib.E2Table.New
+
local E2totalspawnedprops = 0
local playerMeta = FindMetaTable("Player")
@@ -506,7 +508,7 @@ end
__e2setcost(30)
[nodiscard]
e2function table sentGetData(string class)
- local res = E2Lib.newE2Table()
+ local res = newE2Table()
local sent = list.Get("wire_spawnable_ents_registry")[class]
if not sent then self:throw("No class '"..class.."' found in sent registry", res) end
@@ -515,16 +517,13 @@ e2function table sentGetData(string class)
for key, tbl in pairs( sent ) do
if key=="_preFactory" or key=="_postFactory" then continue end
- res.s[key] = E2Lib.newE2Table()
- res.s[key].size = 2
- res.s[key].s["type"] = typeIDToString(tbl[1])
- res.s[key].s["default_value"] = sentDataFormatDefaultVal(tbl[2])
- res.s[key].s["description"] = tbl[3] or ""
- res.stypes[key] = "t"
-
- size = size + 1
+ local subt = newE2Table({
+ type = typeIDToString(tbl[1]),
+ default_value = sentDataFormatDefaultVal(tbl[2]),
+ description = tbl[3] or ""
+ })
+ res:Set(key, subt)
end
- res.size = size
return res
end
@@ -537,11 +536,11 @@ e2function table sentGetData(string class, string key)
if not sent[key] then self:throw("Class '"..class.."' does not have any value at key '"..key.."'", "") end
if key=="_preFactory" or key=="_postFactory" then self:throw("Prohibited key '"..key.."'", "") end
- local res = E2Lib.newE2Table()
- res.s["type"] = typeIDToString(sent[key][1])
- res.s["default_value"] = sentDataFormatDefaultVal(sent[key][2])
- res.s["description"] = sent[key][3] or ""
- res.size = 3
+ local res = newE2Table({
+ type = typeIDToString(tbl[1]),
+ default_value = sentDataFormatDefaultVal(tbl[2]),
+ description = tbl[3] or ""
+ })
return res
end
@@ -551,19 +550,16 @@ end
__e2setcost(25)
[nodiscard]
e2function table sentGetDataTypes(string class)
- local res = E2Lib.newE2Table()
+ local res = newE2Table()
local sent = list.Get("wire_spawnable_ents_registry")[class]
if not sent then self:throw("No class '"..class.."' found in sent registry", res) end
- local size = 0
for key, tbl in pairs( sent ) do
if key=="_preFactory" or key=="_postFactory" then continue end
- res.s[key] = typeIDToString(tbl[1])
- size = size + 1
+ res:Set(key, typeIDToString(tbl[1]))
end
- res.size = size
return res
end
@@ -584,19 +580,16 @@ end
__e2setcost(25)
[nodiscard]
e2function table sentGetDataDefaultValues(string class)
- local res = E2Lib.newE2Table()
+ local res = newE2Table()
local sent = list.Get("wire_spawnable_ents_registry")[class]
if not sent then self:throw("No class '"..class.."' found in sent registry", res) end
- local size = 0
for key, tbl in pairs( sent ) do
if key=="_preFactory" or key=="_postFactory" then continue end
- res.s[key] = sentDataFormatDefaultVal(tbl[2])
- size = size + 1
+ res:Set(key, sentDataFormatDefaultVal(tbl[2]))
end
- res.size = size
return res
end
@@ -617,19 +610,16 @@ end
__e2setcost(25)
[nodiscard]
e2function table sentGetDataDescriptions(string class)
- local res = E2Lib.newE2Table()
+ local res = newE2Table()
local sent = list.Get("wire_spawnable_ents_registry")[class]
if not sent then self:throw("No class '"..class.."' found in sent registry", res) end
- local size = 0
for key, tbl in pairs( sent ) do
if key=="_preFactory" or key=="_postFactory" then continue end
- res.s[key] = tbl[3] or ""
- size = size + 1
+ res:Set(key, tbl[3] or "")
end
- res.size = size
return res
end
@@ -1255,13 +1245,13 @@ end
e2function table entity:ragdollGetPose()
if not ValidAction(self, this) then return end
- local pose = E2Lib.newE2Table()
+ local pose = newE2Table()
local bones = GetBones(this)
local originPos, originAng = bones[0]:GetPos(), bones[0]:GetAngles()
local size = 0
for k, bone in pairs(bones) do
- local value = E2Lib.newE2Table()
+ local value = newE2Table()
local pos, ang = WorldToLocal(bone:GetPos(), bone:GetAngles(), originPos, originAng)
value.n[1] = pos
@@ -1495,8 +1485,6 @@ local typefilter = {
number = "n",
}
-local newE2Table = E2Lib.newE2Table
-
__e2setcost(20)
e2function table collision:toTable()
From 2f9685f8db720785807ae03fa10c63a916859495 Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Mon, 1 Sep 2025 10:21:15 -0400
Subject: [PATCH 03/10] Update table to new API
---
.../gmod_wire_expression2/core/table.lua | 41 ++++++++-----------
1 file changed, 16 insertions(+), 25 deletions(-)
diff --git a/lua/entities/gmod_wire_expression2/core/table.lua b/lua/entities/gmod_wire_expression2/core/table.lua
index 76dd69514c..19f244e4bf 100644
--- a/lua/entities/gmod_wire_expression2/core/table.lua
+++ b/lua/entities/gmod_wire_expression2/core/table.lua
@@ -8,6 +8,8 @@ local tostring = tostring
local table = table
local type = type
+local newE2Table = E2Lib.E2Table.New
+
local opcost = 1/3 -- cost of looping through table multiplier
-- All different table types in E2
@@ -33,8 +35,6 @@ end
-- Type defining
--------------------------------------------------------------------------------
-local newE2Table = E2Lib.newE2Table
-
registerType("table", "t", newE2Table(),
function(self, input)
if input.size == 0 then
@@ -524,28 +524,20 @@ end
-- Removes the specified entry from the array-part and returns 1 if removed
e2function number table:remove( number index )
if (#this.n == 0) then return 0 end
- if (not this.n[index]) then return 0 end
- if index < 1 then -- table.remove doesn't work if the index is below 1
- this.n[index] = nil
- this.ntypes[index] = nil
- else
- table.remove( this.n, index )
- table.remove( this.ntypes, index )
+ if this:Remove(index) then
+ self.GlobalScope.vclk[this] = true
+ return 1
end
- this.size = this.size - 1
- self.GlobalScope.vclk[this] = true
- return 1
+ return 0
end
--- Force removes the specified entry from the table-part, without moving subsequent entries down and returns 1 if removed
e2function number table:remove( string index )
if (IsEmpty(this.s)) then return 0 end
- if (not this.s[index]) then return 0 end
- this.s[index] = nil
- this.stypes[index] = nil
- this.size = this.size - 1
- self.GlobalScope.vclk[this] = true
- return 1
+ if this:Unset(index) then
+ self.GlobalScope.vclk[this] = true
+ return 1
+ end
+ return 0
end
--------------------------------------------------------------------------------
@@ -554,12 +546,11 @@ end
-- Does not shift larger indexes down to fill the hole
--------------------------------------------------------------------------------
e2function number table:unset( index )
- if this.n[index] == nil then return 0 end
- this.n[index] = nil
- this.ntypes[index] = nil
- this.size = this.size - 1
- self.GlobalScope.vclk[this] = true
- return 1
+ if this:Unset(index) then
+ self.GlobalScope.vclk[this] = exists
+ return 1
+ end
+ return 0
end
-- Force remove for strings is an alias to table:remove(string)
From 35ab7e3977de22225bfde11d9bcea3786325ee9b Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Mon, 1 Sep 2025 10:33:10 -0400
Subject: [PATCH 04/10] dumb
---
lua/entities/gmod_wire_expression2/core/e2lib.lua | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/lua/entities/gmod_wire_expression2/core/e2lib.lua b/lua/entities/gmod_wire_expression2/core/e2lib.lua
index 20a0b7efb9..e42638bdd6 100644
--- a/lua/entities/gmod_wire_expression2/core/e2lib.lua
+++ b/lua/entities/gmod_wire_expression2/core/e2lib.lua
@@ -314,12 +314,12 @@ local E2Table = {}
E2Table.__index = E2Table
local _e2table_infer_type_lut = {
- TYPE_NUMBER = "n",
- TYPE_STRING = "s",
- TYPE_ENTITY = "e",
- TYPE_VECTOR = "v",
- TYPE_ANGLE = "a",
- TYPE_PHYSOBJ = "b"
+ [TYPE_NUMBER] = "n",
+ [TYPE_STRING] = "s",
+ [TYPE_ENTITY] = "e",
+ [TYPE_VECTOR] = "v",
+ [TYPE_ANGLE] = "a",
+ [TYPE_PHYSOBJ] = "b"
}
---Does a simple attempt at inferring the type of an object.
local function _e2table_infer_type(v)
From dea24f8652172bb0af031d3d376ed1c23cfce080 Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Mon, 1 Sep 2025 10:38:38 -0400
Subject: [PATCH 05/10] Remove useless comment
---
lua/entities/gmod_wire_expression2/core/e2lib.lua | 1 -
1 file changed, 1 deletion(-)
diff --git a/lua/entities/gmod_wire_expression2/core/e2lib.lua b/lua/entities/gmod_wire_expression2/core/e2lib.lua
index e42638bdd6..7caf54b3e1 100644
--- a/lua/entities/gmod_wire_expression2/core/e2lib.lua
+++ b/lua/entities/gmod_wire_expression2/core/e2lib.lua
@@ -302,7 +302,6 @@ end
--- When called as a function, will create a new `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
--- Otherwise, returns an empty E2Table.
--- The `typeids` argument is optional. It will be used for typeids instead of type inferral. Useful for table-based types.
----@return E2Table
---@class E2Table
---@field n table A table containing only numeric keys
---@field ntypes table A table with typeids corresponding to numeric keys
From f42e969620a012f989c5f818d018cc942ff1d024 Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Mon, 1 Sep 2025 22:20:41 -0400
Subject: [PATCH 06/10] Move E2Table to WireLib
---
.../gmod_wire_expression2/core/e2lib.lua | 166 +----------------
lua/wire/server/wirelib.lua | 168 +++++++++++++++++-
2 files changed, 169 insertions(+), 165 deletions(-)
diff --git a/lua/entities/gmod_wire_expression2/core/e2lib.lua b/lua/entities/gmod_wire_expression2/core/e2lib.lua
index 7caf54b3e1..b1fef2096b 100644
--- a/lua/entities/gmod_wire_expression2/core/e2lib.lua
+++ b/lua/entities/gmod_wire_expression2/core/e2lib.lua
@@ -298,171 +298,9 @@ function Function:Unwrap(arg_sig, ctx)
end
end
---- A wrapper for Lua tables for use in E2.
---- When called as a function, will create a new `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
---- Otherwise, returns an empty E2Table.
---- The `typeids` argument is optional. It will be used for typeids instead of type inferral. Useful for table-based types.
----@class E2Table
----@field n table A table containing only numeric keys
----@field ntypes table A table with typeids corresponding to numeric keys
----@field s table A table containing only string keys
----@field stypes table A table with typeids corresponding to string keys
----@field size number The size of the table. This is equivalent to `table.Count(self.n) + table.Count(self.s)`
----@overload fun(data:{ [string|number]:any }?, typeids:{ [string|number]:any }?):E2Table
-local E2Table = {}
-E2Table.__index = E2Table
-
-local _e2table_infer_type_lut = {
- [TYPE_NUMBER] = "n",
- [TYPE_STRING] = "s",
- [TYPE_ENTITY] = "e",
- [TYPE_VECTOR] = "v",
- [TYPE_ANGLE] = "a",
- [TYPE_PHYSOBJ] = "b"
-}
----Does a simple attempt at inferring the type of an object.
-local function _e2table_infer_type(v)
- local tp = TypeID(v)
- local easy_type = _e2table_infer_type_lut[tp]
- if easy_type then return easy_type end
- if istable(v) then
- -- lame workaround that'll get fixed in 5 years or something
- local mt = getmetatable(v)
- if mt then
- if mt == E2Table then
- return "t"
- elseif mt == Function then
- return "f"
- end
- end
- end
-end
-
----Sets the key to the value and assigns it the typeid. Special types will require `typeid` to be set.
----@param key string|number The key. Must be a string or number.
----@param value any The value to be stored.
----@param typeid string? The typeid of the value. Will be inferred if nil.
-function E2Table:Set(key, value, typeid)
- if not typeid then
- typeid = _e2table_infer_type(value) or error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key)))
- end
-
- if key then
- local dest, dest_type
- if isnumber(key) then
- dest, dest_type = self.n, self.ntypes
- else
- dest, dest_type = self.s, self.stypes
- end
- if not dest_type[key] then self.size = self.size + 1 end
- dest[key] = value
- dest_type[key] = typeid
- end
-end
-
----Returns the typeid and value of the key, if it exists.
----@param key string|number The key. Must be a string or number.
----@return string? typeid The typeid of the key or nil if it doesn't exist.
----@return any? value The value at the key if it exists.
-function E2Table:Get(key)
- local dest, dest_type
- if isnumber(key) then
- dest, dest_type = self.n, self.ntypes
- else
- dest, dest_type = self.s, self.stypes
- end
- return dest_type[key], dest[key]
-end
-
----Returns the typeid, value, source typeid table, source table
-local function _e2table_get_ext(self, key)
- local dest, dest_type
- if isnumber(key) then
- dest, dest_type = self.n, self.ntypes
- else
- dest, dest_type = self.s, self.stypes
- end
- return dest_type[key], dest[key], dest_type, dest
-end
-
----Returns the typeid and value of the key and removes it from the table.
----This will not shift elements down the sequential part of the array.
----@param key string|number The key. Must be a string or number.
----@return string? typeid The typeid of the key or nil if it doesn't exist.
----@return any? value The value at the key if it exists.
-function E2Table:Unset(key)
- local typeid, value, dest_type, dest = _e2table_get_ext(self, key)
-
- if typeid then
- dest[key] = nil
- dest_type[key] = nil
- self.size = self.size - 1
- end
- return typeid, value
-end
-
----Returns the typeid and value of the key and removes it from the table.
----This *will* shift elements down the sequential part of the array.
----@param key string|number The key. Must be a string or number.
----@return string? typeid The typeid of the key or nil if it doesn't exist.
----@return any? value The value at the key if it exists.
-function E2Table:Remove(key)
- local typeid, value, dest_type, dest = _e2table_get_ext(self, key)
-
- if typeid then
- if isnumber(key) and table.remove(dest_type, key --[[@as number]]) then
- -- table.remove will return nil if it fails, meaning we need to unset
- ---@cast key number
- table.remove(dest, key)
- else
- dest[key] = nil
- dest_type[key] = nil
- end
- self.size = self.size - 1
- end
- return typeid, value
-end
-
---- Returns an `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
---- Otherwise, returns an empty E2Table.
----@param data { [number|string]:any }? The data to store in the E2Table.
----@param typeids { [number|string]:any }? Optional typeids. Does not need to include every typeid. Useful for table-based types.
----@return E2Table
-local function newE2Table(data, typeids)
- ---@cast E2Table -function
- if data then
- local n, ntypes, s, stypes, size = {}, {}, {}, {}, 0
- for key, value in pairs(data) do
- local dest, dest_types
- if isnumber(key) then
- dest = n
- dest_types = ntypes
- elseif isstring(key) then
- dest = s
- dest_types = stypes
- else
- error(string.format("Tried to create E2 table with invalid key type: %s, type: %s", tostring(key), type(key)))
- end
- local tp = typeids and typeids[key] or _e2table_infer_type(value)
- if not tp then error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key))) end
- dest[key] = value
- dest_types[key] = tp
- size = size + 1
- end
- return setmetatable({ n = n, ntypes = ntypes, s = s, stypes = stypes, size = size }, E2Table)
- else
- return setmetatable({ n = {}, ntypes = {}, s = {}, stypes = {}, size = 0 }, E2Table)
- end
-end
-E2Table.New = newE2Table
-
-function E2Table:__call(data, typeids)
- return newE2Table(data, typeids)
-end
-
-E2Lib.E2Table = E2Table
+local newE2Table = WireLib.E2Table.New
---- Deprecated. Creates an empty `E2Table`. Use `E2Lib.E2Table` or `E2Lib.E2Table.New` instead.
+--- Deprecated. Creates an empty `E2Table`. Use `WireLib.E2Table` or `WireLib.E2Table.New` instead.
---@see E2Table
---@deprecated
local function newE2Table_compat()
diff --git a/lua/wire/server/wirelib.lua b/lua/wire/server/wirelib.lua
index 367acb275c..63eb16cc61 100644
--- a/lua/wire/server/wirelib.lua
+++ b/lua/wire/server/wirelib.lua
@@ -95,6 +95,172 @@ function WireLib.TriggerInput(ent, name, value, ...)
end
end
+local newE2Table
+do
+ --- A wrapper for Lua tables for use in E2.
+ --- When called as a function, will create a new `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
+ --- Otherwise, returns an empty E2Table.
+ --- The `typeids` argument is optional. It will be used for typeids instead of type inferral. Useful for table-based types.
+ ---@class E2Table
+ ---@field n table A table containing only numeric keys
+ ---@field ntypes table A table with typeids corresponding to numeric keys
+ ---@field s table A table containing only string keys
+ ---@field stypes table A table with typeids corresponding to string keys
+ ---@field size number The size of the table. This is equivalent to `table.Count(self.n) + table.Count(self.s)`
+ ---@overload fun(data:{ [string|number]:any }?, typeids:{ [string|number]:any }?):E2Table
+ local E2Table = {}
+ E2Table.__index = E2Table
+
+ local e2t_tp_lut = {
+ [TYPE_NUMBER] = "n",
+ [TYPE_STRING] = "s",
+ [TYPE_ENTITY] = "e",
+ [TYPE_VECTOR] = "v",
+ [TYPE_ANGLE] = "a",
+ [TYPE_PHYSOBJ] = "b"
+ }
+ ---Does a simple attempt at inferring the type of an object.
+ local function e2t_infer_tp(v)
+ local tp = TypeID(v)
+ local easy_tp = e2t_tp_lut[tp]
+ if easy_tp then return easy_tp end
+ if istable(v) then
+ local mt = getmetatable(v)
+ if mt then
+ if mt == E2Table then
+ return "t"
+ elseif E2Lib and mt == E2Lib.Function then
+ return "f"
+ end
+ end
+ end
+ end
+
+ ---Sets the key to the value and assigns it the typeid. Special types will require `typeid` to be set.
+ ---@param key string|number The key. Must be a string or number.
+ ---@param value any The value to be stored.
+ ---@param typeid string? The typeid of the value. Will be inferred if nil.
+ function E2Table:Set(key, value, typeid)
+ if not typeid then
+ typeid = e2t_infer_tp(value) or error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key)))
+ end
+
+ if key then
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ if not dest_type[key] then self.size = self.size + 1 end
+ dest[key] = value
+ dest_type[key] = typeid
+ end
+ end
+
+ ---Returns the typeid and value of the key, if it exists.
+ ---@param key string|number The key. Must be a string or number.
+ ---@return string? typeid The typeid of the key or nil if it doesn't exist.
+ ---@return any? value The value at the key if it exists.
+ function E2Table:Get(key)
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ return dest_type[key], dest[key]
+ end
+
+ ---Returns the typeid, value, source typeid table, source table
+ local function e2t_get_ext(self, key)
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ return dest_type[key], dest[key], dest_type, dest
+ end
+
+ ---Returns the typeid and value of the key and removes it from the table.
+ ---This will not shift elements down the sequential part of the array.
+ ---@param key string|number The key. Must be a string or number.
+ ---@return string? typeid The typeid of the key or nil if it doesn't exist.
+ ---@return any? value The value at the key if it exists.
+ function E2Table:Unset(key)
+ local typeid, value, dest_type, dest = e2t_get_ext(self, key)
+
+ if typeid then
+ dest[key] = nil
+ dest_type[key] = nil
+ self.size = self.size - 1
+ end
+ return typeid, value
+ end
+
+ ---Returns the typeid and value of the key and removes it from the table.
+ ---This *will* shift elements down the sequential part of the array.
+ ---@param key string|number The key. Must be a string or number.
+ ---@return string? typeid The typeid of the key or nil if it doesn't exist.
+ ---@return any? value The value at the key if it exists.
+ function E2Table:Remove(key)
+ local typeid, value, dest_type, dest = e2t_get_ext(self, key)
+
+ if typeid then
+ if isnumber(key) and table.remove(dest_type, key --[[@as number]]) then
+ -- table.remove will return nil if it fails, meaning we need to unset
+ ---@cast key number
+ table.remove(dest, key)
+ else
+ dest[key] = nil
+ dest_type[key] = nil
+ end
+ self.size = self.size - 1
+ end
+ return typeid, value
+ end
+
+ --- Returns an `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
+ --- Otherwise, returns an empty E2Table.
+ ---@param data { [number|string]:any }? The data to store in the E2Table.
+ ---@param typeids { [number|string]:any }? Optional typeids. Does not need to include every typeid. Useful for table-based types.
+ ---@return E2Table
+ newE2Table = function(data, typeids)
+ ---@cast E2Table -function
+ if data then
+ local n, ntypes, s, stypes, size = {}, {}, {}, {}, 0
+ for key, value in pairs(data) do
+ local dest, dest_types
+ if isnumber(key) then
+ dest = n
+ dest_types = ntypes
+ elseif isstring(key) then
+ dest = s
+ dest_types = stypes
+ else
+ error(string.format("Tried to create E2 table with invalid key type: %s, type: %s", tostring(key), type(key)))
+ end
+ local tp = typeids and typeids[key] or e2t_infer_tp(value)
+ if not tp then error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key))) end
+ dest[key] = value
+ dest_types[key] = tp
+ size = size + 1
+ end
+ return setmetatable({ n = n, ntypes = ntypes, s = s, stypes = stypes, size = size }, E2Table)
+ else
+ return setmetatable({ n = {}, ntypes = {}, s = {}, stypes = {}, size = 0 }, E2Table)
+ end
+ end
+ E2Table.New = newE2Table
+
+ function E2Table:__call(data, typeids)
+ return newE2Table(data, typeids)
+ end
+
+ WireLib.E2Table = E2Table
+end
+
--- Array of data types for Wiremod.
---@type table
WireLib.DT = {
@@ -154,7 +320,7 @@ WireLib.DT = {
},
TABLE = {
Zero = function()
- return { n = {}, ntypes = {}, s = {}, stypes = {}, size = 0 }
+ return newE2Table()
end,
Validator = function(t)
return istable(t)
From 3129aeb352e83980e2b9844bcfe63b8b38fa39b5 Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Mon, 1 Sep 2025 22:28:39 -0400
Subject: [PATCH 07/10] Fix compat in damage detector
---
lua/entities/gmod_wire_damage_detector.lua | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/lua/entities/gmod_wire_damage_detector.lua b/lua/entities/gmod_wire_damage_detector.lua
index dbfe11abfd..aa243886c3 100644
--- a/lua/entities/gmod_wire_damage_detector.lua
+++ b/lua/entities/gmod_wire_damage_detector.lua
@@ -6,7 +6,7 @@ ENT.WireDebugName = "Damage Detector"
if CLIENT then return end -- No more client
-local DEFAULT = {n={},ntypes={},s={},stypes={},size=0}
+local newE2Table = WireLib.E2Table.New
-- Global table to keep track of all detectors
local Wire_Damage_Detectors = {}
@@ -67,7 +67,7 @@ function ENT:Initialize()
self.key_ents = {}
-- Store output damage info
- self.victims = table.Copy(DEFAULT)
+ self.victims = newE2Table()
WireLib.TriggerOutput( self, "Victims", self.victims )
self.damage = 0
@@ -178,7 +178,7 @@ function ENT:TriggerInput( iname, value )
if value then
self.count = 0
self.firsthit_dmginfo = {}
- self.victims = table.Copy(DEFAULT)
+ self.victims = newE2Table()
self.damage = 0
self:TriggerOutput()
end
@@ -193,7 +193,7 @@ function ENT:TriggerOutput() -- Entity outputs won't trigger again until they ch
WireLib.TriggerOutput( self, "Victim", IsValid(victim) and victim or NULL)
self.victims.size = table.Count(self.victims.s)
- WireLib.TriggerOutput( self, "Victims", self.victims or table.Copy(DEFAULT) )
+ WireLib.TriggerOutput( self, "Victims", self.victims or newE2Table() )
WireLib.TriggerOutput( self, "Position", self.firsthit_dmginfo[3] or Vector(0,0,0) )
WireLib.TriggerOutput( self, "Force", self.firsthit_dmginfo[4] or Vector(0,0,0) )
WireLib.TriggerOutput( self, "Type", self.firsthit_dmginfo[5] or "" )
@@ -256,6 +256,8 @@ local damageTypes = {
function ENT:UpdateDamage( dmginfo, ent ) -- Update damage table
local damage = dmginfo:GetDamage()
+ local victims = self.victims
+
if not self.hit then -- Only register the first target's damage info
self.firsthit_dmginfo = {
dmginfo:GetAttacker(),
@@ -268,8 +270,8 @@ function ENT:UpdateDamage( dmginfo, ent ) -- Update damage table
self.dmgtype = damageTypes[dmginfo:GetDamageType()] or "Other"
-
- self.victims = table.Copy(DEFAULT)
+ victims = newE2Table()
+ self.victims = victims
self.firsthit_dmginfo[5] = self.dmgtype
self.hit = true
@@ -286,8 +288,8 @@ function ENT:UpdateDamage( dmginfo, ent ) -- Update damage table
-- Update victims table (ent, damage)
local entID = tostring(ent:EntIndex())
- self.victims.s[entID] = ( self.victims[entID] or 0 ) + damage
- self.victims.stypes[entID] = "n"
+ local old_dmg = select(2, victims:Get(entID)) or 0
+ victims:Set(entID, old_dmg + damage)
self.count = self.count + 1
if self.count == math.huge then self.count = 0 end -- This shouldn't ever happen... unless you're really REALLY bored
From 4070645039d2334fb198cd7b4d57db230bdc6b47 Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Tue, 2 Sep 2025 16:16:17 -0400
Subject: [PATCH 08/10] Fix bad ref and clientside errors
---
.../core/custom/prop.lua | 2 +-
.../gmod_wire_expression2/core/table.lua | 2 +-
lua/wire/wireshared.lua | 165 ++++++++++++++++++
3 files changed, 167 insertions(+), 2 deletions(-)
diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua
index 3a2a3fc017..c0a8deb6b6 100644
--- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua
+++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua
@@ -21,7 +21,7 @@ local setAng = WireLib.setAng
local typeIDToString = WireLib.typeIDToString
local castE2ValueToLuaValue = E2Lib.castE2ValueToLuaValue
-local newE2Table = E2Lib.E2Table.New
+local newE2Table = WireLib.E2Table.New
local E2totalspawnedprops = 0
local playerMeta = FindMetaTable("Player")
diff --git a/lua/entities/gmod_wire_expression2/core/table.lua b/lua/entities/gmod_wire_expression2/core/table.lua
index 19f244e4bf..fa3186f5a7 100644
--- a/lua/entities/gmod_wire_expression2/core/table.lua
+++ b/lua/entities/gmod_wire_expression2/core/table.lua
@@ -8,7 +8,7 @@ local tostring = tostring
local table = table
local type = type
-local newE2Table = E2Lib.E2Table.New
+local newE2Table = WireLib.E2Table.New
local opcost = 1/3 -- cost of looping through table multiplier
diff --git a/lua/wire/wireshared.lua b/lua/wire/wireshared.lua
index 69eb47b78b..b5d795897e 100644
--- a/lua/wire/wireshared.lua
+++ b/lua/wire/wireshared.lua
@@ -1366,3 +1366,168 @@ local typeIDToStringTable = {
function WireLib.typeIDToString(typeID)
return typeIDToStringTable[typeID] or "unregistered type"
end
+
+do
+ --- A wrapper for Lua tables for use in E2.
+ --- When called as a function, will create a new `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
+ --- Otherwise, returns an empty E2Table.
+ --- The `typeids` argument is optional. It will be used for typeids instead of type inferral. Useful for table-based types.
+ ---@class E2Table
+ ---@field n table A table containing only numeric keys
+ ---@field ntypes table A table with typeids corresponding to numeric keys
+ ---@field s table A table containing only string keys
+ ---@field stypes table A table with typeids corresponding to string keys
+ ---@field size number The size of the table. This is equivalent to `table.Count(self.n) + table.Count(self.s)`
+ ---@overload fun(data:{ [string|number]:any }?, typeids:{ [string|number]:any }?):E2Table
+ local E2Table = {}
+ E2Table.__index = E2Table
+
+ local e2t_tp_lut = {
+ [TYPE_NUMBER] = "n",
+ [TYPE_STRING] = "s",
+ [TYPE_ENTITY] = "e",
+ [TYPE_VECTOR] = "v",
+ [TYPE_ANGLE] = "a",
+ [TYPE_PHYSOBJ] = "b"
+ }
+ ---Does a simple attempt at inferring the type of an object.
+ local function e2t_infer_tp(v)
+ local tp = TypeID(v)
+ local easy_tp = e2t_tp_lut[tp]
+ if easy_tp then return easy_tp end
+ if istable(v) then
+ local mt = getmetatable(v)
+ if mt then
+ if mt == E2Table then
+ return "t"
+ elseif E2Lib and mt == E2Lib.Function then
+ return "f"
+ end
+ end
+ end
+ end
+
+ ---Sets the key to the value and assigns it the typeid. Special types will require `typeid` to be set.
+ ---@param key string|number The key. Must be a string or number.
+ ---@param value any The value to be stored.
+ ---@param typeid string? The typeid of the value. Will be inferred if nil.
+ function E2Table:Set(key, value, typeid)
+ if not typeid then
+ typeid = e2t_infer_tp(value) or error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key)))
+ end
+
+ if key then
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ if not dest_type[key] then self.size = self.size + 1 end
+ dest[key] = value
+ dest_type[key] = typeid
+ end
+ end
+
+ ---Returns the typeid and value of the key, if it exists.
+ ---@param key string|number The key. Must be a string or number.
+ ---@return string? typeid The typeid of the key or nil if it doesn't exist.
+ ---@return any? value The value at the key if it exists.
+ function E2Table:Get(key)
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ return dest_type[key], dest[key]
+ end
+
+ ---Returns the typeid, value, source typeid table, source table
+ local function e2t_get_ext(self, key)
+ local dest, dest_type
+ if isnumber(key) then
+ dest, dest_type = self.n, self.ntypes
+ else
+ dest, dest_type = self.s, self.stypes
+ end
+ return dest_type[key], dest[key], dest_type, dest
+ end
+
+ ---Returns the typeid and value of the key and removes it from the table.
+ ---This will not shift elements down the sequential part of the array.
+ ---@param key string|number The key. Must be a string or number.
+ ---@return string? typeid The typeid of the key or nil if it doesn't exist.
+ ---@return any? value The value at the key if it exists.
+ function E2Table:Unset(key)
+ local typeid, value, dest_type, dest = e2t_get_ext(self, key)
+
+ if typeid then
+ dest[key] = nil
+ dest_type[key] = nil
+ self.size = self.size - 1
+ end
+ return typeid, value
+ end
+
+ ---Returns the typeid and value of the key and removes it from the table.
+ ---This *will* shift elements down the sequential part of the array.
+ ---@param key string|number The key. Must be a string or number.
+ ---@return string? typeid The typeid of the key or nil if it doesn't exist.
+ ---@return any? value The value at the key if it exists.
+ function E2Table:Remove(key)
+ local typeid, value, dest_type, dest = e2t_get_ext(self, key)
+
+ if typeid then
+ if isnumber(key) and table.remove(dest_type, key --[[@as number]]) then
+ -- table.remove will return nil if it fails, meaning we need to unset
+ ---@cast key number
+ table.remove(dest, key)
+ else
+ dest[key] = nil
+ dest_type[key] = nil
+ end
+ self.size = self.size - 1
+ end
+ return typeid, value
+ end
+
+ --- Returns an `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
+ --- Otherwise, returns an empty E2Table.
+ ---@param data { [number|string]:any }? The data to store in the E2Table.
+ ---@param typeids { [number|string]:any }? Optional typeids. Does not need to include every typeid. Useful for table-based types.
+ ---@return E2Table
+ local newE2Table = function(data, typeids)
+ ---@cast E2Table -function
+ if data then
+ local n, ntypes, s, stypes, size = {}, {}, {}, {}, 0
+ for key, value in pairs(data) do
+ local dest, dest_types
+ if isnumber(key) then
+ dest = n
+ dest_types = ntypes
+ elseif isstring(key) then
+ dest = s
+ dest_types = stypes
+ else
+ error(string.format("Tried to create E2 table with invalid key type: %s, type: %s", tostring(key), type(key)))
+ end
+ local tp = typeids and typeids[key] or e2t_infer_tp(value)
+ if not tp then error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key))) end
+ dest[key] = value
+ dest_types[key] = tp
+ size = size + 1
+ end
+ return setmetatable({ n = n, ntypes = ntypes, s = s, stypes = stypes, size = size }, E2Table)
+ else
+ return setmetatable({ n = {}, ntypes = {}, s = {}, stypes = {}, size = 0 }, E2Table)
+ end
+ end
+ E2Table.New = newE2Table
+
+ function E2Table:__call(data, typeids)
+ return newE2Table(data, typeids)
+ end
+
+ WireLib.E2Table = E2Table
+end
\ No newline at end of file
From 9cc04d745cc453d1659f1088b226c852bb9d05e2 Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Fri, 12 Sep 2025 09:26:42 -0400
Subject: [PATCH 09/10] Remove duplicated code
---
lua/wire/server/wirelib.lua | 166 +-----------------------------------
1 file changed, 1 insertion(+), 165 deletions(-)
diff --git a/lua/wire/server/wirelib.lua b/lua/wire/server/wirelib.lua
index 63eb16cc61..32cf5bd3f3 100644
--- a/lua/wire/server/wirelib.lua
+++ b/lua/wire/server/wirelib.lua
@@ -95,171 +95,7 @@ function WireLib.TriggerInput(ent, name, value, ...)
end
end
-local newE2Table
-do
- --- A wrapper for Lua tables for use in E2.
- --- When called as a function, will create a new `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
- --- Otherwise, returns an empty E2Table.
- --- The `typeids` argument is optional. It will be used for typeids instead of type inferral. Useful for table-based types.
- ---@class E2Table
- ---@field n table A table containing only numeric keys
- ---@field ntypes table A table with typeids corresponding to numeric keys
- ---@field s table A table containing only string keys
- ---@field stypes table A table with typeids corresponding to string keys
- ---@field size number The size of the table. This is equivalent to `table.Count(self.n) + table.Count(self.s)`
- ---@overload fun(data:{ [string|number]:any }?, typeids:{ [string|number]:any }?):E2Table
- local E2Table = {}
- E2Table.__index = E2Table
-
- local e2t_tp_lut = {
- [TYPE_NUMBER] = "n",
- [TYPE_STRING] = "s",
- [TYPE_ENTITY] = "e",
- [TYPE_VECTOR] = "v",
- [TYPE_ANGLE] = "a",
- [TYPE_PHYSOBJ] = "b"
- }
- ---Does a simple attempt at inferring the type of an object.
- local function e2t_infer_tp(v)
- local tp = TypeID(v)
- local easy_tp = e2t_tp_lut[tp]
- if easy_tp then return easy_tp end
- if istable(v) then
- local mt = getmetatable(v)
- if mt then
- if mt == E2Table then
- return "t"
- elseif E2Lib and mt == E2Lib.Function then
- return "f"
- end
- end
- end
- end
-
- ---Sets the key to the value and assigns it the typeid. Special types will require `typeid` to be set.
- ---@param key string|number The key. Must be a string or number.
- ---@param value any The value to be stored.
- ---@param typeid string? The typeid of the value. Will be inferred if nil.
- function E2Table:Set(key, value, typeid)
- if not typeid then
- typeid = e2t_infer_tp(value) or error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key)))
- end
-
- if key then
- local dest, dest_type
- if isnumber(key) then
- dest, dest_type = self.n, self.ntypes
- else
- dest, dest_type = self.s, self.stypes
- end
- if not dest_type[key] then self.size = self.size + 1 end
- dest[key] = value
- dest_type[key] = typeid
- end
- end
-
- ---Returns the typeid and value of the key, if it exists.
- ---@param key string|number The key. Must be a string or number.
- ---@return string? typeid The typeid of the key or nil if it doesn't exist.
- ---@return any? value The value at the key if it exists.
- function E2Table:Get(key)
- local dest, dest_type
- if isnumber(key) then
- dest, dest_type = self.n, self.ntypes
- else
- dest, dest_type = self.s, self.stypes
- end
- return dest_type[key], dest[key]
- end
-
- ---Returns the typeid, value, source typeid table, source table
- local function e2t_get_ext(self, key)
- local dest, dest_type
- if isnumber(key) then
- dest, dest_type = self.n, self.ntypes
- else
- dest, dest_type = self.s, self.stypes
- end
- return dest_type[key], dest[key], dest_type, dest
- end
-
- ---Returns the typeid and value of the key and removes it from the table.
- ---This will not shift elements down the sequential part of the array.
- ---@param key string|number The key. Must be a string or number.
- ---@return string? typeid The typeid of the key or nil if it doesn't exist.
- ---@return any? value The value at the key if it exists.
- function E2Table:Unset(key)
- local typeid, value, dest_type, dest = e2t_get_ext(self, key)
-
- if typeid then
- dest[key] = nil
- dest_type[key] = nil
- self.size = self.size - 1
- end
- return typeid, value
- end
-
- ---Returns the typeid and value of the key and removes it from the table.
- ---This *will* shift elements down the sequential part of the array.
- ---@param key string|number The key. Must be a string or number.
- ---@return string? typeid The typeid of the key or nil if it doesn't exist.
- ---@return any? value The value at the key if it exists.
- function E2Table:Remove(key)
- local typeid, value, dest_type, dest = e2t_get_ext(self, key)
-
- if typeid then
- if isnumber(key) and table.remove(dest_type, key --[[@as number]]) then
- -- table.remove will return nil if it fails, meaning we need to unset
- ---@cast key number
- table.remove(dest, key)
- else
- dest[key] = nil
- dest_type[key] = nil
- end
- self.size = self.size - 1
- end
- return typeid, value
- end
-
- --- Returns an `E2Table` instance. If `data` is specified, then automatically initializes the E2Table with that data.
- --- Otherwise, returns an empty E2Table.
- ---@param data { [number|string]:any }? The data to store in the E2Table.
- ---@param typeids { [number|string]:any }? Optional typeids. Does not need to include every typeid. Useful for table-based types.
- ---@return E2Table
- newE2Table = function(data, typeids)
- ---@cast E2Table -function
- if data then
- local n, ntypes, s, stypes, size = {}, {}, {}, {}, 0
- for key, value in pairs(data) do
- local dest, dest_types
- if isnumber(key) then
- dest = n
- dest_types = ntypes
- elseif isstring(key) then
- dest = s
- dest_types = stypes
- else
- error(string.format("Tried to create E2 table with invalid key type: %s, type: %s", tostring(key), type(key)))
- end
- local tp = typeids and typeids[key] or e2t_infer_tp(value)
- if not tp then error(string.format("Unknown type for value [%s] at key [%s]", tostring(value), tostring(key))) end
- dest[key] = value
- dest_types[key] = tp
- size = size + 1
- end
- return setmetatable({ n = n, ntypes = ntypes, s = s, stypes = stypes, size = size }, E2Table)
- else
- return setmetatable({ n = {}, ntypes = {}, s = {}, stypes = {}, size = 0 }, E2Table)
- end
- end
- E2Table.New = newE2Table
-
- function E2Table:__call(data, typeids)
- return newE2Table(data, typeids)
- end
-
- WireLib.E2Table = E2Table
-end
+local newE2Table = WireLib.E2Table.New
--- Array of data types for Wiremod.
---@type table
From eaba08b1c654c1c88c44ca7471d10d5d4a20fb1a Mon Sep 17 00:00:00 2001
From: Denneisk <20892685+Denneisk@users.noreply.github.com>
Date: Fri, 12 Sep 2025 09:28:55 -0400
Subject: [PATCH 10/10] Remove unused size var
---
lua/entities/gmod_wire_expression2/core/custom/prop.lua | 1 -
1 file changed, 1 deletion(-)
diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua
index c0a8deb6b6..84c4eac71d 100644
--- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua
+++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua
@@ -513,7 +513,6 @@ e2function table sentGetData(string class)
local sent = list.Get("wire_spawnable_ents_registry")[class]
if not sent then self:throw("No class '"..class.."' found in sent registry", res) end
- local size = 0
for key, tbl in pairs( sent ) do
if key=="_preFactory" or key=="_postFactory" then continue end