Page 1 of 1
Disallow mining tile from under an entity
Posted: Sun Aug 05, 2018 10:01 am
by Gergely
If I use a mod like the
Platform mod that adds
removable landfill tiles, I can kill players and destroy vehicles if I mine a platform tile from under it. Currently the modding interface offers no solution to this problem.
I request the following:
- A generic method to forbid mining tiles if the tile underneath them would collide with the entities on the tile. This could be a flag on the tile prototype or something different.
Re: Disallow mining tile from under an entity
Posted: Sat Aug 11, 2018 7:07 am
by Rseding91
If I can find a way to implement this that doesn't negatively impact performance in the base game I'll add i t.
Re: Disallow mining tile from under an entity
Posted: Tue Aug 28, 2018 3:09 pm
by mrvn
Isn't that similar to mining rails when a train in on them?
Re: Disallow mining tile from under an entity
Posted: Tue Aug 28, 2018 8:51 pm
by Gergely
mrvn wrote:Isn't that similar to mining rails when a train in on them?
No, rails are entities and they reference the train that is on them.
Tiles however don't know if there is an entity on top of them while they are being removed. The entities on mined tiles die as soon as they are ticked when it's already too late to undo the tile removal.
In other words, rails are more self-conscious.
So that's why implementing this can potentially impact the performance. When removing a single tile, all entities inside the chunk and neighboring chunks might have to be checked.
Re: Disallow mining tile from under an entity
Posted: Mon Sep 17, 2018 7:36 am
by mrvn
Gergely wrote: Tue Aug 28, 2018 8:51 pm
mrvn wrote:Isn't that similar to mining rails when a train in on them?
No, rails are entities and they reference the train that is on them.
Tiles however don't know if there is an entity on top of them while they are being removed. The entities on mined tiles die as soon as they are ticked when it's already too late to undo the tile removal.
In other words, rails are more self-conscious.
So that's why implementing this can potentially impact the performance. When removing a single tile, all entities inside the chunk and neighboring chunks might have to be checked.
Do I understand this right? Every tick every entity checks the tiles it stands on and if they conflict with what the entity requires then the entity dies?
That sounds like a horrible design.
Re: Disallow mining tile from under an entity
Posted: Mon Sep 17, 2018 10:23 am
by Rseding91
mrvn wrote: Mon Sep 17, 2018 7:36 am
Do I understand this right? Every tick every entity checks the tiles it stands on and if they conflict with what the entity requires then the entity dies?
That sounds like a horrible design.
No.
When a tile is changed the game scans the entities on the tile and destroys any that collide with the new tile.
The problem with "don't mine if any collide" is it has to then scan every time the mining operation starts in addition to every time it finishes.
Re: Disallow mining tile from under an entity
Posted: Mon Sep 17, 2018 1:12 pm
by mrvn
Rseding91 wrote: Mon Sep 17, 2018 10:23 am
mrvn wrote: Mon Sep 17, 2018 7:36 am
Do I understand this right? Every tick every entity checks the tiles it stands on and if they conflict with what the entity requires then the entity dies?
That sounds like a horrible design.
No.
When a tile is changed the game scans the entities on the tile and destroys any that collide with the new tile.
The problem with "don't mine if any collide" is it has to then scan every time the mining operation starts in addition to every time it finishes.
Huh? Why?
You already have the code that scans entities and destroys them. But before you destroy the entity you add:
Code: Select all
if (dont_destroy) return false; // mining would destroy building
Seems like a trivial change. No need to scan twice. Trying to mine tiles that destroy entities would simply fail. Like mining a chest when you don't have enough space for the contents.
Note: You can't reliably scan before mining starts because a second player might place something while the player mines and then mining should fail (at the end). So you might as well have it fail at the end in all cases if scanning takes too much time.
Re: Disallow mining tile from under an entity
Posted: Wed Sep 19, 2018 7:01 am
by Rseding91
Mining a tile can destroy multiple entities which means it can't just "stop mining the tile if it found 1 entity while destroying that can't be destroyed" since it could have destroyed others already.
Re: Disallow mining tile from under an entity
Posted: Wed Sep 19, 2018 9:27 pm
by Gergely
I have a headache imagining how ... slick that might be. Would be a shame to ruin it.
Here's what I have gathered so far. Correct me if I'm wrong:
- The destroy operation for entities is a 1 step operation which means after a single method call, the entity forcefully ceases to exist no matter which part of the main loop the method was called from.
- The entities are in a one way only linked list (and likely are the links themselves) which means you can only destroy them during an iteration of the list.
- You figured iterating the list twice instead of once would largely impact the performance of bots that place modded water fill. I don't yet know how. Would that really impact the performance so much that it is no longer worth this feature?
I know this isn't simple, but deconstructing tiles are the most effective way to kill players (even invulnerable players!!!) in modded Factorio.
Re: Disallow mining tile from under an entity
Posted: Thu Sep 20, 2018 9:42 am
by mrvn
Rseding91 wrote: Wed Sep 19, 2018 7:01 am
Mining a tile can destroy multiple entities which means it can't just "stop mining the tile if it found 1 entity while destroying that can't be destroyed" since it could have destroyed others already.
I thought the idea was to not allow mining if it would destroy entities. So the first one you find that must be destroyed you stop and the mining fails.
So there would never be any "destroyed others already" case.
But even your case seems rather simple. Assuming entities overlap and some can be destroyed and other not. You first scan the area for any entities that may be destroyed and add them to a list. If you don't find any conflicts in the area the mining will succeed and you destroy all the entities in the list.
It means having 2 loops but the second will only loop over entities that need to be destroyed, not over an area that could cover multiple chunks. The only real extra cost is allocating and building the list. But in all but exceptional cases the list would only have at most one element. Generally entities do not overlap and players tend to not alter tiles destructively below entities except by accident.
Re: Disallow mining tile from under an entity
Posted: Fri Sep 21, 2018 8:29 am
by Gergely
mrvn wrote: Thu Sep 20, 2018 9:42 amBut even your case seems rather simple. Assuming entities overlap and some can be destroyed and other not. You first scan the area for any entities that may be destroyed and add them to a list. If you don't find any conflicts in the area the mining will succeed and you destroy all the entities in the list.
Ummm....
How exactly do you imagine "adding them to a list" would work memory wise if this is supposed to be extremely optimized?
Re: Disallow mining tile from under an entity
Posted: Tue Sep 25, 2018 8:17 am
by mrvn
Gergely wrote: Fri Sep 21, 2018 8:29 am
mrvn wrote: Thu Sep 20, 2018 9:42 amBut even your case seems rather simple. Assuming entities overlap and some can be destroyed and other not. You first scan the area for any entities that may be destroyed and add them to a list. If you don't find any conflicts in the area the mining will succeed and you destroy all the entities in the list.
Ummm....
How exactly do you imagine "adding them to a list" would work memory wise if this is supposed to be extremely optimized?
Code: Select all
std::vector to_be_destroyed(4);
for(entities_in_area) {
if (should_be_destroyed(entity))
to_be_destroyed.push_back(entity);
}
As said the normal case would be at most 1 entity since they normally do not overlap. The vector starts of with space for 4. If more than 4 entities overlap the tile and need to be destroyed then the std::vector will allocate memory as needed in amortized O(1) cost per entity.
Note: I got what you mend by entities that can be destroyed and ones that must not, I think. Did you mean that there might be decorations in the way as well as actual player placed entities? Decoration would be fine to destroy but player based entities would not.
Re: Disallow mining tile from under an entity
Posted: Tue Sep 25, 2018 1:19 pm
by Gergely
mrvn wrote: Tue Sep 25, 2018 8:17 amCode: Select all
std::vector to_be_destroyed(4);
for(entities_in_area) {
if (should_be_destroyed(entity))
to_be_destroyed.push_back(entity);
}
As said the normal case would be at most 1 entity since they normally do not overlap. The vector starts of with space for 4. If more than 4 entities overlap the tile and need to be destroyed then the std::vector will allocate memory as needed in amortized O(1) cost per entity.
Aaaaaoooohhh...

*Pfsshh*
Are you serious right now?

Or am I just an idiot for not having thought of that?
Either way, building that list takes up at least n+n-1 "
space" in memory where
n is the number of entities to be destroyed. (Unless n ≤ 4 of course.) Let
Rseding91 be the judge of that.
Re: Disallow mining tile from under an entity
Posted: Tue Sep 25, 2018 2:59 pm
by mrvn
An std::vector<Entity*> takes c+8*n space where c is some constant like 32 and n is the number of entity pointers. I considered using a linked list or something that is easier to extend but that would require a next and data pointer, so 16*n, and one allocation per item. And I really don't expect there to be any entities in the majority of cases and a std::vector will do fewer calls to new().
I imagine a worst case could be like this:
- the tile has some decoration
- there is an explosion crater (does that exclude decorations? Is that a decoration?)
- some scrap pieces from an explosion are lying around
- there are 4 items on the tile
- there is a building encroaching that tile
Even then that should be a trivial overhead.
@rseeding91: What's your take on this? Does that make sense?
Re: Disallow mining tile from under an entity
Posted: Sat Sep 29, 2018 8:10 pm
by Gergely
Careful!
std:vector needs to re-allocate it's array a lot during which it takes up almost double the space.
This might make linked list a better choice because it would be faster, though less efficient on memory.
Re: Disallow mining tile from under an entity
Posted: Wed Nov 14, 2018 2:53 pm
by mrvn
Gergely wrote: Sat Sep 29, 2018 8:10 pm
Careful!
std:vector needs to re-allocate it's array a lot during which it takes up almost double the space.
This might make linked list a better choice because it would be faster, though less efficient on memory.
Note the part about the vector/list being small and pre-allocating it to fit 99.99% of all cases.
Re: Disallow mining tile from under an entity
Posted: Tue Apr 16, 2019 11:58 am
by Gergely
I wonder if it's possible to do now...