Overwrite Data

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
khamarr3524
Prole
Posts: 41
Joined: Thu Sep 05, 2013 8:48 pm

Overwrite Data

Post by khamarr3524 »

Hello. I'm currently completely lost in how this is failing to work. I'm pretty understanding of OOP but with lua there grows some issues. This is most likely one of them.

I am using the newest implementation of middleclass and I am having issues with units being overwritten in what seems like a global scope, but they should be. I'll post the snippets of concern as well as a .love that will assert the output from an assertion I will also post.

First, I will show how I am loading units.

Code: Select all

--Load the GMTest Unit from file and pass it through Entity
  local tU = Entity:new(require(dH.Units .. "GMTest"))
  --Move the unit to the starting coordinates (found in data/maps/tutorial.lua
  tU:moveTo(GameWorld.map.properties.sX, GameWorld.map.properties.sY)
  tU:setGUID(1)
  tU:setUnitLevel(69)
  --Store the unit table into the GameWorld
  GameWorld:storeUnit(tU)
  tU = nil
  --Reload a second unit to tU
  tU = Entity:new(require(dH.Units .. "GMTest"))
  --Move to an arbitrary location
  tU:moveTo(2, 5)
  --Change the GUID to something arbitrary
  tU:setGUID(645969)
  tU:setUnitLevel(3003)
  --Store this unit
  GameWorld:storeUnit(tU)
Now I will show what GameWorld:storeUnit(unit) is:

Code: Select all

function World:storeUnit(unit)
  local id = unit:getGUID()
  self.map.layers.unit[id] = unit
  unit = {}
end
Here's where the biggest issue is. I'll provide the assert that is ending the execution of the .love after this. Calling

Code: Select all

self.map.layers.unit[1]:getGUID()
returns the value 645969 where it should simply return 1. This is the root of my issue: The first unit is being overwritten almost entirely by the second storeUnit. If someone could take a look at this and give me any insight by all means.

Here is the assert

Code: Select all

  if self.map.layers.unit[1] then
    assert(false, self.map.layers.unit[1]:getGUID())
  end
Attachments
The Thing.love
(569.11 KiB) Downloaded 189 times
User avatar
artofwork
Citizen
Posts: 91
Joined: Mon Sep 15, 2014 1:17 am
Location: East Coast USA

Re: Overwrite Data

Post by artofwork »

This is just a quick look, I wasn't able to run the program because my systems doesn't support shaders however if you look at init.lua on line 135 in src\data\

Code: Select all

  tU:setGUID(1)
on line 139 you set tu to nil

Code: Select all

tU = nil
and then on line 145 you set a new value

Code: Select all

  tU:setGUID(645969)
Lua will return the last value set
khamarr3524
Prole
Posts: 41
Joined: Thu Sep 05, 2013 8:48 pm

Re: Overwrite Data

Post by khamarr3524 »

That doesn't quite make sense.

I first loaded the unit via Entity:new() and passing values. I added some values such as the GUID and level, then stored tU to the world instance via GameWorld:storeUnit(). I then nil tU and reload it from file. If I'm pulling the GUID from the World of the index I saved from the first unit, it should be 1, but it's the last set value.
User avatar
artofwork
Citizen
Posts: 91
Joined: Mon Sep 15, 2014 1:17 am
Location: East Coast USA

Re: Overwrite Data

Post by artofwork »

In Entity.lua in its constructor line 15

self.info is not a table, it is a table but it doesn't contain a property called GUID

Code: Select all

self.info = t.info
but here on line 68

Code: Select all

function Entity:setGUID(id)
  self.info.GUID = id
end
and line 80

Code: Select all

function Entity:getGUID()
	return self.info.GUID
end
I'm surprised it returns anything at all since the function definition is only defined in Entity.lua

Code: Select all

Search "getGUID" (7 hits in 3 files)
  C:\Documents and Settings\user\My Documents\The Thing\lib\Entity.lua (1 hits)
	Line 80: function Entity:getGUID()
  C:\Documents and Settings\user\My Documents\The Thing\lib\world.lua (5 hits)
	Line 49:   local id = unit:getGUID()
	Line 51:   --self.map.layers.unit[1]:getGUID() should return 1, thus why it is unit[1]. It however returns the last GUID added to any entity.
	Line 53:     assert(false, self.map.layers.unit[1]:getGUID())
	Line 64:   local id = object:getGUID()
	Line 278:       local id = v:getGUID()
  C:\Documents and Settings\user\My Documents\The Thing\src\data\debug.lua (1 hits)
	Line 19:   Debug.updateMsg(4, "Id", "GUID: " .. u:getGUID())
I was just backtracking from GameWorld:storeUnit(tU), frankly im kinda lost in the mess lol, this is why I don't like to use other people's libraries because everyone likes to make things more complex then they need to be.
khamarr3524
Prole
Posts: 41
Joined: Thu Sep 05, 2013 8:48 pm

Re: Overwrite Data

Post by khamarr3524 »

That makes less sense. You don't need a variable to be defined before saving toThe it in lua. When I call self.info.GUID = id, the variable (should) be set to id. Entity:GetGUID() is a method member of Entity so when you create a new instance of Entity this method is there for use on a table based off of it. The issue is the data isn't actually being saved in world and I can't figure out why. I'm going to try a clean test environment where I play with the use of this implementation and see if I can narrow it down.
khamarr3524
Prole
Posts: 41
Joined: Thu Sep 05, 2013 8:48 pm

Re: Overwrite Data

Post by khamarr3524 »

I have found a solution to the problem, but I don't know why. Apparently you cannot directly copy data from a required file. To solve this issue, one has to iterate over the key value pairs for the data and copy it into the initialization. This may have something to do with require. It is possible that by modifying the data that was pulled from the require didn't cause it to reload. I don't have time to look into this at the moment. I'm not entirely sure how these things work as I'd have to go read through the functions from lua (namely require) and see how it functions exactly.
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Overwrite Data

Post by Positive07 »

Require caches everything so if you require a file for example "superfile" then you delete it and require "superfile" again it would be the same

Code: Select all

local super = require "superfile"
super.hello = 100000
super = nil
super = require "superfile"
print(super.hello) --100000
You can delete all the references by clearing package.loaded and package.preload (not sure about the last one)

Code: Select all

package.loaded["superfile"] = nil
package.preload["superfile"] = nil --not sure but just in case
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
khamarr3524
Prole
Posts: 41
Joined: Thu Sep 05, 2013 8:48 pm

Re: Overwrite Data

Post by khamarr3524 »

I'm still confused as to why the data was mixed.

What I was doing was taking data from the file, and copying it to the self variable of the class via direct assignment. I would then use the class method member to modify the values. But if I do this to a second object it was modifying both.

From what I experimented with and what I just said, the only explanation is that by directly assigning information loaded from a require table, I'm merely causing the self variables of that class to reference the data in which the require statement is stored. Would this be correct?

Once I looped through the table elements and individually assigned them to the correct self table did this error disappear. So in other words I would use

Code: Select all

function YourClass:initialize(yourTable)
  self.info = {}
  for k, v in pairs(yourTable.info) do
    self.info[k] = v
  end
end
instead of

Code: Select all

function YourClass:initialize(yourTable)
  self.info = yourTable.info
end
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Overwrite Data

Post by Positive07 »

That is because lua references tables rather than copying them, so every time you modify the reference you are modifying the original table (and of course all the other tables that reference to it). If you want to copy (instead of reference) look for "deep copy" in the forums... you'll find lot of things about it

EDIT:
If you want to copy a table you can use the code you posted

Code: Select all

    function YourClass:initialize(yourTable)
      self.info = {}
      for k, v in pairs(yourTable.info) do
        self.info[k] = v
      end
    end
But if yourTable has a table inside of it

Code: Select all

yourTable.childTable = {}
Your code would simply reference this table, something you dont want... deep copy takes into account this and copy the childTable too. Then other problem arise

Code: Select all

yourTable.childTable.littleTable = yourTable
That would generate a never ending loop so deep-copy libraries also handle this cases... I recommend you to read this
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
khamarr3524
Prole
Posts: 41
Joined: Thu Sep 05, 2013 8:48 pm

Re: Overwrite Data

Post by khamarr3524 »

That's what I thought, thanks for that. Would this work for the naming convention as well.

Say I have a table t, and inside the table it has info, also a table. Would deep copying account for it so that if:

local x = deepCopy(t)
x.info.someKey? That's the only thing I was thinking about was whether or not the hierarchy is saved.
Post Reply

Who is online

Users browsing this forum: No registered users and 35 guests