Collision issue on Samsung Galaxy S20 bundled as release

In release mode the reverse hash functionality does not work, but URLs should still work. The individual parts of the URL are hashes and I’m sure these return the values for the hashed strings. Try this:

local url = msg.url( nil, message.other_id, nil )
print(url.socket, url.path, url.fragment)

What do you mean by this?

2 Likes

Yes, the long numbers and (unknown) only appear when the .apk is bundled as release.

I didn’t know you used be able to! Save me! :slight_smile:

That’s possible, but to me it seems fine?

Here is a screenshot of what comes back when printing socket, path and fragment individually (release build .apk on Galaxy S20):

Judging by the confusion on all sides here, I think it’s likely I’m missing something basic. It’s just troublesome it works on all devices apart from the S20. And that it’s so HOT TODAY. :hot_face:

In an effort to get to the crux of the matter, here is what I’m trying to do, step by step:

  1. Turn message.other_id (a collision object) into a game object url.
  2. Use tostring(url) as an id, ie. game_objects[tostring(url)], to cross reference it.

I get the feeling #2 is a no-no, so maybe the questions are:

  • What is the correct way of referencing a game object in an associative array?
  • Why does it only fail on the S20?

I’ll try to explain it in a bit different way.
Strings are available only for debug reason, there are no strings in release build.
It doesn’t matter you can’t see this string. It is not a bug, but if you mention this as a bug, probably you try to use hash in a wrong way.
Could you please explain why it’s bothering you and what exactly doesn’t work in your project because of that?

Thanks Agulev. Yeah, see above. I’m using tostring(url), which is likely why it fails (but only on one device, mind!).

I meant as you used to in debug mode.

  1. As you see from your screenshot (?), the values:
    17296653182486628446 and 12693854167970456507 are the same as in my example. Thus the original strings are “main”, and “/terrain”. So, your url seems fine.

  2. Using the Url as a string, is a no-no. As mentioned, the string representation is for debugging purposes. You should be able to use the url as a key in a table. If all else fails:

	local s = "" .. hash_to_hex(u.socket) .. ":/" .. hash_to_hex(u.path) .. "#" .. hash_to_hex(u.fragment)
	io.stderr:write(string.format("string_id: %s\n", s))

which outputs:

string_id: f00a0e6d893ec85e:/b029a11c607da3bb#f00a0e6d893ec85e
1 Like

Better yet:

	local t = {}
	t[url] = "Url A"
	pprint(t)

which yields:

DEBUG:SCRIPT: 
{ --[[0x10db78610]]
  url: [main:/terrain#main] = "Url A"
}

Oh, nice, I’m trying that right away! I have soaked a long sleeve t-shirt to keep the heat at bay. Thanks for your patience with this.

Hmm, there seems to be a caveat though. It seems it’s using the object id though. so unless you have the original url object, you won’t get the value.

I consider this a bug though. I’m guessing it has been requestedfor a fix previously.

A workaround is to iterate over the table, and do the compare yourself:

		
	for k, v in pairs(self.t) do
		if k == sender then
			print(k, v)
			break
		end
	end
2 Likes

Maybe that’s why I used strings to begin with. So going back to square one, how can I use the url as a key in a table in my specific case?

player.script:

local url = msg.url( nil, message.other_id, nil )
msg.post("/main#main", "hit_box", {url=url})

main.script:

local boxes 

function init(self)

	boxes = {}
	
	for i=1, 2 do
		local url = msg.url( nil, "box"..i, nil )
		boxes[url] = "box_index"..i
	end
	
end

function on_message(self, message_id, message, sender)

	if message_id == hash("hit_box") then

		pprint( boxes )
			--[[
			-- Returns:
			{
				url: [main:/box2] = "box_index2",
				url: [main:/box1] = "box_index1"
			}
			--]]
	
		print( message.url ) -- Returns url: [main:/box1]
		print( boxes[message.url] ) -- Returns nil
		
	end
	
end

Test project: UrlAsKey.zip (20 KB)

Yes, #2 is a very big NO-NO. It will break down completely in a release build. The tostring() will result in the non-unique [main:<unknown>] string and it will be useless as a table key.

If it is a hash then you can use it as a key in a table. The hashes will be unique even in a debug build. If it is a URL you need to convert it to a unique string from its components before using it as a key:

local EMPTY = hash("")

local function to_key(url)
	return hash_to_hex(url.socket or EMPTY) .. hash_to_hex(url.path or EMPTY) .. hash_to_hex(url.fragment or EMPTY)
end

That’s the million dollar question. Which other devices have you tested on?

3 Likes

And now that I think of it maybe we should handle this under-the-hood somehow. We should provide a better __tostring meta-method for URLs. It’s not the first time someone has stumbled on to this issue.

2 Likes

This is what I’ve been missing. I modified the test project to create a key in this way and now it works! :metal: :metal: :metal:

Thanks for helping me find the missing piece of the puzzle.

The above fix might be obvious to some, but it’s black magic to me. Would love to have an easier way to do this.

Literally hundreds of devices on Android and iOS: The game is in soft launch. As far as I know, only the S20 is kicking up a fuss.

Given the solution described, it would apply to all platforms in release mode. If you still only have that particular issue on the S20, then you have another issue in your code.

One step at a time. I might be back! :slight_smile:

It would be really nice if the URL object you got for a given object or component was always the same one, so you could use them as table keys, rather than ending up with something like this:

{ --[[00000000028799B0]]
  url: [game:/player/root#script] = 4,
  url: [game:/player/root#script] = 3,
  url: [game:/player/root#script] = 1,
  url: [game:/player/root#script] = 2
}
2 Likes

By looking a the Lua C code, it seems it’s not possible since it stores the pointer of the object. However, we’ll implement another function for the url, that would give you the url as a unique key, that you can use instead, to the same effect.

5 Likes

Quick question: Can url.path be used as a key in a table? Or is it equally super-bad as using the url itself?

It seems to be fine reading this thread, but wanted to confirm.

Yes, url.path is a hash and hashes can be used as table keys without any problems.

3 Likes

Fantastic!