-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Linkage reworks #419
Linkage reworks #419
Changes from 3 commits
e91eae9
bdc5c6d
ef731d1
de253ca
ce719e8
ac3b9e9
12e0443
6479163
209e5c1
e6c6a4b
730c197
c2c2d24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -399,97 +399,150 @@ do -- Entity linking | |
return Result | ||
end | ||
|
||
--[[ | ||
Example structure of ClassLink: | ||
--- @class LinkFunction | ||
--- @field Ent1 table The first entity in the link | ||
--- @field Ent2 table The second entity in the link | ||
--- @field FromChip boolean If the link is from a chip | ||
--- @return boolean? Success Whether the link was successful | ||
--- @return string? Message A message about the link status | ||
|
||
--- Represents information about storing the link on an entity | ||
--- @class LinkStore | ||
--- @field StoreName string Any entity of this class will store references to the other class in this attribute | ||
--- @field Ordered boolean If true, maintains the link as an array rather than a lookup table | ||
|
||
--- @class LinkOptions | ||
--- @field Link LinkFunction The function to handle linking | ||
--- @field Unlink LinkFunction The function to handle unlinking | ||
--- @field Check LinkFunction The function to check the link status | ||
--- @field ChipDelay number The delay associated with the link if done via chip | ||
--- @field LinkStore1 LinkStore Information about this class stores links to the other class | ||
--- @field LinkStore2 LinkStore Information about how the other class stores links to this class | ||
|
||
local ClassLink = { } | ||
|
||
function ACF.GetLinkDataSafe(Class1, Class2) | ||
if not ClassLink[Class1] then ClassLink[Class1] = {} end | ||
if not ClassLink[Class1][Class2] then ClassLink[Class1][Class2] = {} end | ||
return ClassLink[Class1][Class2] | ||
end | ||
|
||
ClassLink = { | ||
["Link"] = { | ||
["acf_ammo"] = { | ||
["acf_gun"] = function(Ent1, Ent2) -- Handles linking guns and ammo | ||
} | ||
}, | ||
["Unlink"] = { | ||
["acf_ammo"] = { | ||
["acf_gun"] = function(Ent1, Ent2) -- Handles unlinking guns and ammo | ||
} | ||
} | ||
} | ||
]]-- | ||
local ClassLink = { Link = {}, Unlink = {} } | ||
--- Adds a link to this entity's list of links of this LinkData | ||
local function AddLink(Ent, LinkEnt, LinkData) | ||
local StoreName, Ordered = LinkData.StoreName, LinkData.Ordered | ||
if not Ent[StoreName] then Ent[StoreName] = {} end | ||
if Ordered then table.insert(Ent[StoreName], LinkEnt) | ||
else Ent[StoreName][LinkEnt] = true end | ||
end | ||
|
||
--- Registers a link or unlink between two classes and how to handle them. | ||
--- Removes a link from this entity's list of links of this LinkData | ||
local function RemoveLink(Ent, LinkEnt, LinkData) | ||
local StoreName, Ordered = LinkData.StoreName, LinkData.Ordered | ||
if not Ent[StoreName] then Ent[StoreName] = {} end | ||
if Ordered then table.RemoveByValue(Ent[StoreName], LinkEnt) | ||
else Ent[StoreName][LinkEnt] = nil end | ||
end | ||
|
||
--- Registers that two classes can be linked, as well as how to handle entities of their class being linked. | ||
--- @param Class1 string The first class in the link | ||
--- @param Class2 string The other class in the link | ||
--- @param Function fun(Entity1:table, Entity2:table) | ||
local function RegisterNewLink(Action, Class1, Class2, Function) | ||
if not isfunction(Function) then return end | ||
|
||
local Target = ClassLink[Action] | ||
local Data1 = Target[Class1] | ||
|
||
if not Data1 then | ||
Target[Class1] = { | ||
[Class2] = function(Ent1, Ent2) | ||
return Function(Ent1, Ent2) | ||
end | ||
} | ||
else | ||
Data1[Class2] = function(Ent1, Ent2) | ||
return Function(Ent1, Ent2) | ||
end | ||
--- @param Function fun(Entity1:table, Entity2:table, FromChip:boolean) The linking function defined between an entity of Class1 and an entity of Class2; this should always return a boolean for link status and a string for link message | ||
function ACF.RegisterClassLink(Class1, Class2, Function) | ||
local LinkData1 = ACF.GetLinkDataSafe(Class1,Class2) | ||
LinkData1.Link = function(Ent1, Ent2, FromChip) | ||
if LinkData1.LinkStore1 then AddLink(Ent1, Ent2, LinkData1.LinkStore1) end | ||
if LinkData1.LinkStore2 then AddLink(Ent1, Ent2, LinkData1.LinkStore2) end | ||
return Function(Ent1, Ent2, FromChip) | ||
end | ||
|
||
if Class1 == Class2 then return end | ||
|
||
local Data2 = Target[Class2] | ||
|
||
if not Data2 then | ||
Target[Class2] = { | ||
[Class1] = function(Ent2, Ent1) | ||
return Function(Ent1, Ent2) | ||
end | ||
} | ||
else | ||
Data2[Class1] = function(Ent2, Ent1) | ||
return Function(Ent1, Ent2) | ||
end | ||
local LinkData2 = ACF.GetLinkDataSafe(Class1,Class2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this be the same as line 451? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, it should be reversed to
|
||
LinkData2.Link = function(Ent2, Ent1, FromChip) | ||
if LinkData2.LinkStore1 then AddLink(Ent1, Ent2, LinkData2.LinkStore1) end | ||
if LinkData1.LinkStore2 then AddLink(Ent1, Ent2, LinkData1.LinkStore2) end | ||
return Function(Ent1, Ent2, FromChip) | ||
end | ||
end | ||
|
||
--- Registers that two classes can be linked, as well as how to handle entities of their class being linked. | ||
--- Registers that two classes can be unlinked, as well as how to handle entities of their class being unlinked. | ||
--- @param Class1 string The first class in the link | ||
--- @param Class2 string The other class in the link | ||
--- @param Function fun(Entity1:table, Entity2:table) The linking function defined between an entity of Class1 and an entity of Class2; this should always return a boolean for link status and a string for link message | ||
function ACF.RegisterClassLink(Class1, Class2, Function) | ||
RegisterNewLink("Link", Class1, Class2, Function) | ||
--- @param Function fun(Entity1:table, Entity2:table, FromChip:boolean) The unlinking function defined between an entity of Class1 and an entity of Class2 | ||
function ACF.RegisterClassUnlink(Class1, Class2, Function) | ||
local LinkData1 = ACF.GetLinkDataSafe(Class1,Class2) | ||
LinkData1.Unlink = function(Ent1, Ent2, FromChip) | ||
if LinkData1.LinkStore1 then RemoveLink(Ent1, Ent2, LinkData1.LinkStore1) end | ||
if LinkData1.LinkStore2 then RemoveLink(Ent1, Ent2, LinkData1.LinkStore2) end | ||
return Function(Ent1, Ent2, FromChip) | ||
end | ||
if Class1 == Class2 then return end | ||
local LinkData2 = ACF.GetLinkDataSafe(Class1,Class2) | ||
LinkData2.Unlink = function(Ent2, Ent1, FromChip) | ||
if LinkData2.LinkStore1 then RemoveLink(Ent1, Ent2, LinkData2.LinkStore1) end | ||
if LinkData1.LinkStore2 then RemoveLink(Ent1, Ent2, LinkData1.LinkStore2) end | ||
return Function(Ent1, Ent2, FromChip) | ||
end | ||
end | ||
|
||
--- Returns the callback defined previously by ACF.RegisterClassLink between Class1 and Class2. | ||
--- Registers a validation check between two classes. | ||
--- @param Class1 string The first class in the link | ||
--- @param Class2 string The other class in the link | ||
--- @return fun(Entity1:table, Entity2:table) | nil # The linking function defined between an entity of Class1 and an entity of Class2, or nil if Class1 has no linking functions | ||
function ACF.GetClassLink(Class1, Class2) | ||
if not ClassLink.Link[Class1] then return end | ||
|
||
return ClassLink.Link[Class1][Class2] | ||
--- @param Function fun(Entity1:table, Entity2:table, FromChip:boolean) The checking function defined between an entity of Class1 and an entity of Class2 | ||
function ACF.RegisterClassCheck(Class1, Class2, Function) | ||
ACF.GetLinkDataSafe(Class1,Class2).Check = function(Ent1, Ent2, FromChip) return Function(Ent1, Ent2, FromChip) end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, localize the result from |
||
if Class1 == Class2 then return end | ||
ACF.GetLinkDataSafe(Class2,Class1).Check = function(Ent2, Ent1, FromChip) return Function(Ent1, Ent2, FromChip) end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, localize the result from |
||
end | ||
|
||
--- Registers that two classes can be unlinked, as well as how to handle entities of their class being unlinked. | ||
--- Registers a chip delay between two classes. | ||
--- @param Class1 string The first class in the link | ||
--- @param Class2 string The other class in the link | ||
--- @param Function fun(Entity1:table, Entity2:table) The unlinking function defined between an entity of Class1 and an entity of Class2 | ||
function ACF.RegisterClassUnlink(Class1, Class2, Function) | ||
RegisterNewLink("Unlink", Class1, Class2, Function) | ||
--- @param ChipDelay number If the link happens from the chip, then delay it by this amount | ||
function ACF.RegisterClassDelay(Class1, Class2, ChipDelay) | ||
ACF.GetLinkDataSafe(Class1,Class2).ChipDelay = ChipDelay | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, localize the result from |
||
if Class1 == Class2 then return end | ||
ACF.GetLinkDataSafe(Class2,Class1).ChipDelay = ChipDelay | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, localize the result from |
||
end | ||
|
||
--- Returns the callback defined previously by ACF.RegisterClassUnlink between Class1 and Class2. | ||
--- @param Class1 string The first class in the link | ||
--- @param Class2 string The other class in the link | ||
--- @return fun(Entity1:table, Entity2:table) | nil # The unlinking function defined between an entity of Class1 and an entity of Class2, or nil if Class1 has no unlinking functions | ||
function ACF.GetClassUnlink(Class1, Class2) | ||
if not ClassLink.Unlink[Class1] then return end | ||
function ACF.RegisterClassStore1(Class1, Class2, LinkStore) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a reason to have these functions being separated? |
||
ACF.GetLinkDataSafe(Class1,Class2).LinkStore1 = LinkStore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, same reason as before. |
||
if Class1 == Class2 then return end | ||
ACF.GetLinkDataSafe(Class2,Class1).LinkStore2 = LinkStore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, same reason as before. |
||
end | ||
|
||
return ClassLink.Unlink[Class1][Class2] | ||
function ACF.RegisterClassStore2(Class1, Class2, LinkStore) | ||
ACF.GetLinkDataSafe(Class1,Class2).LinkStore2 = LinkStore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, same reason as before. |
||
if Class1 == Class2 then return end | ||
ACF.GetLinkDataSafe(Class2,Class1).LinkStore1 = LinkStore | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readability, same reason as before. |
||
end | ||
|
||
--- Saves a link in an entity's AD2 entity modifiers | ||
function ACF.AD2SaveLinks(Entity, StoreName, SaveName) | ||
local tbl = {} | ||
|
||
if table.IsSequential(Entity[StoreName]) then | ||
for _,ent in ipairs(Entity[StoreName]) do table.insert(tbl,ent:EntIndex()) end | ||
else | ||
for ent,_ in pairs(Entity[StoreName]) do table.insert(tbl,ent:EntIndex()) end | ||
end | ||
|
||
duplicator.StoreEntityModifier(Entity, SaveName, tbl) | ||
end | ||
|
||
--- Loads a link from an entity's AD2 entity modifiers | ||
function ACF.AD2LoadLinks(Entity, SaveName, EntMods, CreatedEntities) | ||
if EntMods[SaveName] then | ||
for _, id in ipairs(EntMods[SaveName]) do Entity:Link(CreatedEntities[id]) end | ||
EntMods[SaveName] = nil | ||
end | ||
end | ||
|
||
--- Unlinks every entity from this entity of this link type | ||
function ACF.UnlinkAll(Entity, StoreName) | ||
if table.IsSequential(Entity[StoreName]) then | ||
for _, ent in ipairs(Entity[StoreName]) do Entity:Unlink(ent) end | ||
else | ||
for ent, _ in pairs(Entity[StoreName]) do Entity:Unlink(ent) end | ||
end | ||
end | ||
end | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In terms of naming convention, returning a "Safe" value often means a copy of it. In this case, the actual real value is being returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed to GetLinkData since its usage requires it to return a real value
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally called it "Safe" since it safely checks if the table exists and creates a new one if it doesn't already exist.