-
Notifications
You must be signed in to change notification settings - Fork 23
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
Getting a list of entity's components #125
Comments
Listing components is possible via Archetype. For example: for _, c := range someEntry.Archetype().Layout().Components() {
switch c.Id() {
case components.Position.Id():
data := components.Position.Get(someEntry)
// do serialization
} |
Is there a way to do this more generically? The use case: I'm adding a SyncComponent onto entities that need to be synced across the network, and then that sync component has an internal list of components to sync, so that SyncComponent specifies that (example) HealthComponent should be synced. I'm looking for a way to query the ECS for all this data, without necessarily knowing the concrete types ahead of time. |
Thanks for the clarification. I think we can add new API, for example: for _, c := syncComponents {
world.Each(c, func(data any) {
// process each data
})
} What do you think? |
That could work, as long as the type information is available somehow |
Would you mind sharing why you need type information? It's just a thought experiment, but there could be other approach if we don't want to deal with type SyncAction struct{}
func handleSyncHealthHandler(action *SyncAction, healthData *components.HealthData) {
}
world.RegisterHandler(serializeHealth)
world.Dispatch(&SyncAction{}, component.Health) // Call handleSyncHealthHandler handler for all entities' health data |
My use case is that I want to be able to just |
The handler / dispatch concept seems fairly powerful as a general feature, so maybe it should be implemented regardless! I'm unsure as to the best way to model a networked ECS, so I'm happy to receive and consider your suggestions. I've looked at https://docs.rs/bevy_replicon/latest/bevy_replicon/ which lets you sync by simply marking an entity for replication. |
I thought that the replicon feature for Beby might be a bit overwhelming to implement in Donburi right now. Below is an idea of how we will be able to handle serialization and deserialization with a new // server
type Health struct {}
func (h Health) Serialize() ([]byte, error) {}
func DeserializeHealth(data []byte) (Health, error) {}
components.New(Health).SetDeserializer(DeserializeHealth)
donburi.Add(someEntry, sync.Serializable, sync.Config{
Components: donburi.Component[]{components.Health}
})
data, err := sync.Serialize(someEntry)
// client
err := sync.Sync(someEntry, data) |
I agree that donburi should not implement a sync feature, but a way to acquire the components and their data is needed for my library on top of donburi. I am not sure about this example, as it depends on the actual implementations. |
Do you have some thoughts or ideas on the API design apart from above examples? Implementation wouldn't be too hard regardless the API design. |
This seems to be the most flexible, along with the world.Each idea, however I need to be able to access the Entity id in order to bundle the components that should be synced into a package to network. |
@im-gin Right. Let's fix the parameter to something like this. package dispatch
type Action[T any, U any] struct {
Entity donburi.Entity
Action *T,
Data *U
} Usage: type SyncAction struct{}
func handleSyncHealthHandler(action *dispatch.Action[SyncAction, *components.HealthData]) {
// ...
}
world.RegisterHandler(serializeHealth)
world.Dispatch(&SyncAction{}, component.Health) |
I agree, let's try something like this, unless you have any better ideas! |
I have no better idea than this right now. I'd very much welcome a contribution if anyone wants to work on it. |
I have been looking at possible other ways to implement my ideal code pattern. |
Thanks! I think we can use a similar pattern to the one used in the For reference, here are the relevant interfaces for Valuer: https://pkg.go.dev/database/sql/driver#Valuer |
I was able to get my implementation to work as desired by adding this method to entry.go: func GetComponents(e *Entry) []any {
archetypeIdx := e.loc.Archetype
s := e.World.StorageAccessor().Archetypes[archetypeIdx]
cs := s.ComponentTypes()
var instances []any
for _, ctyp := range cs {
instancePtr := e.Component(ctyp)
componentType := ctyp.Typ()
val := reflect.NewAt(componentType, instancePtr)
valInstance := reflect.Indirect(val).Interface()
instances = append(instances, valInstance)
}
return instances
} (As well as implementing |
Ah I see what you need to do now. Looks good to me. |
I'm trying to build a world state packet for server-client ECS, and need to build a list of entities with their component data, and I'm looking for a way to do that, but donburi does not seem to have an API I can use to query arbitrary component data, or just to serialize an entity
The text was updated successfully, but these errors were encountered: