From ca4347bed5f8c36b23d969bb5eaf867f7e5f9ce1 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Tue, 16 Jul 2024 16:16:41 -0500 Subject: [PATCH 01/14] Collision core & event for E2 --- .../gmod_wire_expression2/core/collision.lua | 190 ++++++++++++++++++ .../gmod_wire_expression2/core/extloader.lua | 1 + 2 files changed, 191 insertions(+) create mode 100644 lua/entities/gmod_wire_expression2/core/collision.lua diff --git a/lua/entities/gmod_wire_expression2/core/collision.lua b/lua/entities/gmod_wire_expression2/core/collision.lua new file mode 100644 index 0000000000..8039bb4ddb --- /dev/null +++ b/lua/entities/gmod_wire_expression2/core/collision.lua @@ -0,0 +1,190 @@ +-- Collision tracking for E2 +-- Author: DerelictDrone + +E2Lib.RegisterExtension( "collision", false, "Lets E2 chips mark entities to receive information when they collide with something." ) + +registerType("collision", "xcd", nil, + nil, + nil, + nil, + function(v) + return not istable(v) or not v.HitPos + end +) + +-- These are just the types we care about +-- Helps filter out physobjs cause that's not an e2 type +local typefilter = { + entity = "e", + vector = "v", + number = "n", +} + +local newE2Table = E2Lib.newE2Table + +e2function table collision:toTable() + local E2CD = newE2Table() + for k,v in pairs(this) do + local type = typefilter[string.lower(type(v))] + if type then + E2CD.s[k] = v + E2CD.stypes[k] = type + end + end + return E2CD +end + +-- Getter functions below, sorted by return type + +local function GetHitPos(self,collision) + if not this then return self:throw("Invalid collision data!") end + return collision.HitPos +end + +-- * Vectors + +e2function vector collision:hitpos() + return GetHitPos(self,this) +end + +e2function vector collision:pos() + return GetHitPos(self,this) +end + +e2function vector collision:position() + return GetHitPos(self,this) +end + +e2function vector collision:ouroldvelocity() + if not this then return self:throw("Invalid collision data!") end + return this.OurOldVelocity +end + +e2function vector collision:theiroldvelocity() + if not this then return self:throw("Invalid collision data!") end + return this.TheirOldVelocity +end + +e2function vector collision:hitnormal() + if not this then return self:throw("Invalid collision data!") end + return this.HitNormal +end + +e2function vector collision:hitspeed() + if not this then return self:throw("Invalid collision data!") end + return this.HitSpeed +end + +e2function vector collision:ournewvelocity() + if not this then return self:throw("Invalid collision data!") end + return this.OurNewVelocity +end + +e2function vector collision:theirnewvelocity() + if not this then return self:throw("Invalid collision data!") end + return this.TheirNewVelocity +end + +e2function vector collision:ouroldangularvelocity() + if not this then return self:throw("Invalid collision data!") end + return this.OurOldAngularVelocity +end + +e2function vector collision:theiroldangularvelocity() + if not this then return self:throw("Invalid collision data!") end + return this.TheirOldAngularVelocity +end + +-- * Numbers + +e2function number collision:speed() + if not this then return self:throw("Invalid collision data!") end + return this.Speed +end + +e2function number collision:oursurfaceprops() + if not this then return self:throw("Invalid collision data!") end + return this.OurSurfaceProps +end + +e2function number collision:theirsurfaceprops() + if not this then return self:throw("Invalid collision data!") end + return this.TheirSurfaceProps +end + +e2function number collision:deltatime() + if not this then return self:throw("Invalid collision data!") end + return this.DeltaTime +end + +-- * Entities + +e2function entity collision:hitentity() + if not this then return self:throw("Invalid collision data!") end + return this.HitEntity +end + + +__e2setcost( 20 ) + +e2function number trackCollision( entity ent ) + if IsValid(ent) then + local entIndex = ent:EntIndex() + if self.E2TrackedCollisions[entIndex] then + return 0 -- Already being tracked. + end + local chip = self.entity + local callbackID = ent:AddCallback("PhysicsCollide", + function( us, cd ) + chip:ExecuteEvent("entityCollision",{us,cd.HitEntity,cd}) + end) + self.E2TrackedCollisions[entIndex] = callbackID -- This ID is needed to remove the physcollide callback + ent:CallOnRemove("E2Chip_CCB" .. callbackID, function() + self.E2TrackedCollisions[entIndex] = nil + end) + return 1 + end + return 0 +end + +__e2setcost( 5 ) + +e2function number isTrackingCollision( entity ent ) + if IsValid(ent) and self.E2TrackedCollisions[ent:EntIndex()] then + return 1 + else + return 0 + end +end + +e2function void stopTrackingCollision( entity ent ) + if IsValid(ent) then + local entIndex = ent:EntIndex() + if self.E2TrackedCollisions[entIndex] then + local callbackID = self.E2TrackedCollisions[entIndex] + ent:RemoveCallOnRemove("E2Chip_CCB" .. callbackID) + ent:RemoveCallback("PhysicsCollide", callbackID) + self.E2TrackedCollisions[entIndex] = nil + end + end +end + +registerCallback("construct", function( self ) + self.E2TrackedCollisions = {} +end) + +registerCallback("destruct", function( self ) + for k,v in pairs(self.E2TrackedCollisions) do + local ent = Entity(tonumber(k)) + if IsValid(ent) then + ent:RemoveCallOnRemove("E2Chip_CCB" .. v) + ent:RemoveCallback("PhysicsCollide", v) + end + end +end) + +E2Lib.registerEvent("entityCollision", { + {"Entity", "e"}, + {"HitEntity", "e"}, + {"CollisionData", "xcd"}, +}) diff --git a/lua/entities/gmod_wire_expression2/core/extloader.lua b/lua/entities/gmod_wire_expression2/core/extloader.lua index 7253f5183a..05fbf267a6 100644 --- a/lua/entities/gmod_wire_expression2/core/extloader.lua +++ b/lua/entities/gmod_wire_expression2/core/extloader.lua @@ -171,6 +171,7 @@ e2_include("easings.lua") e2_include("damage.lua") e2_include("remote.lua") e2_include("egpobjects.lua") +e2_include("collision.lua") -- Load serverside files here, they need additional parsing do From efff7169b15dea66a4e328b23b79c4cb231c0cb6 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Tue, 16 Jul 2024 17:28:13 -0500 Subject: [PATCH 02/14] Clear trailing whitespace in collision.lua --- lua/entities/gmod_wire_expression2/core/collision.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/entities/gmod_wire_expression2/core/collision.lua b/lua/entities/gmod_wire_expression2/core/collision.lua index 8039bb4ddb..242e15b870 100644 --- a/lua/entities/gmod_wire_expression2/core/collision.lua +++ b/lua/entities/gmod_wire_expression2/core/collision.lua @@ -158,7 +158,7 @@ e2function number isTrackingCollision( entity ent ) end e2function void stopTrackingCollision( entity ent ) - if IsValid(ent) then + if IsValid(ent) then local entIndex = ent:EntIndex() if self.E2TrackedCollisions[entIndex] then local callbackID = self.E2TrackedCollisions[entIndex] From 907941162a58452b6a495ecaf647a2e6ea621042 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Wed, 17 Jul 2024 07:07:36 -0500 Subject: [PATCH 03/14] Errors in strict mode for tracking --- .../gmod_wire_expression2/core/collision.lua | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/collision.lua b/lua/entities/gmod_wire_expression2/core/collision.lua index 242e15b870..51f49df290 100644 --- a/lua/entities/gmod_wire_expression2/core/collision.lua +++ b/lua/entities/gmod_wire_expression2/core/collision.lua @@ -56,71 +56,71 @@ e2function vector collision:position() end e2function vector collision:ouroldvelocity() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.OurOldVelocity end e2function vector collision:theiroldvelocity() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.TheirOldVelocity end e2function vector collision:hitnormal() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.HitNormal end e2function vector collision:hitspeed() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.HitSpeed end e2function vector collision:ournewvelocity() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.OurNewVelocity end e2function vector collision:theirnewvelocity() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.TheirNewVelocity end e2function vector collision:ouroldangularvelocity() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.OurOldAngularVelocity end e2function vector collision:theiroldangularvelocity() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.TheirOldAngularVelocity end -- * Numbers e2function number collision:speed() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",0) end return this.Speed end e2function number collision:oursurfaceprops() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",0) end return this.OurSurfaceProps end e2function number collision:theirsurfaceprops() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",0) end return this.TheirSurfaceProps end e2function number collision:deltatime() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",0) end return this.DeltaTime end -- * Entities e2function entity collision:hitentity() - if not this then return self:throw("Invalid collision data!") end + if not this then return self:throw("Invalid collision data!",Entity(0)) end return this.HitEntity end @@ -131,7 +131,7 @@ e2function number trackCollision( entity ent ) if IsValid(ent) then local entIndex = ent:EntIndex() if self.E2TrackedCollisions[entIndex] then - return 0 -- Already being tracked. + return self:throw("Attempting to track collisions for an already tracked entity",0) -- Already being tracked. end local chip = self.entity local callbackID = ent:AddCallback("PhysicsCollide", @@ -144,13 +144,16 @@ e2function number trackCollision( entity ent ) end) return 1 end - return 0 + return self:throw("Attempting to track collisions for an invalid entity",0) end __e2setcost( 5 ) e2function number isTrackingCollision( entity ent ) - if IsValid(ent) and self.E2TrackedCollisions[ent:EntIndex()] then + if not IsValid(ent) then + return self:throw("Attempting to check tracking of collisions for an invalid entity",0) + end + if self.E2TrackedCollisions[ent:EntIndex()] then return 1 else return 0 @@ -159,13 +162,17 @@ end e2function void stopTrackingCollision( entity ent ) if IsValid(ent) then - local entIndex = ent:EntIndex() + local entIndex = ent:EntIndex() if self.E2TrackedCollisions[entIndex] then local callbackID = self.E2TrackedCollisions[entIndex] ent:RemoveCallOnRemove("E2Chip_CCB" .. callbackID) ent:RemoveCallback("PhysicsCollide", callbackID) self.E2TrackedCollisions[entIndex] = nil + else + return self:throw("Attempting to stop tracking collisions for an untracked entity",nil) end + else + return self:throw("Attempting to stop tracking collisions for an invalid entity",nil) end end From 1756ed17145b8bcb99254f3a5eb117bbc242c583 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Wed, 17 Jul 2024 07:11:12 -0500 Subject: [PATCH 04/14] Aliases for our/their getters as entity/hitentity --- .../gmod_wire_expression2/core/collision.lua | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lua/entities/gmod_wire_expression2/core/collision.lua b/lua/entities/gmod_wire_expression2/core/collision.lua index 51f49df290..676c65ecca 100644 --- a/lua/entities/gmod_wire_expression2/core/collision.lua +++ b/lua/entities/gmod_wire_expression2/core/collision.lua @@ -60,11 +60,21 @@ e2function vector collision:ouroldvelocity() return this.OurOldVelocity end +e2function vector collision:entityoldvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurOldVelocity +end + e2function vector collision:theiroldvelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.TheirOldVelocity end +e2function vector collision:hitentityoldvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirOldVelocity +end + e2function vector collision:hitnormal() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.HitNormal @@ -80,21 +90,41 @@ e2function vector collision:ournewvelocity() return this.OurNewVelocity end +e2function vector collision:entitynewvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurNewVelocity +end + e2function vector collision:theirnewvelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.TheirNewVelocity end +e2function vector collision:hitentitynewvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirNewVelocity +end + e2function vector collision:ouroldangularvelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.OurOldAngularVelocity end +e2function vector collision:entityoldangularvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurOldAngularVelocity +end + e2function vector collision:theiroldangularvelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end return this.TheirOldAngularVelocity end +e2function vector collision:hitentityoldangularvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirOldAngularVelocity +end + -- * Numbers e2function number collision:speed() @@ -107,11 +137,21 @@ e2function number collision:oursurfaceprops() return this.OurSurfaceProps end +e2function number collision:entitysurfaceprops() + if not this then return self:throw("Invalid collision data!",0) end + return this.OurSurfaceProps +end + e2function number collision:theirsurfaceprops() if not this then return self:throw("Invalid collision data!",0) end return this.TheirSurfaceProps end +e2function number collision:hitentitysurfaceprops() + if not this then return self:throw("Invalid collision data!",0) end + return this.TheirSurfaceProps +end + e2function number collision:deltatime() if not this then return self:throw("Invalid collision data!",0) end return this.DeltaTime From 4e374cb5bee408ff9cc5d248f6f08544fa43b83e Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Wed, 17 Jul 2024 07:16:57 -0500 Subject: [PATCH 05/14] Migrate to propcore --- .../gmod_wire_expression2/core/collision.lua | 237 ------------------ .../core/custom/prop.lua | 235 +++++++++++++++++ 2 files changed, 235 insertions(+), 237 deletions(-) delete mode 100644 lua/entities/gmod_wire_expression2/core/collision.lua diff --git a/lua/entities/gmod_wire_expression2/core/collision.lua b/lua/entities/gmod_wire_expression2/core/collision.lua deleted file mode 100644 index 676c65ecca..0000000000 --- a/lua/entities/gmod_wire_expression2/core/collision.lua +++ /dev/null @@ -1,237 +0,0 @@ --- Collision tracking for E2 --- Author: DerelictDrone - -E2Lib.RegisterExtension( "collision", false, "Lets E2 chips mark entities to receive information when they collide with something." ) - -registerType("collision", "xcd", nil, - nil, - nil, - nil, - function(v) - return not istable(v) or not v.HitPos - end -) - --- These are just the types we care about --- Helps filter out physobjs cause that's not an e2 type -local typefilter = { - entity = "e", - vector = "v", - number = "n", -} - -local newE2Table = E2Lib.newE2Table - -e2function table collision:toTable() - local E2CD = newE2Table() - for k,v in pairs(this) do - local type = typefilter[string.lower(type(v))] - if type then - E2CD.s[k] = v - E2CD.stypes[k] = type - end - end - return E2CD -end - --- Getter functions below, sorted by return type - -local function GetHitPos(self,collision) - if not this then return self:throw("Invalid collision data!") end - return collision.HitPos -end - --- * Vectors - -e2function vector collision:hitpos() - return GetHitPos(self,this) -end - -e2function vector collision:pos() - return GetHitPos(self,this) -end - -e2function vector collision:position() - return GetHitPos(self,this) -end - -e2function vector collision:ouroldvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldVelocity -end - -e2function vector collision:entityoldvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldVelocity -end - -e2function vector collision:theiroldvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldVelocity -end - -e2function vector collision:hitentityoldvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldVelocity -end - -e2function vector collision:hitnormal() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.HitNormal -end - -e2function vector collision:hitspeed() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.HitSpeed -end - -e2function vector collision:ournewvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurNewVelocity -end - -e2function vector collision:entitynewvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurNewVelocity -end - -e2function vector collision:theirnewvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirNewVelocity -end - -e2function vector collision:hitentitynewvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirNewVelocity -end - -e2function vector collision:ouroldangularvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldAngularVelocity -end - -e2function vector collision:entityoldangularvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldAngularVelocity -end - -e2function vector collision:theiroldangularvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldAngularVelocity -end - -e2function vector collision:hitentityoldangularvelocity() - if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldAngularVelocity -end - --- * Numbers - -e2function number collision:speed() - if not this then return self:throw("Invalid collision data!",0) end - return this.Speed -end - -e2function number collision:oursurfaceprops() - if not this then return self:throw("Invalid collision data!",0) end - return this.OurSurfaceProps -end - -e2function number collision:entitysurfaceprops() - if not this then return self:throw("Invalid collision data!",0) end - return this.OurSurfaceProps -end - -e2function number collision:theirsurfaceprops() - if not this then return self:throw("Invalid collision data!",0) end - return this.TheirSurfaceProps -end - -e2function number collision:hitentitysurfaceprops() - if not this then return self:throw("Invalid collision data!",0) end - return this.TheirSurfaceProps -end - -e2function number collision:deltatime() - if not this then return self:throw("Invalid collision data!",0) end - return this.DeltaTime -end - --- * Entities - -e2function entity collision:hitentity() - if not this then return self:throw("Invalid collision data!",Entity(0)) end - return this.HitEntity -end - - -__e2setcost( 20 ) - -e2function number trackCollision( entity ent ) - if IsValid(ent) then - local entIndex = ent:EntIndex() - if self.E2TrackedCollisions[entIndex] then - return self:throw("Attempting to track collisions for an already tracked entity",0) -- Already being tracked. - end - local chip = self.entity - local callbackID = ent:AddCallback("PhysicsCollide", - function( us, cd ) - chip:ExecuteEvent("entityCollision",{us,cd.HitEntity,cd}) - end) - self.E2TrackedCollisions[entIndex] = callbackID -- This ID is needed to remove the physcollide callback - ent:CallOnRemove("E2Chip_CCB" .. callbackID, function() - self.E2TrackedCollisions[entIndex] = nil - end) - return 1 - end - return self:throw("Attempting to track collisions for an invalid entity",0) -end - -__e2setcost( 5 ) - -e2function number isTrackingCollision( entity ent ) - if not IsValid(ent) then - return self:throw("Attempting to check tracking of collisions for an invalid entity",0) - end - if self.E2TrackedCollisions[ent:EntIndex()] then - return 1 - else - return 0 - end -end - -e2function void stopTrackingCollision( entity ent ) - if IsValid(ent) then - local entIndex = ent:EntIndex() - if self.E2TrackedCollisions[entIndex] then - local callbackID = self.E2TrackedCollisions[entIndex] - ent:RemoveCallOnRemove("E2Chip_CCB" .. callbackID) - ent:RemoveCallback("PhysicsCollide", callbackID) - self.E2TrackedCollisions[entIndex] = nil - else - return self:throw("Attempting to stop tracking collisions for an untracked entity",nil) - end - else - return self:throw("Attempting to stop tracking collisions for an invalid entity",nil) - end -end - -registerCallback("construct", function( self ) - self.E2TrackedCollisions = {} -end) - -registerCallback("destruct", function( self ) - for k,v in pairs(self.E2TrackedCollisions) do - local ent = Entity(tonumber(k)) - if IsValid(ent) then - ent:RemoveCallOnRemove("E2Chip_CCB" .. v) - ent:RemoveCallback("PhysicsCollide", v) - end - end -end) - -E2Lib.registerEvent("entityCollision", { - {"Entity", "e"}, - {"HitEntity", "e"}, - {"CollisionData", "xcd"}, -}) diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua index e60a7b2061..f4039c1e5c 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua @@ -1277,3 +1277,238 @@ registerCallback("destruct", end end ) + +-- * Collision tracking + +registerType("collision", "xcd", nil, + nil, + nil, + nil, + function(v) + return not istable(v) or not v.HitPos + end +) + +-- These are just the types we care about +-- Helps filter out physobjs cause that's not an e2 type +local typefilter = { + entity = "e", + vector = "v", + number = "n", +} + +local newE2Table = E2Lib.newE2Table + +e2function table collision:toTable() + local E2CD = newE2Table() + for k,v in pairs(this) do + local type = typefilter[string.lower(type(v))] + if type then + E2CD.s[k] = v + E2CD.stypes[k] = type + end + end + return E2CD +end + +-- Getter functions below, sorted by return type + +local function GetHitPos(self,collision) + if not this then return self:throw("Invalid collision data!") end + return collision.HitPos +end + +-- * Vectors + +e2function vector collision:hitpos() + return GetHitPos(self,this) +end + +e2function vector collision:pos() + return GetHitPos(self,this) +end + +e2function vector collision:position() + return GetHitPos(self,this) +end + +e2function vector collision:ouroldvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurOldVelocity +end + +e2function vector collision:entityoldvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurOldVelocity +end + +e2function vector collision:theiroldvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirOldVelocity +end + +e2function vector collision:hitentityoldvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirOldVelocity +end + +e2function vector collision:hitnormal() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.HitNormal +end + +e2function vector collision:hitspeed() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.HitSpeed +end + +e2function vector collision:ournewvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurNewVelocity +end + +e2function vector collision:entitynewvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurNewVelocity +end + +e2function vector collision:theirnewvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirNewVelocity +end + +e2function vector collision:hitentitynewvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirNewVelocity +end + +e2function vector collision:ouroldangularvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurOldAngularVelocity +end + +e2function vector collision:entityoldangularvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.OurOldAngularVelocity +end + +e2function vector collision:theiroldangularvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirOldAngularVelocity +end + +e2function vector collision:hitentityoldangularvelocity() + if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end + return this.TheirOldAngularVelocity +end + +-- * Numbers + +e2function number collision:speed() + if not this then return self:throw("Invalid collision data!",0) end + return this.Speed +end + +e2function number collision:oursurfaceprops() + if not this then return self:throw("Invalid collision data!",0) end + return this.OurSurfaceProps +end + +e2function number collision:entitysurfaceprops() + if not this then return self:throw("Invalid collision data!",0) end + return this.OurSurfaceProps +end + +e2function number collision:theirsurfaceprops() + if not this then return self:throw("Invalid collision data!",0) end + return this.TheirSurfaceProps +end + +e2function number collision:hitentitysurfaceprops() + if not this then return self:throw("Invalid collision data!",0) end + return this.TheirSurfaceProps +end + +e2function number collision:deltatime() + if not this then return self:throw("Invalid collision data!",0) end + return this.DeltaTime +end + +-- * Entities + +e2function entity collision:hitentity() + if not this then return self:throw("Invalid collision data!",Entity(0)) end + return this.HitEntity +end + + +__e2setcost( 20 ) + +e2function number trackCollision( entity ent ) + if IsValid(ent) then + local entIndex = ent:EntIndex() + if self.data.E2TrackedCollisions[entIndex] then + return self:throw("Attempting to track collisions for an already tracked entity",0) -- Already being tracked. + end + local chip = self.entity + local callbackID = ent:AddCallback("PhysicsCollide", + function( us, cd ) + chip:ExecuteEvent("entityCollision",{us,cd.HitEntity,cd}) + end) + self.data.E2TrackedCollisions[entIndex] = callbackID -- This ID is needed to remove the physcollide callback + ent:CallOnRemove("E2Chip_CCB" .. callbackID, function() + self.data.E2TrackedCollisions[entIndex] = nil + end) + return 1 + end + return self:throw("Attempting to track collisions for an invalid entity",0) +end + +__e2setcost( 5 ) + +e2function number isTrackingCollision( entity ent ) + if not IsValid(ent) then + return self:throw("Attempting to check tracking of collisions for an invalid entity",0) + end + if self.data.E2TrackedCollisions[ent:EntIndex()] then + return 1 + else + return 0 + end +end + +e2function void stopTrackingCollision( entity ent ) + if IsValid(ent) then + local entIndex = ent:EntIndex() + if self.data.E2TrackedCollisions[entIndex] then + local callbackID = self.data.E2TrackedCollisions[entIndex] + ent:RemoveCallOnRemove("E2Chip_CCB" .. callbackID) + ent:RemoveCallback("PhysicsCollide", callbackID) + self.data.E2TrackedCollisions[entIndex] = nil + else + return self:throw("Attempting to stop tracking collisions for an untracked entity",nil) + end + else + return self:throw("Attempting to stop tracking collisions for an invalid entity",nil) + end +end + +registerCallback("construct", function( self ) + self.data.E2TrackedCollisions = {} +end) + +registerCallback("destruct", function( self ) + for k,v in pairs(self.data.E2TrackedCollisions) do + local ent = Entity(tonumber(k)) + if IsValid(ent) then + ent:RemoveCallOnRemove("E2Chip_CCB" .. v) + ent:RemoveCallback("PhysicsCollide", v) + end + end +end) + +E2Lib.registerEvent("entityCollision", { + {"Entity", "e"}, + {"HitEntity", "e"}, + {"CollisionData", "xcd"}, +}) From 7688c423c89c3388f1a16dd8acda4fc3dc72ed54 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Wed, 17 Jul 2024 07:26:27 -0500 Subject: [PATCH 06/14] Forgot to remove collision.lua from extloader --- lua/entities/gmod_wire_expression2/core/extloader.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/entities/gmod_wire_expression2/core/extloader.lua b/lua/entities/gmod_wire_expression2/core/extloader.lua index 05fbf267a6..7253f5183a 100644 --- a/lua/entities/gmod_wire_expression2/core/extloader.lua +++ b/lua/entities/gmod_wire_expression2/core/extloader.lua @@ -171,7 +171,6 @@ e2_include("easings.lua") e2_include("damage.lua") e2_include("remote.lua") e2_include("egpobjects.lua") -e2_include("collision.lua") -- Load serverside files here, they need additional parsing do From c3ca9a10e796f10edc3b95a40d5668af6fa924bf Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Wed, 17 Jul 2024 14:55:11 -0500 Subject: [PATCH 07/14] Getter camelCasing & fixes. --- .../core/custom/prop.lua | 81 ++++++++++--------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua index f4039c1e5c..f2b7df9d97 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua @@ -1304,7 +1304,12 @@ e2function table collision:toTable() for k,v in pairs(this) do local type = typefilter[string.lower(type(v))] if type then - E2CD.s[k] = v + if type == "v" then + -- These need to be given copies, otherwise E2s modifications will propagate. + E2CD.s[k] = Vector(v) + else + E2CD.s[k] = v + end E2CD.stypes[k] = type end end @@ -1314,13 +1319,13 @@ end -- Getter functions below, sorted by return type local function GetHitPos(self,collision) - if not this then return self:throw("Invalid collision data!") end - return collision.HitPos + if not collision then return self:throw("Invalid collision data!") end + return Vector(collision.HitPos) end -- * Vectors -e2function vector collision:hitpos() +e2function vector collision:hitPos() return GetHitPos(self,this) end @@ -1332,74 +1337,74 @@ e2function vector collision:position() return GetHitPos(self,this) end -e2function vector collision:ouroldvelocity() +e2function vector collision:ourOldVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldVelocity + return Vector(this.OurOldVelocity) end -e2function vector collision:entityoldvelocity() +e2function vector collision:entityOldVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldVelocity + return Vector(this.OurOldVelocity) end -e2function vector collision:theiroldvelocity() +e2function vector collision:theirOldVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldVelocity + return Vector(this.TheirOldVelocity) end -e2function vector collision:hitentityoldvelocity() +e2function vector collision:hitEntityOldVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldVelocity + return Vector(this.TheirOldVelocity) end -e2function vector collision:hitnormal() +e2function vector collision:hitNormal() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.HitNormal + return Vector(this.HitNormal) end -e2function vector collision:hitspeed() +e2function vector collision:hitSpeed() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.HitSpeed + return Vector(this.HitSpeed) end -e2function vector collision:ournewvelocity() +e2function vector collision:ourNewVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurNewVelocity + return Vector(this.OurNewVelocity) end -e2function vector collision:entitynewvelocity() +e2function vector collision:entityNewVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurNewVelocity + return Vector(this.OurNewVelocity) end -e2function vector collision:theirnewvelocity() +e2function vector collision:theirNewVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirNewVelocity + return Vector(this.TheirNewVelocity) end -e2function vector collision:hitentitynewvelocity() +e2function vector collision:hitEntityNewVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirNewVelocity + return Vector(this.TheirNewVelocity) end -e2function vector collision:ouroldangularvelocity() +e2function vector collision:ourOldAngularVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldAngularVelocity + return Vector(this.OurOldAngularVelocity) end -e2function vector collision:entityoldangularvelocity() +e2function vector collision:entityOldAngularVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.OurOldAngularVelocity + return Vector(this.OurOldAngularVelocity) end -e2function vector collision:theiroldangularvelocity() +e2function vector collision:theirOldAngularVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldAngularVelocity + return Vector(this.TheirOldAngularVelocity) end -e2function vector collision:hitentityoldangularvelocity() +e2function vector collision:hitEntityOldAngularVelocity() if not this then return self:throw("Invalid collision data!",Vector(0,0,0)) end - return this.TheirOldAngularVelocity + return Vector(this.TheirOldAngularVelocity) end -- * Numbers @@ -1409,34 +1414,34 @@ e2function number collision:speed() return this.Speed end -e2function number collision:oursurfaceprops() +e2function number collision:ourSurfaceProps() if not this then return self:throw("Invalid collision data!",0) end return this.OurSurfaceProps end -e2function number collision:entitysurfaceprops() +e2function number collision:entitySurfaceProps() if not this then return self:throw("Invalid collision data!",0) end return this.OurSurfaceProps end -e2function number collision:theirsurfaceprops() +e2function number collision:theirSurfaceProps() if not this then return self:throw("Invalid collision data!",0) end return this.TheirSurfaceProps end -e2function number collision:hitentitysurfaceprops() +e2function number collision:hitEntitySurfaceProps() if not this then return self:throw("Invalid collision data!",0) end return this.TheirSurfaceProps end -e2function number collision:deltatime() +e2function number collision:deltaTime() if not this then return self:throw("Invalid collision data!",0) end return this.DeltaTime end -- * Entities -e2function entity collision:hitentity() +e2function entity collision:hitEntity() if not this then return self:throw("Invalid collision data!",Entity(0)) end return this.HitEntity end From e2b2c52d629ced695988d1399715d9ab921c9534 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Wed, 17 Jul 2024 15:05:48 -0500 Subject: [PATCH 08/14] E2helper documentation for collision & functions --- .../core/custom/cl_prop.lua | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua b/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua index 2e7e0767ce..88c6eb6704 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua @@ -89,4 +89,31 @@ E2Helper.Descriptions["setEyeTarget(e:v)"] = "For NPCs, sets the eye target to t E2Helper.Descriptions["setEyeTargetLocal(e:v)"] = "Sets the eye target to the local eye position" E2Helper.Descriptions["setEyeTargetWorld(e:v)"] = "Sets the eye target to the world position" E2Helper.Descriptions["setFlexScale(e:n)"] = "Sets the flex scale of the entity" -E2Helper.Descriptions["setFlexWeight"] = "Sets the weight of the flex" \ No newline at end of file +E2Helper.Descriptions["setFlexWeight"] = "Sets the weight of the flex" +E2Helper.Descriptions["trackCollision(e)"] = "Starts tracking collisions for the entity, will fire event entityCollision when they occur.\nDoes not track when entities hit world, only other entities.\nReturns 1 on success or 0 on error in non-strict" +E2Helper.Descriptions["isTrackingCollision(e)"] = "Returns 1 if the entity's collisions are already being tracked, 0 if not. Errors on an invalid ent" +E2Helper.Descriptions["stopTrackingCollision(e)"] = "Stops tracking collisions for the entity.\nError in strict if entity is invalid or entity isn't being tracked" +E2Helper.Descriptions["hitPos(xcd:)"] = "Returns a vector of where the collision ocurred" +E2Helper.Descriptions["pos(xcd:)"] = E2Helper.Descriptions["hitPos(xcd:)"] .. "\nAlias of hitPos(xcd:)" +E2Helper.Descriptions["position(xcd:)"] = E2Helper.Descriptions["pos(xcd:)"] +E2Helper.Descriptions["ourOldVelocity(xcd:)"] = "Returns a vector of the velocity of the tracked entity before the collision occurred." +E2Helper.Descriptions["entityOldVelocity(xcd:)"] = E2Helper.Descriptions["ourOldVelocity(xcd:)"] .. "\nAlias of ourOldVelocity(xcd:)" +E2Helper.Descriptions["theirOldVelocity(xcd:)"] = "Returns a vector of the velocity of the hit entity before the collision occurred" +E2Helper.Descriptions["hitEntityOldVelocity(xcd:)"] = E2Helper.Descriptions["theirOldVelocity(xcd:)"] .. "\nAlias of theirOldVelocity(xcd:)" +E2Helper.Descriptions["hitNormal(xcd:)"] = "Returns the hitnormal(vector) of the surface on the tracked entity that hit the other entity" +E2Helper.Descriptions["hitSpeed(xcd:)"] = "Returns a vector of the speed the impact occurred with" +E2Helper.Descriptions["ourNewVelocity(xcd:)"] = "Returns a vector of the velocity of the tracked entity after the collision occurred." +E2Helper.Descriptions["entityNewVelocity(xcd:)"] = E2Helper.Descriptions["ourNewVelocity(xcd:)"] .. "\nAlias of ourNewVelocity(xcd:)" +E2Helper.Descriptions["theirNewVelocity(xcd:)"] = "Returns a vector of the velocity of the hit entity after the collision occurred." +E2Helper.Descriptions["hitEntityNewVelocity(xcd:)"] = E2Helper.Descriptions["theirNewVelocity(xcd:)"] .. "\nAlias of theirNewVelocity(xcd:)" +E2Helper.Descriptions["ourOldAngularVelocity(xcd:)"] = "Returns a vector of the angular velocity of the tracked entity before the collision occurred." +E2Helper.Descriptions["entityOldAngularVelocity(xcd:)"] = E2Helper.Descriptions["ourOldAngularVelocity(xcd:)"] .. "\nAlias of ourOldAngularVelocity(xcd:)" +E2Helper.Descriptions["theirOldAngularVelocity(xcd:)"] = "Returns a vector of the angular velocity of the hit entity before the collision occurred." +E2Helper.Descriptions["hitEntityOldAngularVelocity(xcd:)"] = E2Helper.Descriptions["theirOldAngularVelocity(xcd:)"] .. "\nAlias of ourOldAngularVelocity(xcd:)" +E2Helper.Descriptions["speed(xcd:)"] = "Returns a number representing the speed at which the collision occurred." +E2Helper.Descriptions["ourSurfaceProps(xcd:)"] = "Returns a number representing the surface properties of the tracked entity" +E2Helper.Descriptions["entitySurfaceProps(xcd:)"] = E2Helper.Descriptions["ourSurfaceProps(xcd:)"] .. "\nAlias of ourSurfaceProps(xcd:)" +E2Helper.Descriptions["theirSurfaceProps(xcd:)"] = "Returns a number representing the surface properties of the hit entity" +E2Helper.Descriptions["hitEntitySurfaceProps(xcd:)"] = E2Helper.Descriptions["theirSurfaceProps(xcd:)"] .. "\nAlias of theirSurfaceProps(xcd:)" +E2Helper.Descriptions["deltaTime(xcd:)"] = "Returns a number representing how long ago the last collision between the tracked entity and the hit entity was, in seconds.\nCapped at 1 second." +E2Helper.Descriptions["hitEntity(xcd:)"] = "Returns the entity that was hit for this collision." \ No newline at end of file From 27d2f91f0d0b579c57f9c7253fd4c6767eec1c31 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Wed, 17 Jul 2024 15:07:39 -0500 Subject: [PATCH 09/14] Proper op costs --- lua/entities/gmod_wire_expression2/core/custom/prop.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua index f2b7df9d97..8d4a4ed5a1 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua @@ -1299,6 +1299,8 @@ local typefilter = { local newE2Table = E2Lib.newE2Table +__e2setcost(20) + e2function table collision:toTable() local E2CD = newE2Table() for k,v in pairs(this) do @@ -1318,6 +1320,8 @@ end -- Getter functions below, sorted by return type +__e2setcost(5) + local function GetHitPos(self,collision) if not collision then return self:throw("Invalid collision data!") end return Vector(collision.HitPos) @@ -1408,6 +1412,7 @@ e2function vector collision:hitEntityOldAngularVelocity() end -- * Numbers +__e2setcost(2) e2function number collision:speed() if not this then return self:throw("Invalid collision data!",0) end From 55ec3f80795615f9162ae9dc7f61cbff17d4ab58 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Thu, 18 Jul 2024 12:42:30 -0500 Subject: [PATCH 10/14] Collisions are now queued and flushed on think --- .../core/custom/prop.lua | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua index 8d4a4ed5a1..8eca665db2 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua @@ -1460,10 +1460,10 @@ e2function number trackCollision( entity ent ) if self.data.E2TrackedCollisions[entIndex] then return self:throw("Attempting to track collisions for an already tracked entity",0) -- Already being tracked. end - local chip = self.entity + local ctx = self local callbackID = ent:AddCallback("PhysicsCollide", function( us, cd ) - chip:ExecuteEvent("entityCollision",{us,cd.HitEntity,cd}) + table.insert(ctx.data.E2QueuedCollisions,{us=us,xcd=cd}) end) self.data.E2TrackedCollisions[entIndex] = callbackID -- This ID is needed to remove the physcollide callback ent:CallOnRemove("E2Chip_CCB" .. callbackID, function() @@ -1503,8 +1503,11 @@ e2function void stopTrackingCollision( entity ent ) end end +local registered_chips = {} + registerCallback("construct", function( self ) self.data.E2TrackedCollisions = {} + self.data.E2QueuedCollisions = {} end) registerCallback("destruct", function( self ) @@ -1517,8 +1520,37 @@ registerCallback("destruct", function( self ) end end) + + E2Lib.registerEvent("entityCollision", { {"Entity", "e"}, {"HitEntity", "e"}, {"CollisionData", "xcd"}, -}) +}, + function(ctx) -- Event constructor + registered_chips[ctx.entity] = ctx + end, + function(ctx) -- Event destructor + registered_chips[ctx.entity] = nil + end +) + +local function E2CollisionEventHandler() + for chip,ctx in pairs(registered_chips) do + if IsValid(chip) then + if not chip.error then + for _,i in ipairs(ctx.data.E2QueuedCollisions) do + chip:ExecuteEvent("entityCollision",{i.us,i.xcd.HitEntity,i.xcd}) + if chip.error then break end + end + end + -- Wipe queued collisions regardless of error + ctx.data.E2QueuedCollisions = {} + end + end +end + +hook.Add("Think", "Expression2CollisionClock", E2CollisionEventHandler) +timer.Create("Expression2CollisionClock", 5, 0, function() + hook.Add("Think", "Expression2CollisionClock", E2CollisionEventHandler) +end) \ No newline at end of file From da928be01b5147ea584ec67f11f2cbfba1dda4aa Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Thu, 18 Jul 2024 18:32:36 -0500 Subject: [PATCH 11/14] Collisions only check the tick after a collision --- .../core/custom/prop.lua | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua index 8eca665db2..461defc839 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua @@ -1454,6 +1454,25 @@ end __e2setcost( 20 ) +local processNextTick = false +local registered_chips = {} + +local function E2CollisionEventHandler() + for chip,ctx in pairs(registered_chips) do + if IsValid(chip) then + if not chip.error then + for _,i in ipairs(ctx.data.E2QueuedCollisions) do + chip:ExecuteEvent("entityCollision",{i.us,i.xcd.HitEntity,i.xcd}) + if chip.error then break end + end + end + -- Wipe queued collisions regardless of error + ctx.data.E2QueuedCollisions = {} + end + end + processNextTick = false +end + e2function number trackCollision( entity ent ) if IsValid(ent) then local entIndex = ent:EntIndex() @@ -1464,6 +1483,10 @@ e2function number trackCollision( entity ent ) local callbackID = ent:AddCallback("PhysicsCollide", function( us, cd ) table.insert(ctx.data.E2QueuedCollisions,{us=us,xcd=cd}) + if not processNextTick then + processNextTick = true + timer.Simple(0,E2CollisionEventHandler) -- A timer set to 0 runs next GM:Tick() hook + end end) self.data.E2TrackedCollisions[entIndex] = callbackID -- This ID is needed to remove the physcollide callback ent:CallOnRemove("E2Chip_CCB" .. callbackID, function() @@ -1503,8 +1526,6 @@ e2function void stopTrackingCollision( entity ent ) end end -local registered_chips = {} - registerCallback("construct", function( self ) self.data.E2TrackedCollisions = {} self.data.E2QueuedCollisions = {} @@ -1534,23 +1555,3 @@ E2Lib.registerEvent("entityCollision", { registered_chips[ctx.entity] = nil end ) - -local function E2CollisionEventHandler() - for chip,ctx in pairs(registered_chips) do - if IsValid(chip) then - if not chip.error then - for _,i in ipairs(ctx.data.E2QueuedCollisions) do - chip:ExecuteEvent("entityCollision",{i.us,i.xcd.HitEntity,i.xcd}) - if chip.error then break end - end - end - -- Wipe queued collisions regardless of error - ctx.data.E2QueuedCollisions = {} - end - end -end - -hook.Add("Think", "Expression2CollisionClock", E2CollisionEventHandler) -timer.Create("Expression2CollisionClock", 5, 0, function() - hook.Add("Think", "Expression2CollisionClock", E2CollisionEventHandler) -end) \ No newline at end of file From 8cd3841e1b3ab291cf9404148f0879b67f12f302 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Fri, 19 Jul 2024 19:53:51 -0500 Subject: [PATCH 12/14] Event requirements & callback overload --- .../core/custom/cl_prop.lua | 3 +- .../core/custom/prop.lua | 73 ++++++++++++++----- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua b/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua index 88c6eb6704..480847d786 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua @@ -90,7 +90,8 @@ E2Helper.Descriptions["setEyeTargetLocal(e:v)"] = "Sets the eye target to the lo E2Helper.Descriptions["setEyeTargetWorld(e:v)"] = "Sets the eye target to the world position" E2Helper.Descriptions["setFlexScale(e:n)"] = "Sets the flex scale of the entity" E2Helper.Descriptions["setFlexWeight"] = "Sets the weight of the flex" -E2Helper.Descriptions["trackCollision(e)"] = "Starts tracking collisions for the entity, will fire event entityCollision when they occur.\nDoes not track when entities hit world, only other entities.\nReturns 1 on success or 0 on error in non-strict" +E2Helper.Descriptions["trackCollision(e)"] = "Starts tracking collisions for the entity, will fire event entityCollision when they occur.\nDoes not track when players or vehicles hit world, only other entities.\nNeeds event entityCollision(entity, entity, collision) in order to run.\nReturns 1 on success or 0 on error in non-strict" +E2Helper.Descriptions["trackCollision(ef)"] = "Starts tracking collisions for the entity, will call the provided callback function, then fire event entityCollision when they occur.\nDoes not track when players or vehicles hit world, only other entities.\nMay track without event entityCollision\nPassed callback function needs argument signature of (eexcd), aka (entity, entity, collision)\nReturns 1 on success or 0 on error in non-strict." E2Helper.Descriptions["isTrackingCollision(e)"] = "Returns 1 if the entity's collisions are already being tracked, 0 if not. Errors on an invalid ent" E2Helper.Descriptions["stopTrackingCollision(e)"] = "Stops tracking collisions for the entity.\nError in strict if entity is invalid or entity isn't being tracked" E2Helper.Descriptions["hitPos(xcd:)"] = "Returns a vector of where the collision ocurred" diff --git a/lua/entities/gmod_wire_expression2/core/custom/prop.lua b/lua/entities/gmod_wire_expression2/core/custom/prop.lua index 461defc839..8f1c72a2ae 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua @@ -1462,6 +1462,12 @@ local function E2CollisionEventHandler() if IsValid(chip) then if not chip.error then for _,i in ipairs(ctx.data.E2QueuedCollisions) do + if i.cb then + -- Arguments for this were checked when we set it up, no need to typecheck + i.cb:UnsafeCall({i.us,i.xcd.HitEntity,i.xcd}) + if chip.error then break end + end + -- It's okay to ExecuteEvent regardless, it'll just return when it fails to find the registered event chip:ExecuteEvent("entityCollision",{i.us,i.xcd.HitEntity,i.xcd}) if chip.error then break end end @@ -1473,25 +1479,57 @@ local function E2CollisionEventHandler() processNextTick = false end +local function startCollisionTracking(self,ent,entIndex,lambda) + local ctx = self + local callbackID = ent:AddCallback("PhysicsCollide", + function( us, cd ) + table.insert(ctx.data.E2QueuedCollisions,{us=us,xcd=cd,cb=lambda}) + if not processNextTick then + processNextTick = true + timer.Simple(0,E2CollisionEventHandler) -- A timer set to 0 runs next GM:Tick() hook + end + end) + self.data.E2TrackedCollisions[entIndex] = callbackID -- This ID is needed to remove the physcollide callback + ent:CallOnRemove("E2Chip_CCB" .. callbackID, function() + self.data.E2TrackedCollisions[entIndex] = nil + end) +end + e2function number trackCollision( entity ent ) + -- If it's not registered, collisions will just stack up infinitely and not be flushed. + if not registered_chips[self.entity] then + self:forceThrow("event entityCollision(eexcd) is needed to use trackCollision(e)!") + end if IsValid(ent) then local entIndex = ent:EntIndex() if self.data.E2TrackedCollisions[entIndex] then - return self:throw("Attempting to track collisions for an already tracked entity",0) -- Already being tracked. + return self:throw("Attempting to track collisions for an already tracked entity",0) end - local ctx = self - local callbackID = ent:AddCallback("PhysicsCollide", - function( us, cd ) - table.insert(ctx.data.E2QueuedCollisions,{us=us,xcd=cd}) - if not processNextTick then - processNextTick = true - timer.Simple(0,E2CollisionEventHandler) -- A timer set to 0 runs next GM:Tick() hook - end - end) - self.data.E2TrackedCollisions[entIndex] = callbackID -- This ID is needed to remove the physcollide callback - ent:CallOnRemove("E2Chip_CCB" .. callbackID, function() - self.data.E2TrackedCollisions[entIndex] = nil - end) + startCollisionTracking(self,ent,entIndex) + return 1 + end + return self:throw("Attempting to track collisions for an invalid entity",0) +end + +e2function number trackCollision( entity ent, function cb ) + -- However, since this one IS providing a callback, we can just register it and run the CB + if not registered_chips[self.entity] then + registered_chips[self.entity] = self + end + if IsValid(ent) then + local entIndex = ent:EntIndex() + if self.data.E2TrackedCollisions[entIndex] then + return self:throw("Attempting to track collisions for an already tracked entity",0) + end + -- First, double check the arg sig lines up + if cb.arg_sig ~= "eexcd" then + local arg_sig = "(void)" + if #cb.arg_sig > 0 then + arg_sig = "("..cb.arg_sig..")" + end + self:forceThrow("Collision callback expecting arguments (eexcd), got "..arg_sig) + end + startCollisionTracking(self,ent,entIndex,cb) return 1 end return self:throw("Attempting to track collisions for an invalid entity",0) @@ -1539,6 +1577,9 @@ registerCallback("destruct", function( self ) ent:RemoveCallback("PhysicsCollide", v) end end + -- Moved from event destructor to general destructor + -- Cause now it can be dynamically registered for callback functions + registered_chips[self.entity] = nil end) @@ -1549,9 +1590,7 @@ E2Lib.registerEvent("entityCollision", { {"CollisionData", "xcd"}, }, function(ctx) -- Event constructor + print("event constructor") registered_chips[ctx.entity] = ctx - end, - function(ctx) -- Event destructor - registered_chips[ctx.entity] = nil end ) From 6b7f0a0070a885fbf175ce0da597ae01eef34a82 Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Fri, 19 Jul 2024 20:02:38 -0500 Subject: [PATCH 13/14] Forgot to remove a print --- 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 8f1c72a2ae..6202ffbb2b 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/prop.lua @@ -1590,7 +1590,6 @@ E2Lib.registerEvent("entityCollision", { {"CollisionData", "xcd"}, }, function(ctx) -- Event constructor - print("event constructor") registered_chips[ctx.entity] = ctx end ) From 4c21ee047f823ed8a5d0b85da3124491bfeb561c Mon Sep 17 00:00:00 2001 From: DerelictDrone Date: Fri, 19 Jul 2024 20:35:32 -0500 Subject: [PATCH 14/14] Fit trackCollision descriptions to e2helper box --- lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua b/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua index 480847d786..ccb8606c17 100644 --- a/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua +++ b/lua/entities/gmod_wire_expression2/core/custom/cl_prop.lua @@ -90,8 +90,8 @@ E2Helper.Descriptions["setEyeTargetLocal(e:v)"] = "Sets the eye target to the lo E2Helper.Descriptions["setEyeTargetWorld(e:v)"] = "Sets the eye target to the world position" E2Helper.Descriptions["setFlexScale(e:n)"] = "Sets the flex scale of the entity" E2Helper.Descriptions["setFlexWeight"] = "Sets the weight of the flex" -E2Helper.Descriptions["trackCollision(e)"] = "Starts tracking collisions for the entity, will fire event entityCollision when they occur.\nDoes not track when players or vehicles hit world, only other entities.\nNeeds event entityCollision(entity, entity, collision) in order to run.\nReturns 1 on success or 0 on error in non-strict" -E2Helper.Descriptions["trackCollision(ef)"] = "Starts tracking collisions for the entity, will call the provided callback function, then fire event entityCollision when they occur.\nDoes not track when players or vehicles hit world, only other entities.\nMay track without event entityCollision\nPassed callback function needs argument signature of (eexcd), aka (entity, entity, collision)\nReturns 1 on success or 0 on error in non-strict." +E2Helper.Descriptions["trackCollision(e)"] = "Starts tracking collisions for the entity, will fire event entityCollision when they occur. Does not track when players or vehicles hit world, only other entities.\nNeeds event entityCollision(entity, entity, collision) in order to run.\nReturns 1 on success or 0 on error in non-strict" +E2Helper.Descriptions["trackCollision(ef)"] = "Starts tracking collisions for the entity, will call the provided function, then fire event entityCollision when they occur.\nMay track without event entityCollision. Passed callback function needs argument signature of (eexcd), aka (entity, entity, collision)\nFor more info see trackCollision(e)" E2Helper.Descriptions["isTrackingCollision(e)"] = "Returns 1 if the entity's collisions are already being tracked, 0 if not. Errors on an invalid ent" E2Helper.Descriptions["stopTrackingCollision(e)"] = "Stops tracking collisions for the entity.\nError in strict if entity is invalid or entity isn't being tracked" E2Helper.Descriptions["hitPos(xcd:)"] = "Returns a vector of where the collision ocurred"