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

refactor: Make game data pluggable #691

Merged
merged 4 commits into from May 14, 2018

Conversation

Projects
None yet
5 participants
@Rhuagh
Member

Rhuagh commented May 1, 2018

Remove Dispatcher from Application, and add a pluggable generic type.
Add a direct replacement for the old game data, featuring only a Dispatcher.
Make the states take a new StateData type, containing references to World and pluggable game data.
Move responsibility for doing system dispatch to the states.

Opening this early to get feedback.

Resolves #576


This change is Reviewable

@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 1, 2018

Collaborator

I'll need a more complex example to really get the feel of it.
Maybe an example with:
-Global systems
renderer,input,ui,assets
-StateLoading
waits for assets to be all loaded, shows a ui specific to this state (loading ui), which get removed automatically when changing state (because when you switch you lose this World)
-StateGame
simple ui showing the loaded asset

The prototype looks good ;)

Collaborator

jojolepro commented May 1, 2018

I'll need a more complex example to really get the feel of it.
Maybe an example with:
-Global systems
renderer,input,ui,assets
-StateLoading
waits for assets to be all loaded, shows a ui specific to this state (loading ui), which get removed automatically when changing state (because when you switch you lose this World)
-StateGame
simple ui showing the loaded asset

The prototype looks good ;)

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 2, 2018

Member

The World is not replaced, it's just the Dispatcher that's been replaced with a generic type.

Member

Rhuagh commented May 2, 2018

The World is not replaced, it's just the Dispatcher that's been replaced with a generic type.

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 2, 2018

Member

I was thinking of maybe adding a loading state to the renderable example, since some of those assets take a while to load in debug mode.

Member

Rhuagh commented May 2, 2018

I was thinking of maybe adding a loading state to the renderable example, since some of those assets take a while to load in debug mode.

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 2, 2018

Member

This is basically my stab at #576.

Because we use World for a lot of things internally in Application and a lot of the core, my proposal is basically to keep the core World in place, and simply abstract away the Dispatcher, and any "extra" data that the user might want to keep centrally. The naming of the different types could use improvements, but the core concept is solid I believe.

Member

Rhuagh commented May 2, 2018

This is basically my stab at #576.

Because we use World for a lot of things internally in Application and a lot of the core, my proposal is basically to keep the core World in place, and simply abstract away the Dispatcher, and any "extra" data that the user might want to keep centrally. The naming of the different types could use improvements, but the core concept is solid I believe.

@Rhuagh Rhuagh requested review from jojolepro, Xaeroxe and torkleyy May 2, 2018

@Xaeroxe

Xaeroxe approved these changes May 3, 2018

I was pleasantly surprised with how this turned out.

image

LGTM!

@Xaeroxe

This comment has been minimized.

Show comment
Hide comment
@Xaeroxe

Xaeroxe May 3, 2018

Member

I think it might be a good idea to add a chapter to the book called Advanced Game Architecture that shows how to use multiple dispatchers in a custom GameData structure.

Member

Xaeroxe commented May 3, 2018

I think it might be a good idea to add a chapter to the book called Advanced Game Architecture that shows how to use multiple dispatchers in a custom GameData structure.

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 3, 2018

Member

I was planning on creating an example atleast once I get some feedback on the basic design :)

Member

Rhuagh commented May 3, 2018

I was planning on creating an example atleast once I get some feedback on the basic design :)

@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 3, 2018

Collaborator

I'll re-review it soon.

Collaborator

jojolepro commented May 3, 2018

I'll re-review it soon.

@Aceeri

Aceeri approved these changes May 4, 2018

@torkleyy

I like it, thanks for your work! A chapter would really be helpful, I'm not sure I understand how all the *Data types interact exactly.

amethyst_animation/src/util.rs
- controls.entry(entity).unwrap().or_insert_with(AnimationControlSet::default)
+ controls
+ .entry(entity)
+ .unwrap()

This comment has been minimized.

@torkleyy

torkleyy May 4, 2018

Member

This should not unwrap but return the error.

@torkleyy

torkleyy May 4, 2018

Member

This should not unwrap but return the error.

This comment has been minimized.

@Rhuagh

Rhuagh May 4, 2018

Member

That's a known (and reported issue), yes, will fix that in a separate PR as it changes the API.

@Rhuagh

Rhuagh May 4, 2018

Member

That's a known (and reported issue), yes, will fix that in a separate PR as it changes the API.

@@ -0,0 +1,240 @@
+use std::sync::Arc;

This comment has been minimized.

@torkleyy

torkleyy May 4, 2018

Member

Missing top-level docs

@torkleyy

torkleyy May 4, 2018

Member

Missing top-level docs

@jojolepro

That looks good, but since this is a really big breaking change, I have a few questions.

Main one:
Is it possible to have a GameData that has:
global_dispatch
state_specific_dispatch
where the state_specific_dispatch is created during a State start() method?

Basically, sometimes you want to have systems run only for some states (like in this example), but you want the state to conditionally set the systems. Also, creating it in the start (or similar) method makes it easy to find the relation between State and state_specific_dispatch.

I don't want to have
GameData
-global_dispatch
-state1_dispatch
-state2_dispatch
-state3_dispatch
-state4_dispatch
Especially since sometimes creating a System might need data loaded by a previous state. For example, a System specific to GameMode1State would require a Handle loaded by LoadingState.

amethyst_ui/src/layout.rs
- (entities, mut locals, parents, anchors, stretches, screen_dim, hierarchy): Self::SystemData,
-){
+ fn run(&mut self, data: Self::SystemData) {
+ let (entities, mut locals, parents, anchors, stretches, screen_dim, hierarchy) = data;

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

Any reason for this?

@jojolepro

jojolepro May 4, 2018

Collaborator

Any reason for this?

This comment has been minimized.

@Rhuagh

Rhuagh May 4, 2018

Member

Formatting. The previous code complained about too long row every time I ran rustfmt, and I got tired of it.

@Rhuagh

Rhuagh May 4, 2018

Member

Formatting. The previous code complained about too long row every time I ran rustfmt, and I got tired of it.

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

👍

@jojolepro

jojolepro May 4, 2018

Collaborator

👍

examples/game_data/README.md
@@ -0,0 +1,5 @@
+# Renderable Example

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

s/Renderable/Game Data/

@jojolepro

jojolepro May 4, 2018

Collaborator

s/Renderable/Game Data/

examples/game_data/game_data.rs
+use amethyst::{DataInit, Error, Result};
+use rayon::ThreadPool;
+
+pub struct GameData<'a, 'b> {

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

I got really really confused, because this custom GameData has the same name has amethyst::GameData. I couldn't figure out why this one had two dispatchers and the other one had one.

Please rename it to CustomGameData.

@jojolepro

jojolepro May 4, 2018

Collaborator

I got really really confused, because this custom GameData has the same name has amethyst::GameData. I couldn't figure out why this one had two dispatchers and the other one had one.

Please rename it to CustomGameData.

examples/game_data/main.rs
@@ -0,0 +1,583 @@
+//! Demonstrates how to load renderable objects, along with several lighting

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

I doubt it!

@jojolepro

jojolepro May 4, 2018

Collaborator

I doubt it!

examples/game_data/main.rs
+//! Demonstrates how to load renderable objects, along with several lighting
+//! methods.
+//!
+//! TODO: Rewrite for new renderer.

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

hmmmmmmmm :P

@jojolepro

jojolepro May 4, 2018

Collaborator

hmmmmmmmm :P

examples/game_data/main.rs
+
+mod game_data;
+
+struct DemoState {

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

I think having all the lighting stuff makes the example way more complicated than how it needs to be. Its harder to really spot what GameData does when there is so much unrelated code. A simple rotating cube with a fixed camera is all you would need I think.

@jojolepro

jojolepro May 4, 2018

Collaborator

I think having all the lighting stuff makes the example way more complicated than how it needs to be. Its harder to really spot what GameData does when there is so much unrelated code. A simple rotating cube with a fixed camera is all you would need I think.

This comment has been minimized.

@Rhuagh

Rhuagh May 4, 2018

Member

The renderable example is the only one where loading is slow enough to actually warrant a Loading state, that's why I chose it.

@Rhuagh

Rhuagh May 4, 2018

Member

The renderable example is the only one where loading is slow enough to actually warrant a Loading state, that's why I chose it.

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

You could keep the .obj loading, which is the slow part, but remove the lights. If not then its fine.

@jojolepro

jojolepro May 4, 2018

Collaborator

You could keep the .obj loading, which is the slow part, but remove the lights. If not then its fine.

examples/game_data/main.rs
+ data.data.update(&data.world, true);
+ match self.progress.as_ref().unwrap().complete() {
+ Completion::Failed => {
+ println!("Failed loading assets");

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

printerr! or error!

@jojolepro

jojolepro May 4, 2018

Collaborator

printerr! or error!

This comment has been minimized.

@Rhuagh

Rhuagh May 4, 2018

Member

Didn't see a need to pull in an extra crate for an example.

@Rhuagh

Rhuagh May 4, 2018

Member

Didn't see a need to pull in an extra crate for an example.

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

printerr! then?

@jojolepro

jojolepro May 4, 2018

Collaborator

printerr! then?

This comment has been minimized.

@Rhuagh

Rhuagh May 4, 2018

Member

printerr? Not a part of core rust from what I know ?

@Rhuagh

Rhuagh May 4, 2018

Member

printerr? Not a part of core rust from what I know ?

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

Ya sorry its "eprintln!" actually :P

@jojolepro

jojolepro May 4, 2018

Collaborator

Ya sorry its "eprintln!" actually :P

examples/game_data/main.rs
+ .with_pass(DrawShaded::<PosNormTex>::new())
+ .with_pass(DrawUi::new()),
+ );
+ let game_data = GameDataBuilder::default()

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

Games don't only have a base and a running state. There should be a way to provide multiple systems that are specific to each of the states. Those systems should be added during the state start function, to allow for better logic locality.

@jojolepro

jojolepro May 4, 2018

Collaborator

Games don't only have a base and a running state. There should be a way to provide multiple systems that are specific to each of the states. Those systems should be added during the state start function, to allow for better logic locality.

This comment has been minimized.

@Rhuagh

Rhuagh May 4, 2018

Member

Ofc not, but I'm not about to write a whole game in a single example, and this example is for demonstrating a custom game data implementation, not teach people how to structure a game code wise.

@Rhuagh

Rhuagh May 4, 2018

Member

Ofc not, but I'm not about to write a whole game in a single example, and this example is for demonstrating a custom game data implementation, not teach people how to structure a game code wise.

+(
+ fullscreen: false,
+ multisampling: 0,
+ title: "Renderable Example",

This comment has been minimized.

@jojolepro

jojolepro May 4, 2018

Collaborator

Renderable again

@jojolepro

jojolepro May 4, 2018

Collaborator

Renderable again

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 4, 2018

Member

It's a generic type without bounds, you can put anything you like in it. Data would be in the World though, so there's no need to "share" that. Personally, I would put state specific dispatchers in the state, and not in a central location.

Member

Rhuagh commented May 4, 2018

It's a generic type without bounds, you can put anything you like in it. Data would be in the World though, so there's no need to "share" that. Personally, I would put state specific dispatchers in the state, and not in a central location.

@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 4, 2018

Collaborator

So GameData is global? If so I'm not sure what you can do with it that you couldn't do using Resource.

Collaborator

jojolepro commented May 4, 2018

So GameData is global? If so I'm not sure what you can do with it that you couldn't do using Resource.

@Xaeroxe

This comment has been minimized.

Show comment
Hide comment
@Xaeroxe

Xaeroxe May 4, 2018

Member

@jojolepro The main thrust of the PR is to permit people to access data in a way that isn't via specs. So this would be for people who don't even want a Resource.

Member

Xaeroxe commented May 4, 2018

@jojolepro The main thrust of the PR is to permit people to access data in a way that isn't via specs. So this would be for people who don't even want a Resource.

@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 4, 2018

Collaborator
  1. What would be the use case for that?
  2. Is it worth the added complexity?
Collaborator

jojolepro commented May 4, 2018

  1. What would be the use case for that?
  2. Is it worth the added complexity?
@Xaeroxe

This comment has been minimized.

Show comment
Hide comment
@Xaeroxe

Xaeroxe May 4, 2018

Member

@Rhuagh mentioned #576 in a comment on this PR (Maybe we should mention it in the opening PR description)

If we go to that issue some helpful context is present. Specifically this quote:

As more use cases for Amethyst begin to explore the virtues and limitations of
the current data architecture some hurdles are beginning to present themselves for
both optimization and flexibility. The current ECS design forces a specific way of
thinking that works for a lot of designs but requires use of anti-pattern solutions
in others. When examining how one would implement a dense voxel map idiomatically in
Amethyst general consensus is that each voxel should be an entity within
the system. While very simple this is not an optimal structure for chunked densely
packed Voxel data accessed by range query. Thus Voxel information would be
relegated to an outside resource with array data and a second ecs world containing
Voxel definitions. The access pattern of this second ecs is random and differs
greatly from the sequential access pattern of the primary ecs iterator.

Member

Xaeroxe commented May 4, 2018

@Rhuagh mentioned #576 in a comment on this PR (Maybe we should mention it in the opening PR description)

If we go to that issue some helpful context is present. Specifically this quote:

As more use cases for Amethyst begin to explore the virtues and limitations of
the current data architecture some hurdles are beginning to present themselves for
both optimization and flexibility. The current ECS design forces a specific way of
thinking that works for a lot of designs but requires use of anti-pattern solutions
in others. When examining how one would implement a dense voxel map idiomatically in
Amethyst general consensus is that each voxel should be an entity within
the system. While very simple this is not an optimal structure for chunked densely
packed Voxel data accessed by range query. Thus Voxel information would be
relegated to an outside resource with array data and a second ecs world containing
Voxel definitions. The access pattern of this second ecs is random and differs
greatly from the sequential access pattern of the primary ecs iterator.

@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 4, 2018

Collaborator

And how does Resource not solve this? My current plan for a voxel world involves having it as a resource and having Systems use that resource to create entities (optimised) that will end up getting rendered.

For me, this change is replicating what specs Resources is doing already.

Collaborator

jojolepro commented May 4, 2018

And how does Resource not solve this? My current plan for a voxel world involves having it as a resource and having Systems use that resource to create entities (optimised) that will end up getting rendered.

For me, this change is replicating what specs Resources is doing already.

@Xaeroxe

This comment has been minimized.

Show comment
Hide comment
@Xaeroxe

Xaeroxe May 4, 2018

Member

Yeah a Resource could be used for this. That means that to me there's one remaining major reason to merge this PR, and that is to facilitate types that aren't Any + Send + Sync.

Member

Xaeroxe commented May 4, 2018

Yeah a Resource could be used for this. That means that to me there's one remaining major reason to merge this PR, and that is to facilitate types that aren't Any + Send + Sync.

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 4, 2018

Member

You can't store systems in a resource.

Member

Rhuagh commented May 4, 2018

You can't store systems in a resource.

@Xaeroxe

This comment has been minimized.

Show comment
Hide comment
@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 4, 2018

Collaborator

That is a good argument. ;)
Okay then.

Collaborator

jojolepro commented May 4, 2018

That is a good argument. ;)
Okay then.

@Rhuagh Rhuagh changed the title from [WIP] refactor: Make game data pluggable to refactor: Make game data pluggable May 7, 2018

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 7, 2018

Member

Re-review if you can please.

Member

Rhuagh commented May 7, 2018

Re-review if you can please.

@jojolepro

Still not a fan of all the lighting stuff, but that's fine ;)

Thanks!

@torkleyy

This comment has been minimized.

Show comment
Hide comment
@torkleyy

torkleyy May 8, 2018

Member

When examining how one would implement a dense voxel map idiomatically in
Amethyst general consensus is that each voxel should be an entity within
the system.

Didn't we have that discussion before?

Member

torkleyy commented May 8, 2018

When examining how one would implement a dense voxel map idiomatically in
Amethyst general consensus is that each voxel should be an entity within
the system.

Didn't we have that discussion before?

@torkleyy

This comment has been minimized.

Show comment
Hide comment
@torkleyy

torkleyy May 8, 2018

Member

Reviewed 3 of 8 files at r1, 5 of 10 files at r2, 19 of 21 files at r3, 3 of 3 files at r4, 1 of 2 files at r6, 13 of 20 files at r7.
Review status: all files reviewed at latest revision, 10 unresolved discussions.


Comments from Reviewable

Member

torkleyy commented May 8, 2018

Reviewed 3 of 8 files at r1, 5 of 10 files at r2, 19 of 21 files at r3, 3 of 3 files at r4, 1 of 2 files at r6, 13 of 20 files at r7.
Review status: all files reviewed at latest revision, 10 unresolved discussions.


Comments from Reviewable

@torkleyy

LGTM

@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 9, 2018

Collaborator

I thought cfg!(target_os = "ios") didn't work?
anyway
Waiting for label change + build checks to merge. @Rhuagh

Collaborator

jojolepro commented May 9, 2018

I thought cfg!(target_os = "ios") didn't work?
anyway
Waiting for label change + build checks to merge. @Rhuagh

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 9, 2018

Member

I still need to add a chapter to the book, and I'm currently focusing on getting specs out.

Member

Rhuagh commented May 9, 2018

I still need to add a chapter to the book, and I'm currently focusing on getting specs out.

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 9, 2018

Member

Rebased, squashed, book chapter added. @Xaeroxe feel free to take over.

Member

Rhuagh commented May 9, 2018

Rebased, squashed, book chapter added. @Xaeroxe feel free to take over.

@Rhuagh Rhuagh added status: ready and removed status: working labels May 9, 2018

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 10, 2018

Member

Ready for final review @jojolepro @torkleyy @Xaeroxe

Member

Rhuagh commented May 10, 2018

Ready for final review @jojolepro @torkleyy @Xaeroxe

@jojolepro

This comment has been minimized.

Show comment
Hide comment
@jojolepro

jojolepro May 10, 2018

Collaborator

outside most of the day, I'll review tonight if I can, or tomorow

Collaborator

jojolepro commented May 10, 2018

outside most of the day, I'll review tonight if I can, or tomorow

@Xaeroxe

LGTM! bors r+

@Xaeroxe

This comment has been minimized.

Show comment
Hide comment
@Xaeroxe

Xaeroxe May 14, 2018

Member

err actually nevermind, I think this might fail on CI due to some new examples.

Member

Xaeroxe commented May 14, 2018

err actually nevermind, I think this might fail on CI due to some new examples.

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 14, 2018

Member

bors r=Xaeroxe,torkleyy,jojolepro

Member

Rhuagh commented May 14, 2018

bors r=Xaeroxe,torkleyy,jojolepro

bors bot added a commit that referenced this pull request May 14, 2018

Merge #691
691: refactor: Make game data pluggable r=Xaeroxe,torkleyy,jojolepro a=Rhuagh

Remove Dispatcher from Application, and add a pluggable generic type.
Add a direct replacement for the old game data, featuring only a Dispatcher.
Make the states take a new StateData type, containing references to World and pluggable game data.
Move responsibility for doing system dispatch to the states.

Opening this early to get feedback.

Resolves #576 

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/amethyst/amethyst/691)
<!-- Reviewable:end -->


Co-authored-by: Simon Rönnberg <seamonr@gmail.com>
@bors

This comment has been minimized.

Show comment
Hide comment
Contributor

bors bot commented May 14, 2018

@Rhuagh

This comment has been minimized.

Show comment
Hide comment
@Rhuagh

Rhuagh May 14, 2018

Member

bors r=Xaeroxe,torkleyy,jojolepro

Member

Rhuagh commented May 14, 2018

bors r=Xaeroxe,torkleyy,jojolepro

bors bot added a commit that referenced this pull request May 14, 2018

Merge #691
691: refactor: Make game data pluggable r=Xaeroxe,torkleyy,jojolepro a=Rhuagh

Remove Dispatcher from Application, and add a pluggable generic type.
Add a direct replacement for the old game data, featuring only a Dispatcher.
Make the states take a new StateData type, containing references to World and pluggable game data.
Move responsibility for doing system dispatch to the states.

Opening this early to get feedback.

Resolves #576 

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/amethyst/amethyst/691)
<!-- Reviewable:end -->


Co-authored-by: Simon Rönnberg <seamonr@gmail.com>
@bors

This comment has been minimized.

Show comment
Hide comment

@bors bors bot merged commit 6d3f65a into amethyst:develop May 14, 2018

2 of 4 checks passed

continuous-integration/travis-ci/pr The Travis CI build failed
Details
code-review/reviewable 12 files, 10 discussions left (jojolepro, Rhuagh, torkleyy)
Details
bors Build succeeded
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details

@Rhuagh Rhuagh deleted the Rhuagh:refactor/game-data branch May 14, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment