-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add entity tag support #119
Conversation
Looks great for a quick draft! One thing I'm concerned about is type safety. There's no difference between regular components and tags which could prevent you from doing bad things. For example you could accidentally add a Tag object to an entity, then unset that tag and by doing so cause an invalid state where the ComponentsHolder has the Tag object but the entity's mask does not signal having it. |
@LobbyDivinus: I updated the draft now. Documentation is still missing. It is now possible to also use enums as tags (thank you for your fork, that gave me the idea on how to solve it ;) ). And I also included typealias for tags to make the code easier to read and understand imo. About type-safety: I had a similar concern and tried a few things but I think we are lucky. You get compile errors when you do something wrong because a tag does not extend Here is the current test that shows the syntax and compile errors: data object Visible : EntityTag()
class TestTagSystem(var ticks: Int = 0) : IteratingSystem(family { all(Visible) }) {
override fun onTickEntity(entity: Entity) {
++ticks
}
}
enum class TestTags : EntityTags by entityTagsOf() {
PLAYER, COLLISION
}
class EntityTagTest {
@Test
fun testTagAssignment() {
val world = configureWorld {}
val entity = world.entity { it += Visible }
with(world) {
assertTrue(entity[Visible])
// entity.getOrNull(Visible) // <- compile error because Visible does not extend Component
// val cmp : Visible = entity[Visible] // <- compile error because Visible does not extend Component and therefore 'cmp' must be of type Boolean
// assertTrue(Visible in entity) // <- compile error because Visible does not extend Component
// assertTrue(entity has Visible) // <- compile error because Visible does not extend Component
// assertTrue(entity hasNo Visible) // <- compile error because Visible does not extend Component
entity.configure {
it -= Visible
}
assertFalse(entity[Visible])
}
}
@Test
fun testTagSystem() {
lateinit var testSystem: TestTagSystem
val world = configureWorld {
systems {
add(TestTagSystem().also { testSystem = it })
}
}
val entity = world.entity { it += Visible }
world.update(1f)
assertEquals(1, testSystem.ticks)
testSystem.ticks = 0
with(world) { entity.configure { it -= Visible } }
world.update(1f)
assertEquals(0, testSystem.ticks)
}
@Test
fun testEnumTags() {
assertNotEquals(TestTags.PLAYER.id, TestTags.COLLISION.id)
assertNotEquals(Visible.id, TestTags.PLAYER.id)
assertNotEquals(Visible.id, TestTags.COLLISION.id)
val world = configureWorld {}
val entity = world.entity { it += TestTags.PLAYER }
with(world) {
assertTrue(entity[TestTags.PLAYER])
entity.configure { it -= TestTags.PLAYER }
assertFalse(entity[TestTags.PLAYER])
}
}
} |
Ah, with that forget about my concerns. This looks quite polished and covers all of what I'd expect tags to do. |
* fix snapshot functionality for tags
Wow, that took quite some time to verify it in my three example games because a lot of things got actually broken haha. Luckily I drank an energy drink today so going the extra mile for my community and work until midnight was not an issue! To summarize it:
@LobbyDivinus: Would be great if you can check my changes and review them and ideally also try this branch in your local game and experiment a little bit with it. |
* add plusAssign for list of tags
Thank you, that was quick and it looks great so far! I will report back once I've had a chance to play with it more thoroughly. I don't use snapshotting though so I wouldn't be able to notice issues there. |
Sorry for the late reply, I did play a bit more with it and integrated it into may project and it all works as expected. There seems to be no noticable difference in performance but definitely in memory use. Thanks again for adding this one. |
No worries, I just wanted to merge it today to have it officially in the snapshot version. I want to release 2.5 when Kotlin 1.9.20 is out for a week or two. Then this feature will be officially in Fleks stable versions 🙂 Thanks again for the suggestion and help with the enum class tags! |
Sounds great. I really appreciate this extension and the fast way you respond to feature requests. |
PR for #118 (WIP)
@LobbyDivinus : this is a very quick draft from my side. Basically, I just added two additional entity extension functions which should be sufficient to support tags. You can see the usage in the Test class.
The downside of this approach is that tag ids are part of component ids, meaning that they will be part of the normal component mask and "waste" space in the BitArray.
I haven't had a look at your fork yet. Will do that tomorrow!
TODO:
UniqueId
interface but seems to have no extra overhead or impactEntityComponentContext
can be refactored a little bit to avoidcomponentService.world.entityService
calls