Scripting: How Can Scripts Interact With Non-Scripted Components?

(Zicklag) #1

I’m splitting this off as a separate topic from Scripting: What Do We Need to Get There to try and keep the thread from getting too scrambled.

@Moxinilian Do you have any idea how we can expose non-scripted components to scripts. For example, how would we expose the Amethyst built-in Transform component to a script?

Right now all of the ideas for scripted components use a buffer to store the component data, but with the built-in components, they are going to be in memory in the Rust repr which is unpredictable and unusable from scripts. Converting them to a representation compatible with scrips would almost surely require copying.

It seems like you would have to make any components that you want to be acessible to scripts stored in buffers in the same way that components created by scripts would be. That would mean that we would have to recreate ( or otherwise re-configure ) any of the core Amethyst systems that you want to use in a scripted game as scripts instead of built-in systems.

Other than having set up the existing core Amethyst systems differently for a scripted game, as long as there are no performance disadvantages to our scripting solution, it probably wouldn’t be a problem to have them as scripts instead of build-in systems. I’m not sure. :man_shrugging:

(Théo Degioanni) #2

I don’t have a lot of time right now, but basically make it repr(C) and expose it through FFI. We’ll just accept to use C representation for those components which is perfectly fine.

1 Like
(Zicklag) #3

That would work, but then we are back to the fact that repr(C) has to be converted to the right endianness before saving or sending over the network, which is a performance hit ( maybe slight, but still ). If it was the only good way to do it, then that would be fine, but it would be better if we didn’t have to handle internal and external components differently from each-other.

Here’s my thought, if you were to store all components, Amethyst built-in and scripted components, using the Cap’nProto memory layout, all of the components could be zero-copy serialized and deserialized for transfer across the network or storage on disk. The entire game state could transfered or stored as efficiently as possible.

This would mean setting up the core Amethyst systems as “scripts” essentially, but if there is no performance disadvantage that would be perfectly fine.

Here’s some pros and cons as far as I see.


  • Maximum efficiency for saving games and networking.
  • Unified handling of built-in and scripted components.
  • You could potentially configure the Amethyst engine by selecting which core “scripts” to include with what config without having to recompile Amethyst, which would aid in rapid prototyping.
  • You could download a pre-built version of Amethyst for your platform and get right to making a game by writing scripts in any language supporting Cap’nProto.


  • All built-in amethyst systems would have to be reconfigured as scripts which would mean some work and refactoring the current codebase.

It might be a big deal to refactor all of the Amethyst systems as scripts, so I can understand if that was out of the question for Amethyst, but I might still experiment with the design for Arsenal. I could test out without making any changes to Amethyst.

What do you think of the idea?

(Théo Degioanni) #4

I don’t understand the focus on sending things over the network? Surely this is a very convoluted solution for something that is barely ever used anymore like big endian.

Regarding the pros you provide:

  • You might want to talk to the networking team, but I am pretty sure this is not necessary to have excellent network sync. Regarding saving, I don’t think the bottleneck would be here.
  • Well, right. Unless you use static collapsing for scripting components at deployment, in which case it only becomes a development-time backend, with the trade-offs we can accept there.
  • How does Cap’n’Proto bring any advantage on that aspect?
  • Same as above.

But yes, I am pretty sure this is quite out of the question for Amethyst itself. Not only is it a lot of work, but it’s also incompatible with raw native programming I believe.

(Zicklag) #5

Reasonable point. I did forget that you wouldn’t have to do a conversion if the system was already little endian.

I was thinking that you could only dynamically include/exclude portions of Amethyst core if they were scripts themselves. I guess you could, though, if you read from a config file at startup you could selectively include different Amethyst components when the game starts.

So, it may not make much sense. I wanted to bring it up because I like unifying the way things are handled as much as possible. I like to come up with the cleanest model that can handle all of the requirements, without having to make specific handling for edge-cases. Handling everything as a script seems like a theoretically clean solution in my mind, but especially with all of the work already done, it probably isn’t a good idea in this context.

(Théo Degioanni) #6

I mean I am still unsure Cap’n’Pro is worth it considering we could just as well use C interfaces. That would be unified for sure. The build step in the language driver would not even have to be aware whether a type is from the engine itself or is a custom script component.

(Zicklag) #7

OK, that should be good. I’m still very new to lower-level programming, C interfaces and such, so I’m having some trouble putting together the pieces in my head. I appreciate the help and discussion. :slightly_smiling_face:

(Théo Degioanni) #8

If you want to have a call about it to get more of the intuition behind it feel free to contact me anywhere.

1 Like
(Zicklag) #9

Awesome, thanks.