#0.14 Bevy Jam

1 messages · Page 3 of 1

slender belfry
#

You can also spawn something directly on a state transition

bitter sparrow
#

yep we do that for the UI

slender belfry
#

Ah yeah right

bitter sparrow
#

well by "directly" it's actually a command ofc

agile dirge
#

new idea:

struct SpawnPlayer {
  // player data
}

impl Component for SpawnPlayer {
  fn register_component_hooks(entity, world, blah) {
    let data = world.entity(entity).remove::<SpawnPlayer>();
    // Spawn logic
  }
}
bitter sparrow
#

because it's not an exclusive system

slender belfry
#

Only thing that AFAIK does not work is spawning something in a hook

agile dirge
#

damn

#

wait no, it works

#

it has an entity just adds components

bitter sparrow
#

wait what spawn player as component???

agile dirge
#

no child entities tho

bitter sparrow
#

oh god

slender belfry
agile dirge
#

note that world.commands() exists, so you can queue spawns

slender belfry
#

My vote is for keeping the code as-is with observers

#

For one reason mostly

agile dirge
#

deferred init is a weird subject in Rust sadly

slender belfry
agile dirge
#

based on what

#

(links to the example)

slender belfry
#

Oh hey @hidden pond is back 👋 How you doing?

bitter sparrow
hidden pond
#

I have a quick question about the splash screen...are actually allowed to distribute the bevy logo, especially given the licenses this is under? I remember the CI template we forked from removed it due to that.

agile dirge
#

@prisma delta wasn't the logo transfered to Bevy and is now under the same license as code?

bitter sparrow
#

allowed, yes, as long as we get permission and specify the copyright in the README

#

it just means that whoever clones the template has to consider whether they want the non-open-source bevy logo in their assets

prisma delta
#

Put it in, but list the credits

hidden pond
#

Our template also has the CC0, so we might need to specify in the README the license does not apply to that at the very least.

agile dirge
hidden pond
#

Just want to make sure we don't accidentally violate a license or cause copyright infringement.

slender belfry
#

I like how Bevy itself highlights it

slender belfry
bitter sparrow
#

and should probably specify the license even for assets we use that are CC0

slender belfry
#

Maybe we should have a button in the menu for licenses?

#

So that users can add the assets they use easily

bitter sparrow
#

you mean the credits screen?

slender belfry
#

It's a bit different than credits imo

#

credits = "This is the creative team"
licenses = "This is the stuff we yoiked"

#

At least in my mind

#

Credits also should look nice, probably. Not too much text, maybe a few social links

#

while licenses is just a dump

#

the font can be minuscule there, just get it onto one screen so no one has to learn that bevy has no widget for scrolling

bitter sparrow
slender belfry
bitter sparrow
#

Made by

...

Assets

...

slender belfry
#

Many games just have all licenses in their splash screen

#

@bitter sparrow can we merge the movement PR or should we wait?

bitter sparrow
#

i havent looked at it yet

#

so prob wait

slender belfry
#

👍

agile dirge
#

How do you attach sound to a character

slender belfry
agile dirge
#

it should be based on the physics right?

slender belfry
#

Do you mean for footsteps?

#

That should probs depend on the Velocity, yeah

#

I have not looked much into audio in Bevy, so I can't comment much on that. No idea what best practices there are.

agile dirge
#

I'll branch off and try to prototype

#

any suggestions for source of sounds?

slender belfry
#

Also maybe ask #audio-dev

slender belfry
bitter sparrow
slender belfry
bitter sparrow
#

even so

#

the best practice may change in 0.15 or 0.16 but as things currently stand

agile dirge
#

oh

#

nvm

#

i did miss the free section

hidden pond
bitter sparrow
#

@slender belfry yeah physics don't have to go in core, it more makes sense there if you're pulling in a 3rd-party library like avian2d

#

then you're just setting up their physics plugin

slender belfry
#

That makes sense

#

Responded to your comments on the PR

bitter sparrow
#

oh all the physics stuff was just added to the PR?

#

before it was just spawning player/level

slender belfry
#

Yep

bitter sparrow
#

ok

slender belfry
#

or wait

#

what do you mean?

#

I mean to say "yes, this PR includes all the physics stuff"

#

But I added that hours ago

bitter sparrow
#

o

#

well i didnt see it lol

#

when i did a review pass

slender belfry
#

😄

bitter sparrow
#

so the thing about fixed timestep is

#

the last time i tried it the tooling sucked

#

it's "technically correct" but it was a buggy pain

#

i think some of the bugs have been fixed

#

is it good enough to recommend in general though?

#

also for a game jam i'd prob not bother trying to get it right personally, fwiw

slender belfry
bitter sparrow
#

well lightyear has the time to write any boilerplate / make sure it works, anyways. in theory, idk what they're actually doing

slender belfry
bitter sparrow
#

i suppose

slender belfry
#

I'm pretty strongly in favor of showing people how to do it the right way if we are semi-official

bitter sparrow
#

if fixed timestep is good enough to be considered "the right way" then sure

#

it used to drop events, i heard that was fixed recently

#

so all user game logic should go in FixedUpdate, right?

agile dirge
#

only time-based things i'd say

#

physics

#

you need to process inputs in Update cause the resources get refreshed each frame

#

graphics need to be in Update

#

interactions can be ticked with physics so thats FixedUpdate

slender belfry
#

Exactly right

bitter sparrow
#

yea interactions like a projectile hitting something and dealing damage

#

or triggering an effect on collision

agile dirge
#

mhm

bitter sparrow
#

would be FixedUpdate

#

so by game logic ig i meant "game simulation logic"

agile dirge
#

there are probably cases where you don't need to, but anything based on physics, yes

slender belfry
bitter sparrow
#

for something like updating a health bar, that's in Update i assume

bitter sparrow
agile dirge
#

you can have effects based on collisions

#

thats graphics depending on physics

bitter sparrow
#

if there are multiple FixedUpdate steps in the same Update frame, the later ones wouldn't see the effects of the earlier ones

#

oh no i don't mean vfx

#

i mean cause-effect

slender belfry
bitter sparrow
#

yes

#

i mean effects like "spawn explosion entity on collision"

agile dirge
#

but yeah, if physics get updated in two FixedUpdates and then we have an Update that reads physics then there will be problems

#

cant have that

slender belfry
#

But you could also spawn it directly in FixedUpdate

#

Your choice really

agile dirge
#

i'd say fixed update is correct here

bitter sparrow
#

the point is the next FixedUpdate step will want to see the effects of the previous step

bitter sparrow
#

otherwise framerate affects how fast game-affecting effects are triggered

slender belfry
#

Yes, if you need to access that information, you are totally right!

#

I was thinking about a purely visual effect here, like a particle spawner

bitter sparrow
#

yeah for sure. that can be in update

slender belfry
#

So that's where the misunderstanding came from 🙂

agile dirge
#

just noticed, this isn't a linear interpolator

#

probably won't be noticeable, but wanted to point it out

slender belfry
agile dirge
#

lightyear does it that way?

slender belfry
#

Ping @lavish robin

bitter sparrow
#

i'm once again sad we have to bake in our own physics so that the user can tear it all out and depend on avian2d

slender belfry
hidden pond
#

Never actually used it tbh.

agile dirge
bitter sparrow
agile dirge
#

more often you get few Updates interrupted by a FixedUpdate

bitter sparrow
#

i'll prob switch to it once i update to bevy 0.14

agile dirge
#

why are we optimizing worst case experience xD

bitter sparrow
#

eh needed

#

bad pc maybe

#

or good pc but web release

agile dirge
#

well, let's wait for Periwink to reply

lavish robin
#

I'm not sure what the actual question is

agile dirge
#

Two questions

#

Why is the example using one Update to many FixedUpdate, which I believe isn't the typical way it works?

#

In the example it's always a frame (Update) with one or two FixedUpdates

#

but never zero fixed updates

slender belfry
#

If your update is fast enough, you should get zero fixed updates

agile dirge
#

exactly

bitter sparrow
#

oh btw. one reason not to use commands or observers for spawning things is you can't add components to them after spawning

lavish robin
#

Hm no specific reason, just because that's something I was observing in my examples (where I set the tick-rate to 64Hz). But in my tests I test both cases (tick rate faster than frame rate and frame rate faster than tick rate): https://github.com/cBournhonesque/lightyear/blob/main/lightyear/src/client/interpolation/visual_interpolation.rs#L552

GitHub

A networking library to make multiplayer games for the Bevy game engine - cBournhonesque/lightyear

bitter sparrow
#

like StateScoped would be more idiomatic to add after the helper method spawns the thing, imo

agile dirge
#

hm

slender belfry
agile dirge
#

you can provide Box<dyn Bundle>

#

if you really need to xD

agile dirge
slender belfry
#

Whaddup

agile dirge
#

The interpolation uses values from last 2 FixedUpdates, not from last Update (transform.translation) and last FixedUpdate

lavish robin
#

Yeah i don't think you want to interpolate between the last rendered value and the next FixedUpdate value

#

you always want to interpolate between 2 FixedUpdate

slender belfry
agile dirge
#

(contributor successfully baited into a review, rejoice)

slender belfry
lavish robin
#

haha

agile dirge
#

glad we got this figured out

bitter sparrow
#

so PhysicalTransform is to separate it from Transform which is used for interpolation?

slender belfry
#

So, just so I got this right: I want to keep track of the last PhysicalTransform and interpolate to the current PhysicalTransform, then use that value for the Transform, right?

bitter sparrow
#

if so i'd explicitly mention interpolation as the reason for its existence

slender belfry
#

I'll add comment though, makes sense to mention it 🙂

#

I'll be AFK for a little while, gonna address the comments later

bitter sparrow
#

i'll trigger a release cause why not, we're not paying for it

#

crazy thought. what if the release workflow split the upload to itch.io into two jobs: one that only uploads the web build, and one that uploads all the native builds

#

that would give a 3x speedup for uploading the web build instead of waiting 10 minutes for windows...
probably not worth splitting into two releases on itch.io though ig

rigid geyser
#

Baloo Bhaijaan 2

agile dirge
bitter sparrow
slender belfry
slender belfry
slender belfry
bitter sparrow
#

oh

#

i wasn't linking the release, just making a joke about it being suspicious

#

lol my bad

slender belfry
#

hehe

bitter sparrow
#

release just finished now tho

#

ok no

#

the css spinner -> splash screen combo looks awesome

#

ngl

#

i cooked

agile dirge
#

now we need an SFX for the splash screen

#

so people kno when their game is done loading

bitter sparrow
#

birds chirping sfx

#

embedded asset

#

bevy needs an official trademarked sound effect

agile dirge
#

we should interpret the entire bevy repository an audio stream and find something cool in there

slender belfry
bitter sparrow
prisma delta
bitter sparrow
#

need to get an audio clip of a parrot saying that

lavish robin
slender belfry
slender belfry
#

I'd love to try it, but I'm not spending money on that

#

(also shady licensing when the content is AI-generated)

inland wyvern
#

y'all work so fast

bitter sparrow
#

copying comment here:

commands.spawn uses Commands::entities to return an EntityCommands which includes both Entity and Commands.

commands.add and commands.trigger both can't do this, but an extension trait could (like we do for UI widgets). Maybe an extension trait with a generic method like commands.my_spawn(impl Spawnable) -> EntityCommands, so you could do commands.my_spawn(Player { ... }).with_children() etc. if you want

#

the fact that other spawning methods return the Entity id right away, but commands.add and commands.trigger don't, mean that IMO we should not be using the latter two

#

like maybe we could use them internally, but w/e api is provided it should return the Entity

agile dirge
#

I don't think this is something we should support

#

we aren't trying to make another layer of spawn API

#

we are trying to make top-level methods of spawning predefined game entities

#

like a layer on top of bundles

bitter sparrow
#

yes but it's so limited if you don't get the Entity back

agile dirge
#

the spawned entity should be mostly complete

bitter sparrow
#

what if you want to set its parent?

agile dirge
#

I'd need an example

bitter sparrow
#

okay let's say i want to spawn an enemy

#

i'm using bevy editor pls so i want all my enemies to be under an abstract Enemies parent entity

#

commands.trigger(SpawnEnemy { ... }) and then.. what?

agile dirge
#

You set the parent in spawn_enemy

#

because you defined that all enemies will have Enemy as the parent

#

again, this isn't a shorthand for Commands::spawn

#

it's a new API that shared the same "spawn" name

bitter sparrow
#

yes i'm just saying this API is strictly worse

agile dirge
#

Anything but strictly

#

It has a specific use case and it does it perfectly

bitter sparrow
#

disagree

#

spawning something and then not being able to do anything with the Entity id is bad

#

what if you want to store it in a resource, or who knows what

#

there's always something you don't account for

agile dirge
#

add marker traits instead

#

and query for it

bitter sparrow
#

oof

agile dirge
#

we aren't making an engine

#

we don't need to support every imaginable option

#

most games will have clearly defined mechanics

#

and in 99% cases they won't need the Entity

#

if you do need it, explore other options

bitter sparrow
#

ehhhh

#

it's not like it's more work to provide it

#

this is just limiting options for no reason

#

i really don't think it's 99% cases

#

maybe like 80%

#

probably less tbh

agile dirge
#

it really is, take a platformer

bitter sparrow
#

in a real game you want the flexibility

agile dirge
#

player, enemies, interactibles

#

you spawn them and let systems do their job

#

no Entity is being used

#

if you have player variants, either use an enum to control the variant or have multiple spawn methods

#

like, this is not meant to be flexible, we encase very specific logic in a convenient wrapper

bitter sparrow
#

you can still get the latter while also getting the former tho

agile dirge
#

how exactly

bitter sparrow
#

return Entity

agile dirge
#

you can't return entity because you don't spawn entity

bitter sparrow
#

and in most cases the user will just not touch it

agile dirge
#

like

#

okay

#

here are the possible cases:

#
  • defer spawning (observers/commands) - no Entity to return at call site
  • immediately spawn (Commands::spawn) - return Entity at call site, but also provide ALL values for ALL components (including asset related data which we specifically try to defer)
  • hybrid - spawn an incomplete Entity and return it at call site, add other components later
#

we can't do that

bitter sparrow
#

Commands::spawn is deferred too btw

agile dirge
#

okay, so once again, how do you return and not mess up the entity component integrity

bitter sparrow
#

the entity id is created before the entity is actually spawned

agile dirge
#

and

bitter sparrow
#

and returned? wdym

agile dirge
#

...

#

i will fight against any proposition that introduces race conditions

#

if you spawn entity and fill it later

#

in a different command

#

you have a time period where it's incorrect

#

can't have that

bitter sparrow
#

not really, both commands will be applied at the next sync point

#

like commands.spawn(xyz).insert(abc) is totally fine to do

agile dirge
#

thinking

#

and waiting for language server to wake up

bitter sparrow
#

okay how about something like this:

let entity = commands.spawn_empty();
commands.trigger_with_targets(entity, InsertPlayer { ... });
return commands.entity(entity);
agile dirge
#

i see how that would work with commands now

#

i honestly thought the EntityCommands batched the changes into one command .-.

#

it doesnt

bitter sparrow
#

ic

agile dirge
#

but

#

is that still fine with observers mixed in

bitter sparrow
#

like will it work? idk i can make a pr to try it out after this lands

agile dirge
#

no, it will work in common case

#

im looking for edge cases

#

we don't want to give a solution that leads to obscure issues

#

cause with commands, if they come from one system they run back-to-back

#

but if you do a command then observer

#

there is way more that can happen inbetween

bitter sparrow
#

true idk what the ordering between commands and observers is

#

tbf though... the trigger_with_targets can instead be commands.add(InsertPlayer { entity, ... }), so the ordering will be well-defined

#

even though the new entity arg makes observers more appealing

hidden pond
prisma delta
#

I actually think the right thing is to have a nice bird song or a flight of birds whooshing by

slender belfry
#

Back now! I'll work through the comments now and leave the spawning stuff for a follow-up. It may be worth asking #ecs-dev for their opinion as well.

#

For the record, I have no strong feelings, it should just not look too surprising or weird to a beginner.

bitter sparrow
#

this would work for example:

// Auto-derives EntityCommand
fn insert_player(entity: Entity, world: &mut World) { ... }

fn my_system(mut commands: Commands) {
    commands.spawn_empty().add(insert_player);
}
#

not suggesting this as the API just PoC

agile dirge
#

i know how it will work

#

but i think a good api will be difficult

bitter sparrow
#

ok ill just make a pr later

agile dirge
#

I'm trying to figure out whether we can reserve an Entity and request a spawn command with a specific Entity

#

then observers would work fine

bitter sparrow
#

i think there's an upstream docs error

#

spawn_empty says it adds a command. it does not seem to

#

it registers the Entity id directly on Entities

#

unless i'm mistaken

agile dirge
#

if spawn_empty makes the entity at call site, instead of just reserving an id

#

then i think we're fine with the observer trick

bitter sparrow
#

yeah should be fine

#

and docs should be fixed upstream :)

agile dirge
#

lets merge the current version of the PR k?

#

and then work off that

bitter sparrow
#

yeah ofc this is not blocking

agile dirge
#

except there are requested changes

#

🙃

bitter sparrow
#

yea those requests are still valid

#

gonna take a break to cook irl

agile dirge
#

okay, we cannot do observers AND return entity

#

the end

slender belfry
#

Done check_accept

agile dirge
#

I'll double check my test case

bitter sparrow
#

o you have a test case ok ill wait

agile dirge
#

testing give me some time

#

but i suspect a hook like what Jan did will make this fail miserably

#

im not super clear on command/observer execution order

slender belfry
#

They only get DeferredWorld

agile dirge
#

deferred world still has commands

#

you can request to spawn an entity

slender belfry
#

Oh wait, you're right

#

huh

agile dirge
#

it just cannot access entities and mess up archetypes

#

but if you defer it it's fine

#

(as name implies lol)

#
thread 'main' panicked at src\game\spawn\level.rs:32:44:
called `Option::unwrap()` on a `None` value
#
fn spawn_level(_trigger: Trigger<SpawnLevel>, mut commands: Commands) {
    // The only thing we have in our level is a player,
    // but add things like walls etc. here.
    commands
        .spawn_deferred(SpawnPlayer)
        .insert(ComponentWithHook);
}

struct ComponentWithHook;

impl Component for ComponentWithHook {
    const STORAGE_TYPE: StorageType = StorageType::Table;

    fn register_component_hooks(hooks: &mut ComponentHooks) {
        hooks.on_add(|world, entity, _component_id| {
            world.get::<Transform>(entity).unwrap();
        });
    }
}
#

i insert a component that's expecting other components to already exist

#

spawn deferred is implemented with observers

#

wait no, i fucked up the impl

#

holy crap

#

it works

#

okay, well then i have a PR ready

#

i need some bikeshredders

#

what do we name this

#
pub(crate) trait SpawnDeferred {
    fn spawn_deferred<E: Event>(&mut self, events: E) -> EntityCommands;
}

impl<'a, 'b> SpawnDeferred for Commands<'a, 'b> {
    fn spawn_deferred<E: Event>(&mut self, event: E) -> EntityCommands {
        let entity = self.spawn_empty().id();
        self.trigger_targets(event, entity);
        self.entity(entity)
    }
}
slender belfry
#

Oh whoops, I forgot I didn't use the GameSystem enum I prepared. Fixed.

slender belfry
slender belfry
#

So what's the secret reason why this is not what trigger_targets already does?

agile dirge
#

it returns EntityCommands at call site

slender belfry
#

Ah wait, I see now

#

Cool!

#

I like the pattern!

agile dirge
#

yeah, Pyrious cooked

#

I just had to check the edge case but I bugged him long enough to figure out all the code

#

I'm moving this to util then

slender belfry
#

hehehe

agile dirge
#

i want the name to reference the fact that it takes in an Event

slender belfry
#

trigger_spawn

agile dirge
#

perfect

slender belfry
#

In reference to trigger_targets

agile dirge
#

now that it works um

#

i noticed we don't need it

#

we don't have a use for it here

#

cause we don't need Entity at callsite

slender belfry
#

Yesn't

#

wait

#

You could add the StateScoped to the spawn_level function this way

agile dirge
#

right, good idea

#

and Name

#

perfect

slender belfry
#

I set the PR to automerge as soon as @bitter sparrow gives it an approval

#

gonna go cook something as well now cooltofu

agile dirge
#

👌

bitter sparrow
#

hooray

#

another naming option: spawn_prefab

#

idc about the name much though

slender belfry
#

e.g. loading from a file

agile dirge
#

i cooked too hard guys

#
impl<'a, T: Spawner<'a>> TriggerSpawn for T {
    fn trigger_spawn<E: Event>(&mut self, event: E) -> EntityCommands {
        let mut entity = self.spawn_empty();
        let id = entity.id();
        let mut commands = entity.commands();
        commands.trigger_targets(event, id);
        entity
    }
}
#

this is required for ChildBuilder to work properly

bitter sparrow
#

my rice is ready 🍚

#

four transform types 🐸 but ok

#

comments explain it

#

how does auto-merge work? is it gonna get merged now

#

had to refresh the page all good

hidden pond
agile dirge
#

@bitter sparrow @slender belfry

#

may need bikeshedding

bitter sparrow
#
    let intent = intent.normalize_or_zero();
    let velocity = intent * SPEED;

    player_velocity.single_mut().0 = velocity;

this fine?

#

merged

#

and obviously it panics because i didn't try running it

#

single_mut moment

#

so either the system only runs in the Playing state, or i switch to get_single_mut (which would result in silently nothing happening if there are 2+ player entities), or i go back to iterating over the query

#

my preference is for #3 but open to opinions

agile dirge
#

if it's the same input scheme multiple players make no sense

bitter sparrow
#

okay well #2 is possible because get_single_mut returns a Result not an option, so i could check the error :p

bitter sparrow
agile dirge
#

you can also do iter_mut().next()

#

so it only affects one

bitter sparrow
#

true

#
// Option 2
if let Some(mut velocity) = player_query.iter_mut().next() { velocity.0 = velocity }

// Option 3
for mut velocity in &mut player_query { velocity.0 = velocity }
#

uh ignore the velocity name shadowing

#

hm if there's more than one player entity for some reason, option 2 will silently move a different entity each time

agile dirge
#

do all then

bitter sparrow
slender belfry
#

I'd do if let Ok(foo) = foo.get_single_mut() else { return; }, everything else is kinda misleading imo

bitter sparrow
#

in terms of the resulting behavior, i think moving everything makes the most sense

slender belfry
#

But that’s way more controversial haha

bitter sparrow
#

i mean that macro would be fine, i'm just more concerned about the behavior than the code

#

for something like a window entity, you want to get the single window or return from the function otherwise

#

but for player it's not like the system cannot continue if there's more than 1

#

this system at least

#

like if you need the window size to do some calculations on each entity in a query, then if there are 2 windows.. there's no sensible way to continue

#

merged

slender belfry
#

Fair enough, you’re right

bitter sparrow
#

@agile dirge do we have to support triggering the spawn events without an entity?

#

it seems like that's the main ugliness in the api?

agile dirge
#

the trigger systems are bit wonky

#

quite wonky

#

and that too

bitter sparrow
#

mmm

#

what if EntityCommands::trigger existed

#

wouldn't that be nice?

#
        let mut e = self.spawn_empty();
        e.trigger(event);
        e
#

😍

slender belfry
#

PR on Bevy main plz

bitter sparrow
#

will do if no one in #ecs-dev complains

#

commands.spawn(bundle).trigger(event) mmm

agile dirge
#

also add trigger capability to BuildChildren or a way to retrieve Commands

slender belfry
slender belfry
#

@agile dirge is it alright for you if I do another refactor pass? I’d like to add name to everything, reflect, etc.
Asking because you might get a merge conflict then

agile dirge
#

Ehh sure

bitter sparrow
#

i think if we merge mini's pr before the refactor pr it's fine

slender belfry
#

Aight, I’ll wait then

bitter sparrow
#

well you can make the refactor pr now if you want

#

ig it depends on what you're planning to do

slender belfry
#

Also, thoughts on #derive order? I personally do Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Component/Resource/Event

#

But that’s completely arbitrary

bitter sparrow
#

so what i do for derive order is the "most important" derive first, aka Event or Component etc

agile dirge
#

No preference

bitter sparrow
#

and then after that kinda arbitrary but i do the traits required for the first trait first

#

and put PartialEq by Eq, and Clone by Copy

#

anything beyond that is fair game afaic

slender belfry
# agile dirge Ehh sure

How ready is your PR? I did not look into it too much yet because I thought you were still on it

slender belfry
#

Hi @hoary flower 👋

hoary flower
agile dirge
agile dirge
#

Only the first two you added earlier

bitter sparrow
slender belfry
#

Hrrm, looking at it, it looks like the kind of code I'd expect to see in a third-party crate, not a Jam template

#

I think someone who is not deep into Bevy looking at that will get quite spooked

bitter sparrow
#

i feel like that's unavoidable though. i could say the same about the physics stuff

#

bevy is just lacking some basic features upstream

slender belfry
#

This here is more of an experiment

#

But I don't want to block the PR if both of you think it's a good idea

bitter sparrow
#

i think it's a good idea, and will be replaced by bsn

#

everyone always ends up looking for a solution to this problem one way or another

agile dirge
#

Id rather not merge this for the template

slender belfry
bitter sparrow
#

i just really think the api is not bad at all after applying my suggestions

agile dirge
#

Its still very bad and one suggestion makes it worse

bitter sparrow
#

ok. i don't see it, it's just trigger.entity()

#

but w/e

agile dirge
#

The problem is the spawn code

#

It's too finicky

bitter sparrow
#

which spawn code?

#

the observer?

agile dirge
#

Level and player

#

Yes

slender belfry
#

Like, if this was my own project I'd have no issues using this, it's neat

bitter sparrow
#
commands.entity(trigger.entity()).insert(bundle).with_children(children)
#

bad?

agile dirge
#

?

bitter sparrow
#

how else would this look?

#

in the alternative api

#

commands.spawn(bundle).with_children(children) right

agile dirge
#

The problem is the observer system

slender belfry
#

@bitter sparrow could you show me your suggestion for how the spawn_level and spawn_player systems would look like?

#

I'm ready to change my mind if it looks intuitive enough

bitter sparrow
#
fn spawn_level(trigger: Trigger<SpawnLevel>, mut commands: Commands) {
    commands
        .entity(trigger.entity())
        .insert(Name::new("Level"))
        .with_children(|children| {
            children.spawn_trigger(SpawnPlayer);
        });
}

fn spawn_player(trigger: Trigger<SpawnPlayer>, mut commands: Commands) {
    commands
        .entity(trigger.entity())
        .insert((
            Name::new("Player"),
            Player,
            SpriteBundle {
                texture: assert_server.load("ducky.png"),
                transform: Transform::from_scale(Vec3::splat(0.5)),
                ..default()
            },
            Velocity::default(),
            PhysicalTransform::default(),
        ));
}
#

basically commands.spawn is replaced with commands.entity(trigger.entity()).insert

slender belfry
bitter sparrow
#

nope, it's spawned before the observer runs with .spawn_empty()

slender belfry
#

That is a bit whacky 😅

agile dirge
#

Entity() returns the targeted entity of the event

slender belfry
bitter sparrow
#

yea

agile dirge
#

Which is PLACEBOLDER if none was targeted btw

#

Its not a panic if there is no entity

bitter sparrow
#

yes but you're not supposed to trigger the spawn events manually

agile dirge
#

I missed that in my review 🥹

bitter sparrow
#

you're supposed to use the commands.spawn_trigger

#

but yeah a user could mis-use it like that and it wouldn't be an error, that is true

#

actually it would be an error i think

#

you can't insert on Entity::PLACEHOLDER right?

#

well a panic not an error i mean

slender belfry
#

Mis-use is a bit of an overstatement, a user is just triggering an observer the way Bevy has taught them.

agile dirge
#

Yeah

bitter sparrow
#

ig so but i feel like an observer expecting there to be an entity is a valid use case in general?

#

just bevy doesn't have a way to require that statically rn

#

unless it does and i missed it

agile dirge
#

It was decided to not require it statically

#

For now at least

#

May change foe 0.15

bitter sparrow
#

even the bevy docs for observer have an example that would panic

#

if triggered without a target entity

slender belfry
#

What happened to the suggestion of using Commands instead of observers?

bitter sparrow
#

it would be an EntityCommand

slender belfry
bitter sparrow
#

okay

slender belfry
#

If @agile dirge is fine with that as well

agile dirge
#

Im not gonna stop him from making a pe

#

Pr*

#

But if it ends up looking janky dont hold it against me if i refuse it

bitter sparrow
#

if you want to remove the spawn stuff and keep the ui refactoring part i'll approve

#

from your pr

#

or i can redo it in mine

agile dirge
#

Ye, ill do that when im at pc, away rn

bitter sparrow
#

ok

slender belfry
#

Thoughts on whether I should add Serialize and Deserialize to everything?

#

I'd do it personally just to be on the safe side

#

But I know many users won't care

bitter sparrow
#

no thoughts head empty in this case

slender belfry
#

👍

#

I'll add it then

bitter sparrow
#

btw all the lifetimes can be removed from the ui/widgets.rs stuff

#

i will do that

#

the power of '_

slender belfry
bitter sparrow
#

aaaaaaa

slender belfry
#

Aaah yes, ergonomics bavy

bitter sparrow
#

derive deref and derefmut = ?

#

i havent seen that before

#

oh

#

to deref to Transform, right

slender belfry
#

Yep

#

It comes from Bevy 🙂

bitter sparrow
#

suggestion for a better name than prefab here?

#

im going with prefab in the meantime

#

hmmmmm may have an idea

#

will request an open mind for this api when i make the pr

#

i think it will be good

slender belfry
#

Solving 4 issues in there cooltofu

slender belfry
#

I added this because IME it's quite a subtle footgun for a lot of beginners

bitter sparrow
#

sure

slender belfry
#

so better made sure that people can have a second camera without wondering where their UI went 🙂

bitter sparrow
#

IsPrimaryCamera maybe?

#

or as a separate component

#

for like following the player

#

or is that out of scope :p

slender belfry
bitter sparrow
#

o

#

got it

slender belfry
bitter sparrow
#

right

slender belfry
#

It's imo the ugliest named component in all of Bevy 😄

bitter sparrow
#

nah i like the name

#

i think marker components starting with Is is reasonable

slender belfry
#

Hmm

bitter sparrow
#

because that's how you'd name them if they were fields on a struct

slender belfry
#

Didn't think about it that way

bitter sparrow
#

although ig that'd be moreso equivalent to IsDefaultUiCamera(bool)

slender belfry
#

I'll let it roll around in my head. Thanks for the perspective.

#

I also did not add any derives to triggers because serializing or reflecting them would be bonkers.
Edit: nvm added all the derives as well

bitter sparrow
#

btw the fact that EntityCommands != EntityWorldMut is annoying me rn 😄

#

may want another trait to abstract it

#

it's Commands, ChildBuilder, World, and WorldChildBuilder

#

call spawn, and get either EntityCommands or EntityWorldMut

#

we're currently only supporting the former 2, but for a custom EntityCommand, you need to support the latter 2 as well

#

because they take world

slender belfry
#

Hi @pseudo marten 👋

pseudo marten
#

For a game jam submission: does physics really need to run in FixedUpdate? I think the template would be significantly more approachable just setting the Transform in an Update system based on the velocity.

pseudo marten
bitter sparrow
#

#1258521739395203174 message

slender belfry
#

I mean, people can still yeet the entire thing if they want

#

It's not interconnected with anything

pseudo marten
#

Is it still that jittery if one takes the frame time in account? I never really experienced any jitter with that

slender belfry
#

Also tunneling

#

Historically, quite a few people roll their own 2D logic instead of using a physics engine, so they will run into that

#

(Although maybe this changed and now everyone will use Avian, as they should)

pseudo marten
#

Hmm ok, maybe I never used enough physics xD
I see you discussed it a lot already. Just took a quick look and wondered about the size of the template. It has significantly more code/files than I expected.

slender belfry
#

It's split into rather neat small files :>

pseudo marten
#

Yeah

bitter sparrow
#

that is true. the files are mostly like 50 LoC max

slender belfry
slender belfry
#

So that also contributes to being happy with a lot of small files

rigid geyser
slender belfry
rigid geyser
#

(not putting my foot down on any issues / treat me like any other contributor as this is "outside of the bevy repo")

bitter sparrow
#

responded to changes 3 and 5

#

have not looked at the code

slender belfry
#

The deflicker drop is a bit more controversial; I think @prisma delta mentioned this specifically as the kind of boilerplate a template should include (correct me if I'm wrong)

dawn crag
#

3 / 5 specifically bugged me as well, and I agree with the additional commentary in 5.

I haven't looked closely at the code, because at some point this thing seemed to become quite complex and I stopped following closely. So I am inclined to agree that an effort to simplify things is a good thing.

slender belfry
dawn crag
#

If the deflicker fix weren't so janky I would be more okay with it

slender belfry
bitter sparrow
#

boot state needed for loading window config anyways ^\_(``/)_/^

prisma delta
#

Yeah I'm mostly just annoyed that it's so janky in the first place lol

bitter sparrow
#

this template won't include a window config most likely. but still, it's only as janky as that would be

slender belfry
#

I'm completely fine removing it as well

dawn crag
#

But also I think I'm just generally not well aligned with this effort and don't want to rain on any parades so I am trying to keep my opinions muted 🙂

bitter sparrow
#

the difficulty in keeping the template simple is that we're not using 3rd-party crates

#

so no input management, no physics, no UI abstractions, no asset loading abstractions

#

etc

slender belfry
slender belfry
#

👀 this message gonna be long

agile dirge
#

Don't worry about us, we all have our opinions too 😄

dawn crag
#

Well, mainly I am not sure that the timing is right for this effort -- as pyrious mentioned, it would be a bit crazy to try to build a game in Bevy without a single third party ecosystem crate. I also think we definitely shouldn't be picking winners among the ecosystem crates. Especially e.g. among the physics crates.

So with that background, my thoughts are that this template seems a bit too ambitious, and I'd personally rather

Very much just my opinion. I do think that a template that goes a bit beyond what we're willing to do with bevy_github_ci_template but still does not use third party crates could potentially be valuable / something I might use myself, but I think we've gone way way way deep into some opinionated patterns.

#

And because this is "semi-official" I definitely don't want to make a fuss.

bitter sparrow
#

timing not being right is understandable. my take is being opinionated now, and later on removing the opinionated stuff in favor of w/e gets upstreamed, is a reasonable compromise

dawn crag
bitter sparrow
#

reasonable. i think we were planning to link to other templates in the README but that would probably be better (or link from both places)

slender belfry
# dawn crag Well, mainly I am not sure that the timing is right for this effort -- as pyriou...

I definitely see where you're coming from. I'm personally very happy about having had a place to discuss these opinionated patterns, as I was kind of missing a discussion about best practices in general.
In my experience, for a template to be useful, it will be big enough that it has to incorporate opinionated stuff. The templates so far just involve the opinions of a single person, but this one is coming together from the shared experience of multiple people actively trying to find out together how to best structure stuff. I think that's a pretty cool opportunity 🙂 (at least for me, I'm learning a lot here)

slender belfry
#

I want people to be very quickly directed to the ecosystem

dawn crag
#

Yeah, me as well. I actually generally like what y'all are doing under these constraints 🙂

slender belfry
#

Is anyone vetoing @rigid geyser's PR? Otherwise I'll merge it. And cry a bit because of the merge conflict's I'll get.

slender belfry
bitter sparrow
slender belfry
#

I'll wait for you then 🙂

agile dirge
#

I don't have anything against it, it doesn't bring much controversy

#

most of those topics came up and we just decided to roll with the one we did

bitter sparrow
#

oh another thing. .disable.add_after may be strange, but bevy is meant to be modular. so being able to swap out plugins for your own versions of them shouldn't be considered strange

slender belfry
#

So, while everyone is in this chat, general vibe check: how do y'all outside the working group feel about two things:

  • The deflicker workaround
  • Having fixed timestamp stuff in the template
bitter sparrow
#

if you could do .swap::<WindowPlugin>(window::plugin) it might look less strange

slender belfry
hidden pond
#

Mind if I give my opinion on those two since I haven't already?

agile dirge
#

Honestly, looking at the discussions I'm starting to reconsider whether this project was necessary
I don't regret it, I'll be taking a lot of this for myself
but looking back, without 3rd party crates there is barely anything to show
we are either:

  • implementing something that should be in core
  • implementing something that should be in 3rd part lib
slender belfry
agile dirge
#

yes, the knowledge is definitely helpful overall

prisma delta
#

I am very much enjoying y'all figure out things that should be in core :p

agile dirge
#

well, someone still has to add it 😩

#

@bitter sparrow did you add issues for triggers and other commands?

slender belfry
bitter sparrow
bitter sparrow
#

btw regarding pub(crate) being noisy, i agree on that. i accept that it may be "more correct", and i don't fully understand what the benefit to it is, but yeah

bitter sparrow
hidden pond
#

Personally. I'm fine with the deflicker being in the template, as its a bit jank. However it also doesn't work on all platforms. If it is jank and likely to come up and isn't necessarily easy to find, then I would support it being in the template.

As for things in FixedUpdate, I'm fine keeping stuff in there. Makes things easier to showcase and it's the "right way". Although I won't have an issue if it's removed.

prisma delta
#

Since cargo says "oh this could be read elsewhere!"

#

Which is dumb, because it's a binary

bitter sparrow
#

ok that makes sense

#

i could probably live with maybe having some uncaught dead code in my binary personally

slender belfry
#

I was mostly pushing for the pub(crate) stuff, but yeah, I'm completely fine with changing it to pub is that's the general vibe 🙂

dawn crag
#

Yeah, I think I'm slightly on the side of catching my dead code, but I am fine with changing it back. I think just generally we should remember we're just jammin' and havin fun here. 🙂 Enterprise-grade code isn't really the norm.

hidden pond
#

Also bevy is a WIP itself, so there's a lot that is needed to be done regardless. This has also helped point out and revealed weak points or areas that wouldn't have been brought up otherwize

bitter sparrow
#

"simplify the bevy-template" can be the metric for improving bevy :)

hidden pond
#

I mean hell my PR would've never been made if not for this.

prisma delta
bitter sparrow
#

bevy-template revealing issues in rust rust_on_fire

hidden pond
#

First bevy, and bow bevy template.

#

*now

slender belfry
#

Okay, so general vibes are the following, correct me if I'm wrong:

  • Use pub instead of pub(crate)
  • Remove deflicker, it's just too jank
  • Remove fixed timestep and link the example
#

Did I miss anything else that people brought up?

bitter sparrow
#

idk if removing deflicker was the consensus?

#

im in and out of paying attention rn though

slender belfry
bitter sparrow
#

okay. i won't complain about that. will re-add WindowState if we need window config

#

very easy anyways

hidden pond
#

I'm neutral on deflicker and pro fixed timestep myself. But I'm fine if they end up removed. Especially since we are doing this for a specific game jam. Some of these things should be upstreamed, but.

slender belfry
slender belfry
bitter sparrow
#

imo remove fixed timestep before the jam

#

after the jam maybe re-add

#

99% of jammers will not want to think about fixed timestep

slender belfry
#

I'd rather have a consistent vision

slender belfry
bitter sparrow
slender belfry
#

Because I don't want to have a ton of merge conflicts everywhere 😅

hidden pond
#

Fair enough. FWIW I generally view this template as being a kind of good "start here" convenience template. A way for inexperienced and newer people to bevy to hit the ground running for the game jam, without necessarily needing to understand what templates exist or what they want.

At least that's how I've been treating it.

agile dirge
bitter sparrow
#

hm

#

i managed to get my spawn api to compile

#
// Impls EntityCommand automatically
fn level(mut entity: EntityWorldMut) {
    entity
        .insert(Name::new("Level"))
        .with_children(|children| {
            children.spawn_with(player);
        });
}

fn enter_playing(mut commands: Commands) {
    commands.spawn_with(level).insert(StateScoped(Screen::Playing));
}
#

the implementation is 100 lines of code and compatible with Commands, ChildBuilder, World, and WorldChildBuilder

agile dirge
#

have you used a shared trait and GATs for return type?

bitter sparrow
#

yes

agile dirge
#

great, that's more code we can copy for the issue i posted

bitter sparrow
#

heh

#

should i make a PR or not bother

#

idk where we're at with that rn, just wanted to get this working

agile dirge
#

I'd say it's either a light 3rd party crate

#

or possibly an engine feature depending on the API

#

i should read the example

bitter sparrow
#

engine feature in 0.15 for sure

#

3rd party crate maybe, but then we can't use it in bevy template 😄

#

unless it's duplicated

agile dirge
#

did you use a macro for various sized tuples?

bitter sparrow
#

no macro involved

#

dumping as text file

agile dirge
#

what can level take as arguments besides entity world mut

bitter sparrow
#

you can split it into Entity and &mut World if you want

agile dirge
#

gah 💀

bitter sparrow
#

but it's only between those two options

agile dirge
#

the api is just as bad on that side sadly

bitter sparrow
#

you can also make it a struct with EntityCommand impl instead of a function ofc

#

if you want the command to include some data

#

if a system could be an EntityCommand.. that would be nice

agile dirge
#

the ideal interface I imagine for load is something like

bitter sparrow
#

or like a system taking Entity as its first arg

agile dirge
#
fn load(entity: EntityCommands, my_assets: Res<MyAssets>, other_stuff: Res<OtherStuff>) { ... }
#

which we maybe could do with observer piping

bitter sparrow
#

aaaaa observers

#

i think give observers like 1-2 more releases before they're a go-to option tbh

#

nvm ig you're suggesting adding an upstream feature for observers actually

agile dirge
#

it can be on top of observers

#

for commands

#

you can make a IntoSystem like trait

#

that takes EntityCommands as first argument

#

can't use EntityMutWorld with other args

bitter sparrow
#

yep. you can pull resources out of it though

agile dirge
#

yeah, but it's a nasty interface

bitter sparrow
#
pub(crate) fn player(mut entity: EntityWorldMut) {
    let asset_server = entity.world().resource::<AssetServer>();

    entity.insert((
        Name::new("Player"),
        Player,
        SpriteBundle {
            texture: asset_server.load("ducky.png"),
            transform: Transform::from_scale(Vec3::splat(0.5)),
            ..Default::default()
        },
        Velocity::default(),
        PhysicalTransform::default(),
        StateScoped(Screen::Playing),
    ));
}
agile dirge
#

I'm ok making tests with it, but that's not end-user fit

bitter sparrow
#

i agree it's not great. but it does work

agile dirge
#

well yeah, both work

#

probably will use observer one in my projects

#

need to get the ecs patches in though

#

have you checked the issue?

bitter sparrow
#

skimmed it

#

add spawn_with to Spawn and you get what i wrote

agile dirge
#

what do you think about the traits? remove some add some?

bitter sparrow
#

adding spawn_with is pretty free btw. that part is like 3 lines of code

#

the 97 lines is impling a bunch of common traits for all the different types

agile dirge
#

yeah i skimmed the code and got the general idea

#

i had to consider this exact thing for the issue so i can understand it more than less

bitter sparrow
agile dirge
#

yeah, cause it's spawn empty + add

bitter sparrow
#

yep

#

instead of spawn empty + insert

#

it's the generalized version of spawn empty + insert

agile dirge
#

mhm

bitter sparrow
#

kinda canonical tbh

agile dirge
#

it's the command brother of spawn trigger lol

#

I'll sit down and crank few of those out tomorrow

#

I experimented a little but no internal impl worked for me

#

maybe you'll have an idea since you are fresh off commands

#

actually, we can probably use the spawn_empty trick

#

now that i think about it

#

get Entity early and pass it down for insertion

bitter sparrow
#

added a comment for spawn_with to your ecs issue

agile dirge
#

it's the same issue as with deferred spawning

#

just for spawning observers specifically

bitter sparrow
#

hmmm

#

you can do commands.entity(xyz).observe?

#

i thought it was just app.observe

#

actually i kinda remember that

#

love that there are 4 instances of fn observe and it's not a common trait as well

agile dirge
#

yup

#

it's mentioned in the issue

bitter sparrow
#

that is mentioned in your issue i see

#

yeah

agile dirge
#

but this is actually, much worse XD

#

cause if you have EntityCommands and you run .observe this spawns a new entity

bitter sparrow
#

hm so App::observe returns &mut App

#

Commands::observe returns EntityCommands

agile dirge
#

now you need to setup how to make both commands available

bitter sparrow
#

aaa they return 4 different types lol

#

er 5

agile dirge
#

api fresh out of the oven

bitter sparrow
#

the App version doesn't count tbh

#

cause all App methods return &mut App... I guess?

#

||maybe they shouldn't||

agile dirge
#

so the solution is actually very simple

#

described in the observer issue

#

wrapper that holds both, the original builder and the new builder

#

derefs by default to original builder

#

allows for .with(|builder| { ... }) to run stuff on observer builder

bitter sparrow
#

oh

#

EntityCommands::observe returns the EntityCommands of the target entity.. not the observer

agile dirge
#

yes hahaha

bitter sparrow
#

🐸

agile dirge
#

the design is very human

#

im gonna guess all of those were developed independently as needed

bitter sparrow
#

feels like there'd be some edge case

#

surface level though sure

#

i mean it's probably fine

agile dirge
#

you just implement drop

#

that's about it

bitter sparrow
#

you could also have .target() and .observer() to select one explicitly

agile dirge
#

that's how gizmos work

#

can, yeah, that'd be a nice api

bitter sparrow
#

commands.entity(entity).observe(reaction).observer().insert(xyz)

agile dirge
#

i would default to the original builder though

bitter sparrow
#

probably reasonable

#

i mean there's a use case for .with still

#

if you want to do something quickly to the observer, then get back to your target entity command chain

agile dirge
#

if we can return a proper EntityCommands I'm all down for it, with can be just an extra

#

but if we decide with is the feature we can take some shortcuts i think?

bitter sparrow
#

the wrapper type is probably like { Commands, Entity, Entity } right

#

internally

agile dirge
#

oh god, yeah it's be have to be something like that

#

i forgot command has to be in both

bitter sparrow
#

well the nice thing about it is

#

every method this type implements

#

will immediately resolve it down into an actual EntityCommands

agile dirge
#

yes but..

#

that's only for EntityCommands

#

what if your og builder is App

#

or World

bitter sparrow
#

that's fine

#

{ T, Entity, Entity }

#

where T: SomeTrait

agile dirge
#

would { C, E, E } be the GAT?

bitter sparrow
#

well not fine but it might be possible

agile dirge
#

for EntityBuilder

#

and others can have other "storages"

bitter sparrow
#

i dont see the need to abstract Entity?

agile dirge
#

short for Command, Entity, Entity

bitter sparrow
#

ok but E is the concrete type or a generic?

agile dirge
#

concrete

bitter sparrow
#

ok then fine yea lol

agile dirge
#

no generics there

bitter sparrow
#

o

#

well the GAT would just be C then right

agile dirge
#

but something like { T, Entity } is generic enough

bitter sparrow
#

er

agile dirge
#

T can be world, world can make commands

#

T can be commands

bitter sparrow
#

w/e the GAT is depends on the context

agile dirge
#

T cna be Commands + Entity (EntityCommands)

#

yeah

bitter sparrow
#

oh

agile dirge
#

T would be the type we're implementing observe on

bitter sparrow
#

wait so you're doing like

#

WithEntity<T> = { T, Entity }

#

EntityCommands = WithEntity<Commands>

#

our new type for .observe = WithEntity<WithEntity<Commands>>

agile dirge
#

and then implement .og_builder() .observer_builder() which can reassemble the WithEntity<T>

bitter sparrow
#

do you want to deref to T?

#

that could be an issue if T impls some methods that you don't want to be calling instead of the WithEntity variant

agile dirge
#

oh i know

#

T: GetCommands

#

is enough

bitter sparrow
#

is EntityBuilder not a WithEntity<Commands>?

agile dirge
#

layout-wise yes, idea-wise no

bitter sparrow
#

EntityBuilder vs EntityCommands?

agile dirge
#

i misspelled the name, i meant commands 🤡

bitter sparrow
#

ahh ok

agile dirge
#

this will be a bit clearer when we get some of the simpler traits in

#

the observer one is the hardest

bitter sparrow
#

mhm

#

i want Spawn

agile dirge
#

same

#

i'll add it tomorrow unless you do it first

bitter sparrow
#

what's your target milestone for this?

#

or at least some of it

#

it's a breaking change i assume

agile dirge
#

as much as i can force Francois to merge for 0.14.1

#

that is not controversial

#

insert/remove is pretty controversial

bitter sparrow
#

isn't that not possible because it's a breaking change?

#

you have to have the trait imported in order to use the method

agile dirge
#

prelude

bitter sparrow
#

i mean ok

#

"technically a breaking change"

#

with a usually no-op migration

agile dirge
#

it's an "internal breaking change"

#

aka

bitter sparrow
#

users don't have to use the prelude

agile dirge
#

a change xD

bitter sparrow
#

some libraries prob don't

agile dirge
#

well, they don't have to you're right, but that's the intended use case

#

Alice seems to have agreed on that

#

not gonna bother her more though, she's taking time off

bitter sparrow
#

is 0.14.1 meant to be before the jam or later?

agile dirge
#

before jam

bitter sparrow
#

hmmm

#

okay. tbh i could put my pr through and we can just delete util/spawn when 0.14.1 lands

#

in theory

#

regarding @rigid geyser's PR. i'd prefer if the changes were split into several PRs

#

some of the changes are uncontroversial.. some are more controversial

#

and i don't want to have to resolve all of the controversial stuff while the greater PR is looming the entire time, freezing other potential work and its uncontroversial parts

#

i'm in favor of simplifying, but not necessarily the way the PR does it

agile dirge
#

you gotta fight him about it, I'd be happy if it just still worked 😅

#

I'm not sure how high on cart's todo list the template is

bitter sparrow
#

ok. i think a practical plan would be to start by taking the uncontroversial changes from cart's PR and reimplementing them as separate PRs, and merging those through

#

then discuss the controversial bits

#

and just use cart's PR as a reference instead of actually trying to merge it wholesale

agile dirge
#

I'm for removing pub(crate) and flattening down the core/util/game

bitter sparrow
#

the PR isn't big, it just touches a lot of files and moves things around, so reimplementing should be easy

agile dirge
#

the rest i have no strong opinion on

bitter sparrow
#

i'm for removing pub(crate) and renaming GamePlugin -> AppPlugin

agile dirge
#

k

bitter sparrow
#

as for the flattening... maybe a partial flattening

#

like only flattening core would be fine ig

#

flattening util only looks reasonable rn because we only have ui utils atm

agile dirge
#

we may not have more in the template

bitter sparrow
#

so it could be flattened temporarily with the expectation that util may be re-added later

#

yeah

#

are we keeping pub(super) fn plugin or does that become pub fn plugin as well?

agile dirge
#

i'd say keep that

#

what id cart do

bitter sparrow
#

ill check

#

untouched

agile dirge
#

👍

bitter sparrow
#

actually no

#

two of the plugins had super removed

#

the rest did not

agile dirge
#

odd

#

just keep them all for now

#

when flattening we may need to change that

bitter sparrow
#

for sure. prs set to automerge on approve because uncontroversial

agile dirge
#

Jan is waiting for cart's

#

if we're doing cart's in parts then Jan's waits

bitter sparrow
#

okay, fair enough

agile dirge
#

or, since cart's coflicting now

#

if Jan rebases onto main I'm fine merging it earlier

bitter sparrow
#

alice said remove deflicker

#

so i'll make a pr for that

#

for flattening util

#

thoughts on keeping the top-level folder named util?

#

and just pouring util/ui/* out into util/

#

it's either that or ui_utils or w/e which seems like an unnecessary quantification

agile dirge
#

cart also took a lot of the core for flattening

bitter sparrow
#

yeah i will flatten core in a separate PR imo

agile dirge
#

oke

#

then yeah that

bitter sparrow
#

ok

#

@agile dirge resolved comment

agile dirge
#

okay sleep fr this time