Open AnderWoche opened 2 weeks ago
I made MutableEntityBag to an interface, and two implementations for it.
Ref #156
thank you for the contribution - looks good to me! I wonder if the list version can be simplified with Kotlin's delegation? Maybe you can write:
class ListMutableEntityBag(
@PublishedApi
internal val list: MutableList<Entity>
) : MutableEntityBag by list {
But I am not sure if the delegation mechanism is smart enough to detect that the methods are the same. I guess they'd need a common interface and I am not sure if there is one ;)
by not working
In the List implementation i have this one:
ListMutableEntityBag.kt
/**
* Resizes the bag to fit in the given [capacity] of [entities][Entity] if necessary.
*/
override fun ensureCapacity(capacity: Int) {
throw NotImplementedError("Not Supported")
}
/**
* Resets [size] to zero, clears any [entity][Entity] of the bag, and if necessary,
* resizes the bag to be able to fit the given [capacity] of [entities][Entity].
*/
override fun clearEnsuringCapacity(capacity: Int) {
throw NotImplementedError("Not Supported")
}
yout are fine with this?
I was not aware of a NotImplementedError but imo it makes sense if the class does not have that.
Of course one would ask why the interface has it but the implementation doesn't. That is for sure not clean. Can we maybe remove it from the interface and just use the array implementation internally in Fleks? Need to have a look when I am at a computer again 😅
Out of curiosity: how do you actually use the list implementation? I mean how do you get entities in it?
My usecase is this:
class ChildrenComponent : Component<ChildrenComponent> {
val children = ListMutableEntityBag(ArrayList(8)) // on remove the order stays the same thats for me important.
override fun World.onRemove(entity: Entity) {
children.forEach { child ->
child.configure {
it -= ParentComponent
}
}
}
override fun type() = ChildrenComponent
companion object : ComponentType<ChildrenComponent>()
}
!!!! I have a new idea:
Why does the MutableEntityBag has its own interface?
couldn't we just replace the
or maybe other interface like MutableCollection
If there is an interface that contains all those methods then sure, would be better to use it.
I still don't get in your example why you are not using a normal list? What is the advantage of using an entitybag which is actually a list in the background? 😅
I have just looked it up right now, I wouldn't need it. (because I have reprogrammed it again) but before it was like this:
private fun validate(parent: Entity?, children: EntityBag) {
// validatre children
children.forEach { newParent ->
val newChildren = newParent.getOrNull(ChildrenComponent)?.children
if (newChildren != null) {
validate(newParent, newChildren)
}
}
}
and i wantet to start the method like:
override fun onTick() {
super.onTick()
validate(null, family.entities) // The family.entities has forced me to use the interface everywhere
}
The Problem was that the fast MutableEntityBag implementation had no sorting if you have these entities: 1 2 3
and you remove 1
the oder was:
3 2
and not:
2 3
thats why i needed a "sorted" entity bag
Ah okay now I get it. Well, a bag is a special data structure which doesn't care about order and is therefore a very fast and efficient way to add/remove elements. It is basically a dynamically growing array without the overhead of other data structures.
I will test if we can use the collection interface because e.g. all extra functions like .all {} would be included automatically
Okay i have a new idea:
Maybe it is enough to implement only the Iterable interace
Ok pls take a look at this.
I have decided that the Collection interface makes more sense.
if its okay i going to write some tests
also take a look at the .forEach funktion now there will be the iterator i think it should be fast anyway couse the iterator is reused. But can you do a performance test for safety?
Take a Look at the _EntityBag.kt
The normal extension functions often return a list instead of an EntityBag. where you originally returned an EntityBag, I have added the function.
Thank you for your effort. I am currently on holiday for three weeks and don't have access to a computer, sorry.
I will have a look when I am back.
Regarding performance test: there is a Gradle task called jvmBenchmarks if I remember correctly. That should work for you as well.
There is also a manual.kt file where you can run benchmarks. However, you should run them a few times and take an average value.
For the Gradle benchmarks you don't need to do that but they also run for a longer time.
@AnderWoche: I just had a look now and that looks like way too many changes for what we are trying to achieve here. Also, the iterator seems to be limited to only two nested iterations? In general, it does not look like a clean solution imo.
I do like the Collection interface for the EntityBag. I will have a look at that when I am back from my holiday and have more time.
In the meanwhile - you already solved your initial problem in a different way, right? Or is there an easier "quick win" that we can introduce to help you?
edit: the Collection interface inherits from Iterable which has the iterator() method, I see. Then I don't want to go that route because initially the bag was just a helper collection to speed up certain parts of Fleks and it does not require an iterator and imo it does not make sense because it is basically a dynamic array and an array also has no iterator?
edit2: would a simple toList() method on an EntityBag help you? Or did you anyway solve it differently now and there is no need for it?
How i can link this to a Issue?