Im not sure if you understand what I am going for here, I’m not replicating between clients, but replicating between instances of the server requiring a module, this has nothing to do with the client.
Thanks for your reply though!
Im not sure if you understand what I am going for here, I’m not replicating between clients, but replicating between instances of the server requiring a module, this has nothing to do with the client.
Thanks for your reply though!
oh i see now. Well logically the way i mentioned would be workable for module to module, but if u can provide some more info i.e the use case or behavior example of ur current code, it would be easier to identify
I dont think I really need to show code but uh, heres an example ig.
local Id = 0
local ThisId = 0
local module = {}
Id += 1
ThisId = Id
return module
Every time you require the module on the server, Id goes up by one.
I then want ThisId to be well Id, but if another script requires the module, ThisId will be set to the new Id value.
There are a few things you need to know about modules.
They run once and only once when required the first time. Having multiple requires will not re-run the code in your module. The requires subsequent to the first one will have a reference to what was returned the first time around.
You can not access local variables between module scripts unless you have a function returning their value.
Im aware, the module itself uses the local variable, not the scripts.
The behavior you want, which is for the ID to go up on each require, is not possible with the behavior of modules. What is your actual use case for something like this? I’m curious to know what made you approach things this way.
So the main point of this was for debugging purposes, as then I could tell what script changed what values with the help of metatables (specifically __newindex), in order to tell which script changed it I would just take the ThisId value, which well I explained above on how that works so yeah
There’s no way to detect a require
call. However, as long as the instances that require the module have unique full names, you can use debug.info
to identify the Script/LocalScript/ModuleScript that triggered the __newindex call.
Here’s an example of how this can be done. These example scripts (ModuleScripts and one Script) are in the same folder.
A ModuleScript called “ModuleWithRequireCounter”
local ModuleWithRequireCounter = {}
local COUNTER_VALUE_INDEX: string = "counter"
local counter: number = 0
local counterValuesForScriptInstanceFullNames: {[string]: number} = {}
-- This will return nil if there isn't an instance with this full name
-- or if there are multiple instances with this full name
-- (well, at least it should, I haven't tested it much).
local function getInstanceFromUniqueFullName(fullName: string): Instance?
local currentParents: {Instance} = {game}
for iName: number, name: string in string.split(fullName, ".") do
local currentValidChildren: {Instance} = {}
for _, parent: Instance in currentParents do
for _, child: Instance in parent:GetChildren() do
if child.Name ~= name then
continue
end
table.insert(currentValidChildren, child)
end
end
if #currentValidChildren == 0 then
print(`Zero instances with full name {fullName}.`)
return nil
end
currentParents = currentValidChildren
end
if #currentParents > 1 then
print(`More than 1 instance with full name {fullName}`)
return nil
end
return currentParents[1]
end
local function getId(): number
local requiringInstanceFullName: string = debug.info(3, "s")
if getInstanceFromUniqueFullName(requiringInstanceFullName) == nil then
error(`There is not exactly one instance with this full name ({requiringInstanceFullName}).`
.. "In order for the counter to be instance-spesific, the requiring instance"
.. " must be the only instance with its full name.")
end
if counterValuesForScriptInstanceFullNames[requiringInstanceFullName] == nil then
counter += 1
counterValuesForScriptInstanceFullNames[requiringInstanceFullName] = counter
end
local id: number = counterValuesForScriptInstanceFullNames[requiringInstanceFullName]
return id
end
local moduleData: {[any]: any} = {}
local metatable = {
__newindex = function(_, index: any, value: any)
local id: number = getId()
print(`Code in instance with id {id} changed ModuleWithRequireCounter.{index} from {moduleData[index]} to {value}`)
moduleData[index] = value
end,
}
setmetatable(ModuleWithRequireCounter, metatable)
return ModuleWithRequireCounter
A ModuleScript called “RequireCounterTestModule1”
local requireCounterTestFolder = script.Parent
local ModuleWithRequireCounter = require(requireCounterTestFolder.ModuleWithRequireCounter)
local RequireCounterTestModule1 = {}
ModuleWithRequireCounter.value1 = 7
return RequireCounterTestModule1
A ModuleScript called “RequireCounterTestModule2”
local requireCounterTestFolder = script.Parent
local ModuleWithRequireCounter = require(requireCounterTestFolder.ModuleWithRequireCounter)
local RequireCounterTestModule2 = {}
ModuleWithRequireCounter.value2 = 9
ModuleWithRequireCounter.value1 = -3
return RequireCounterTestModule2
A ModuleScript called “RequireCounterTestModule3”
local requireCounterTestFolder = script.Parent
local ModuleWithRequireCounter = require(requireCounterTestFolder.ModuleWithRequireCounter)
local RequireCounterTestModule3 = {}
ModuleWithRequireCounter.value2 = 4
ModuleWithRequireCounter.value1 = -1
ModuleWithRequireCounter.value3 = -6
return RequireCounterTestModule3
A script
local requireCounterTestFolder = script.Parent
local RequireCounterTestModule1 = require(requireCounterTestFolder.RequireCounterTestModule1)
local RequireCounterTestModule2 = require(requireCounterTestFolder.RequireCounterTestModule2)
local RequireCounterTestModule3 = require(requireCounterTestFolder.RequireCounterTestModule3)
Is it sufficient to have indexing the returned table with a specific key result in a different value depending on which Script/LocalScript/ModuleScript required the module? This can be achieved as long as the instances that require the module have unique full names.
Here’s an example of how this can be done.
A module script called “ModuleWithRequireCounter”
local ModuleWithRequireCounter = {}
local COUNTER_VALUE_INDEX: string = "counter"
local counter: number = 0
local counterValuesForScriptInstanceFullNames: {[string]: number} = {}
-- This will return nil if there isn't an instance with this full name
-- or if there are multiple instances with this full name
-- (well, at least it should, I haven't tested it much).
local function getInstanceFromUniqueFullName(fullName: string): Instance?
local currentParents: {Instance} = {game}
for iName: number, name: string in string.split(fullName, ".") do
local currentValidChildren: {Instance} = {}
for _, parent: Instance in currentParents do
for _, child: Instance in parent:GetChildren() do
if child.Name ~= name then
continue
end
table.insert(currentValidChildren, child)
end
end
if #currentValidChildren == 0 then
print(`Zero instances with full name {fullName}.`)
return nil
end
currentParents = currentValidChildren
end
if #currentParents > 1 then
print(`More than 1 instance with full name {fullName}`)
return nil
end
return currentParents[1]
end
local metatable = {
__index = function(_, index: any)
if index == COUNTER_VALUE_INDEX then
local requiringInstanceFullName: string = debug.info(2, "s")
if getInstanceFromUniqueFullName(requiringInstanceFullName) == nil then
error(`There is not exactly one instance with this full name ({requiringInstanceFullName}).`
.. "In order for the counter to be instance-spesific, the requiring instance"
.. " must be the only instance with its full name.")
end
if counterValuesForScriptInstanceFullNames[requiringInstanceFullName] == nil then
counter += 1
counterValuesForScriptInstanceFullNames[requiringInstanceFullName] = counter
end
return counterValuesForScriptInstanceFullNames[requiringInstanceFullName]
end
return nil
end,
}
setmetatable(ModuleWithRequireCounter, metatable)
return ModuleWithRequireCounter
A module script called “RequireCounterTestModule1”
local requireCounterTestFolder = script.Parent
local ModuleWithRequireCounter = require(requireCounterTestFolder.ModuleWithRequireCounter)
local RequireCounterTestModule1 = {}
task.spawn(function()
print(`Counter value for test module 1: {ModuleWithRequireCounter.counter}`)
task.wait(2)
print(`Counter value for test module 1: {ModuleWithRequireCounter.counter}`)
end)
return RequireCounterTestModule1
A modulescript called “RequireCounterTestModule2”
local requireCounterTestFolder = script.Parent
local ModuleWithRequireCounter = require(requireCounterTestFolder.ModuleWithRequireCounter)
local RequireCounterTestModule2 = {}
task.spawn(function()
print(`Counter value for test module 2: {ModuleWithRequireCounter.counter}`)
task.wait(1)
print(`Counter value for test module 2: {ModuleWithRequireCounter.counter}`)
end)
return RequireCounterTestModule2
A modulescript called “RequireCounterTestModule3”
local requireCounterTestFolder = script.Parent
local ModuleWithRequireCounter = require(requireCounterTestFolder.ModuleWithRequireCounter)
local RequireCounterTestModule3 = {}
task.spawn(function()
print(`Counter value for test module 3: {ModuleWithRequireCounter.counter}`)
task.wait(3)
print(`Counter value for test module 3: {ModuleWithRequireCounter.counter}`)
end)
return RequireCounterTestModule3
A script
local requireCounterTestFolder = script.Parent
local RequireCounterTestModule1 = require(requireCounterTestFolder.RequireCounterTestModule1)
local RequireCounterTestModule2 = require(requireCounterTestFolder.RequireCounterTestModule2)
local RequireCounterTestModule3 = require(requireCounterTestFolder.RequireCounterTestModule3)
sorry for the slight necro but I specifically mean instantiating a variable on only the server or client. if you’re doing that then I would move it to a module designed specifically for one or the other