Non-square non-1x1 inserter giving constant error

Place to get help with not working mods / modding interface.
Post Reply
User avatar
Reika
Filter Inserter
Filter Inserter
Posts: 582
Joined: Tue May 19, 2015 1:56 am
Contact:

Non-square non-1x1 inserter giving constant error

Post by Reika »

I am trying to make an entity of type inserter which has a size of 3x6, and no matter what I do, I cannot get the game to load, as it always halts with an "invalid insert vector, not a safe distance from the tile edge" error.

No matter what positions I pick, I get this error. I have tried the originals (inherited from the stack inserter), those values offset by 1, 1.5, and 3 (to compensate for the increased hitbox size), and even ridiculous like {0, 2000}. Nothing has worked.

What exactly raises this error? What is it telling me, and what can I do to fix it (not just some magic values, but how are such 'safe' values derived)?

Image
Image

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by eradicator »

They're probably derived similar to fluid boxes (see this post).
I find those error messages pretty frustrating myself though.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

User avatar
Reika
Filter Inserter
Filter Inserter
Posts: 582
Joined: Tue May 19, 2015 1:56 am
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by Reika »

eradicator wrote:They're probably derived similar to fluid boxes (see this post).
I find those error messages pretty frustrating myself though.
I suspected this, as I have run into that error myself, back when designing the geothermal wells.

However, among the values I tried were ones that should meet that criterion, like {0, -1.6} or {0, -2} for an entity of collision box {{-2.9, -1.4}, {2.9, 1.4}}.

EDIT:
OK, WTF: I tried rotating the collision and selection boxes 90 degrees, as a random test, and now it loads. But the insert vector is inside the collision box! How is this acceptable while its 90-degree counterpart is not?! And why do vanilla ones - which are NOT inside the box - work?
Image


Also, rotation is broken - I hit R when holding the item, but when I place a new entity, its collision box is not placed in a rotated state. Its insert vectors are, (and now in line with what I wanted), but the collision box remains "aligned to Y axis". Likewise if I rotate the insert vector in the prototype but leave the collision box unrotated:
Image
Image
Image

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by eradicator »

Non-square entities are generally fiddly, and if you want an entity that's rotateable 4 ways after being placed they're a straight no-go. They can only rotate 2-way (i.e. flip direction). And ofc the vectors are box sensitive. Best guess: inserters don't have any code for non-square boxes. Best to ask someone (rsed?) on irc i guess.

I remember there was a bug report/fix about a non-square tank but can't find it right now. I found a topic concerning assemblers viewtopic.php?t=53310 which sounds like it supports my theory that every entity needs special code before it can handle non-square boxes.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

User avatar
Therax
Filter Inserter
Filter Inserter
Posts: 470
Joined: Sun May 21, 2017 6:28 pm
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by Therax »

Reika wrote:However, among the values I tried were ones that should meet that criterion, like {0, -1.6} or {0, -2} for an entity of collision box {{-2.9, -1.4}, {2.9, 1.4}}.
Insert positions must not be on tile boundaries, i.e. having final coordinates that are integers or close to integers. (I've found >=0.2 and <=0.8 to be safest.)

For this example, the collision box has even size in the X direction, and odd size in the Y direction, so the center of the entity will be something like (0, 0.5). Adding the insert vector to this, we get (0, -1.1), and (0, -1.5). These are both invalid in the X direction. It's unclear to the engine whether dropped items should be inserted into tile (0,-1) or (-1, -1).

Vanilla inserters are 1x1, giving them a conceptual center of (0.5, 0.5) relative to the tile grid, and integer pickup/drop positions are always safely within the bounds of a tile.
Reika wrote:EDIT:
OK, WTF: I tried rotating the collision and selection boxes 90 degrees, as a random test, and now it loads. But the insert vector is inside the collision box! How is this acceptable while its 90-degree counterpart is not?! And why do vanilla ones - which are NOT inside the box - work?
Being inside/outside the collision box is not important, as long as the drop_position is clearly inside a tile, not near a tile boundary.

Rotating the collision box changes the conceptual center of the entity to (0.5, 0). If you did not change the drop_position, we now have a sum drop position of:

(0.5, -1.1) or (0.5, -1.5), which do not contain integer values on either axis, and are thus valid.

From the screenshots, it looks like you're trying to make a train unloader with inserters, possibly inspired by Miniloader? :) I ran into very similar problems tweaking drop positions to put items into the different lanes of a belt.
Miniloader β€” UPS-friendly 1x1 loaders
Bulk Rail Loaders β€” Rapid train loading and unloading
Beltlayer & Pipelayer β€” Route items and fluids freely underground

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by eradicator »

@Therax:
Do you have any "proof"/anectodes that that "conceptual" center of entities is relevant to vectors? I assumed that entities are always "centered" on 0,0 of their own collision box and thus the vectors should be based on that and not on if the game places them on a tile boundary or not?
(Not saying you're wrong. I'm just struggling with that s*** myself and want to understand it better...)
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5150
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by Klonan »

eradicator wrote:@Therax:
Do you have any "proof"/anectodes that that "conceptual" center of entities is relevant to vectors? I assumed that entities are always "centered" on 0,0 of their own collision box and thus the vectors should be based on that and not on if the game places them on a tile boundary or not?
(Not saying you're wrong. I'm just struggling with that s*** myself and want to understand it better...)
Maybe you can glean some insight from this:

Code: Select all

bool InserterPrototype::isPickupDropoffPositionValid(Vector checkVector)
{
  double intPart;
  float intPartFloat;
  checkVector.dx = modff(modf(modf(checkVector.dx, &intPart) + double(1.0), &intPart), &intPartFloat);
  checkVector.dy = modff(modf(modf(checkVector.dy, &intPart) + double(1.0), &intPart), &intPartFloat);
  return !(checkVector.dx <= ItemEntityPrototype::size.getDouble() + 0.01 ||
           checkVector.dy <= ItemEntityPrototype::size.getDouble() + 0.01 ||
           checkVector.dx >= 1 - ItemEntityPrototype::size.getDouble() - 0.01 ||
           checkVector.dy >= 1 - ItemEntityPrototype::size.getDouble() - 0.01);
}

User avatar
Therax
Filter Inserter
Filter Inserter
Posts: 470
Joined: Sun May 21, 2017 6:28 pm
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by Therax »

eradicator wrote:@Therax:
Do you have any "proof"/anectodes that that "conceptual" center of entities is relevant to vectors? I assumed that entities are always "centered" on 0,0 of their own collision box and thus the vectors should be based on that and not on if the game places them on a tile boundary or not?
(Not saying you're wrong. I'm just struggling with that s*** myself and want to understand it better...)
Anecdotal evidence: Reika rotated the collision_box of an entity without changing the vectors, and it went from non-working to working. ;)

I'm assuming that collision boxes are centered around 0,0, which I believe is true for all vanilla entities and followed by most mod authors. I've never tried to make a collision box that wasn't centered on 0,0, so I can't say what the behavior might be in that case. When I say "conceptual center", all I'm referring to is whether the center of an entity, its "position", lies on a tile boundary or not.

The "position" of an entity is the center of the collision box, but the size of the collision box affects where "position" lies in relation to the tile grid. Check "position" of a 1x1 entity (inserter), or a 3x3 entity (storage-tank), and you'll always find that the position has the form (XX.5, YY.5). Do the same for an entity with an even dimension, like a pump or a decider combinator (1x2), and you'll find that the position is always (XX.0, YY.5) or (XX.5, YY.0), depending on its rotation.

Do the same for a 2x2 entity like a straight-rail or a train-stop, and the position is always (XX.0, YY.0), because the center of the entity is exactly the center of 4 tiles, on a "corner" of the tile grid.

Put another way, Factorio's coordinate system is anchored at the top-left corner of each tile, so tile boundaries are integer coordinates, while a 1x1 entity aligned with the grid has its position in the center of a tile, at (0.5, 0.5) relative to the top-left corner of its tile.
Last edited by Therax on Tue Jan 16, 2018 9:34 pm, edited 1 time in total.
Miniloader β€” UPS-friendly 1x1 loaders
Bulk Rail Loaders β€” Rapid train loading and unloading
Beltlayer & Pipelayer β€” Route items and fluids freely underground

User avatar
Therax
Filter Inserter
Filter Inserter
Posts: 470
Joined: Sun May 21, 2017 6:28 pm
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by Therax »

Klonan wrote:Maybe you can glean some insight from this:

Code: Select all

bool InserterPrototype::isPickupDropoffPositionValid(Vector checkVector)
{
  double intPart;
  float intPartFloat;
  checkVector.dx = modff(modf(modf(checkVector.dx, &intPart) + double(1.0), &intPart), &intPartFloat);
  checkVector.dy = modff(modf(modf(checkVector.dy, &intPart) + double(1.0), &intPart), &intPartFloat);
  return !(checkVector.dx <= ItemEntityPrototype::size.getDouble() + 0.01 ||
           checkVector.dy <= ItemEntityPrototype::size.getDouble() + 0.01 ||
           checkVector.dx >= 1 - ItemEntityPrototype::size.getDouble() - 0.01 ||
           checkVector.dy >= 1 - ItemEntityPrototype::size.getDouble() - 0.01);
}
Thanks Klonan!

So taking "s" as the size of the "item-on-ground" entity (plus a floating-point rounding-compensation factor of 0.01), it takes the fractional part of both x and y of checkVector and makes sure they're in the range s <= fractional_part <= 1-s. The addition of 1.0 ensures that fractional_part always ends up with a positive value in the range 0 <= x < 1.

I'm fairly sure that checkVector is simply position + drop_position. What eradicator and I are discussing is how tile alignment determines the inserter's position from its collision_box.
Miniloader β€” UPS-friendly 1x1 loaders
Bulk Rail Loaders β€” Rapid train loading and unloading
Beltlayer & Pipelayer β€” Route items and fluids freely underground

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by eradicator »

Therax wrote:What eradicator and I are discussing is how tile alignment determines the inserter's position from its collision_box.
Not really. You misunderstood the question. It looked like you were calculating the correct vector values off the map position of an entity whereas i assume that the map position should be (more or less) irrelevant. Thinking about it the map position has to be relevant to prevent dropping on tile borders.... I'm farily sure i know how the positioning works though (see my description here).

@Klonan:
Thanks for the snippet. I have to admit i have no c experience... but comparing it with @Theraxes explanation (thanks for that too) i think i get it now. A vector is invalid if it would put an item-on-the-ground so close to the tile border that the items collision box would overlap with the tile border. It also doesn't seem to consider the collision box at all?

@Therax:
I always thought of the 0.01 as more of a collision-prevention so things directly adjacent things don't collide. I.e. two lines [0,1] and [1,2] collide at the point 1, but two lines [0,0.99] and [1.01,2] don't collide.

So that would mean a valid vector for a 6x3 entity should be...eer, {0,3.5} or {0.5,2} for pickup and {0,3.7} or {0.5,2.2} for insert? Time for @Reika to do some more tests :P
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: ζ—₯本θͺž, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

User avatar
Reika
Filter Inserter
Filter Inserter
Posts: 582
Joined: Tue May 19, 2015 1:56 am
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by Reika »

eradicator wrote:Time for @Reika to do some more tests :P
Because of these and other problems, I ended up scrapping the entire entity, at least for now.
Image

PyroFire
Filter Inserter
Filter Inserter
Posts: 356
Joined: Tue Mar 08, 2016 8:18 am
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by PyroFire »

Seems like having certain prototypes completely unrelated to the inserter (e.g. data.raw.item-entity) with incorrect collision boxes also cause this error.

Weird.

User avatar
Therax
Filter Inserter
Filter Inserter
Posts: 470
Joined: Sun May 21, 2017 6:28 pm
Contact:

Re: Non-square non-1x1 inserter giving constant error

Post by Therax »

PyroFire wrote: ↑
Tue Nov 05, 2019 9:23 pm
Seems like having certain prototypes completely unrelated to the inserter (e.g. data.raw.item-entity) with incorrect collision boxes also cause this error.

Weird.
Not that weird. As discussed:
Therax wrote: ↑
Tue Jan 16, 2018 9:26 pm
So taking "s" as the size of the "item-on-ground" entity (plus a floating-point rounding-compensation factor of 0.01), it takes the fractional part of both x and y of checkVector and makes sure they're in the range s <= fractional_part <= 1-s. The addition of 1.0 ensures that fractional_part always ends up with a positive value in the range 0 <= x < 1.
Changing the size of the item-on-ground entity changes the math of how close to the edge of a tile an inserter's drop position is allowed to be.
Miniloader β€” UPS-friendly 1x1 loaders
Bulk Rail Loaders β€” Rapid train loading and unloading
Beltlayer & Pipelayer β€” Route items and fluids freely underground

Post Reply

Return to β€œModding help”