i juiced up the crude carpentry table: now it drops the items you craft, and materials involved in the crafting get a little animation. also it now shows the quantities of materials when you mouse over the crafting station for convenience

next is adding more items/recipes to the table to finish it out

i'm also gonna give splitting block game development into shorter (bi)weekly threads a shot. we'll see how that goes

#EniBlockGame #GameDev #IndieDev

RE: https://mastodon.gamedev.place/@eniko/115640571595780929

you can find the previous dev post here:

small change but on-screen overlays like crafting station material quantities are now sorted properly. took a bit of work to implement

this'll be nice to have later when there's multiplayer and nameplates and such

#EniBlockGame #GameDev #IndieDev

the first crude carpentry recipe is in! time to make some crude tables. they attach to each other to form various shapes and sizes! :3

#EniBlockGame #GameDev #IndieDev

doors are complex and we ran out of budget at block game development inc so you only get half a door and it's tidally locked to a single orientation, sorry

seriously though doors went from "oh this should be pretty easy" to "omg why is this so hard" SO QUICKLY

#EniBlockGame #GameDev #IndieDev

There is one thing that's making me reconsider "door in the middle of block" and instead doing it like minecraft, and that's what effect an open door would have on mob pathing since it's halfway between blocks and blocks travel between them

But I can probably work around it

#EniBlockGame

you can collide with entities (and so the door) now. took a while to figure out how to do efficiently

at the start of each tick, for each entity that has physics, collision boxes are stored for all collidable entities nearby. this prevents ordering issues and having to calculate collision boxes multiple times, which is expensive since it requires firing an event

atm its stored per chunk but i can go more fine grained later if it becomes a performance issue

#EniBlockGame #GameDev #IndieDev

finally wrapped my head around how to make blocks with different orientations so i could have east/west facing doors

and immediately got stuck again trying to figure out the implementation for making them 2 blocks talls :|

which is frustrating since i'm so close to being done with this dang door!

#EniBlockGame #GameDev #IndieDev

the problem with multi-block structures is every block in the structure needs to know the structure it's a part of. i can store that, but not as a simple block

so all blocks in a multi-block structure would be complex blocks. seems wasteful but i think it's just what i gotta do 🤷‍♀️

#EniBlockGame

the next (bi)weekly block game development thread can be found below: https://mastodon.gamedev.place/@eniko/115702717565225091
@eniko the negative space in a structure may be important too (thinking about a house 'teleported' into solid rock)
@eniko how much does a megastructure have of its own state? I'm guessing they have a type?
@sashabilton i figure they all just parent to the 0,0,0 corner block and any state the structure has will be kept on a block entity on that block
@eniko so blocks know their location? Would something as simple as a double linked list work?
@sashabilton yes it would. but its not so much a problem of how to store the information, there's lots of ways to do that, the problem is how to store it in the absolute most efficient way possible >_>
@eniko the challenge we live for 🤣 until it's out challenge. What is efficient in this case?

@sashabilton ideally blocks inside the structure would not need to store anything, so that simple blocks can remain simple blocks and stored wholly in the blocks array instead of having to have complex data that lives outside of it

i can come up with ways to do that, but they're more complex and inefficient in other ways

@eniko is a really good solution something you can defer until later and use just go with a quick solution? The richness you've already added to the game implies there is more to come and I wonder if you'd need to refactor any solution you do now because of additional functionality.
@sashabilton yeah, i can do the complex blocks thing for now and add optimizations later
@eniko then any block can transverse and find the structure parent but the don't need to know about all other blocks, just two.

@eniko No idea if that helps you, but just in case: in my game there are objects occupying several grid cells, but it's really nice if each entity is only attached to one grid cell. So I assign some cell as the "main" one, and it is the one the entity is attached to, and for each of the remaining cells I create a "proxy" entity which is a child of the main object and it occupies one of the extra cells.

Feels a wee bit dumb but actually works great!

@lisyarus that's basically what im gonna do. every block will store an offset that points to the parent block that knows the structure information

but that still won't fit into a simple block so it feels wasteful

@lisyarus @eniko I feel like every voxel game eventually reinvents TileEntities which is funny

@eniko I don't know how your world data is set up in classes/memory, but if you have something like a "minecraft chunk" class, save an array of data with that chunk that is a Dictionary<chunk-block-coordinates, entity-instance-id>, or another keyvaluepair collection.

When you need to check if a block is entity, check for its presence. Need the entity, query the entity-id value and use it to index your entities array elsewhere. (and keep the origin block pos as a property on the entity)

@eniko tricky, I guess I’d do it this way: assuming multi-block structures are contiguous, I’d encode 3 bits per block representing whether +x +y or +z are connected.

If you want to backtrack, check the -x (for example) and if its +x bit is set, then they’re connected. You can then flood-fill to find the whole structure. Assuming structures aren’t massive this should be fine.

If you have a single “root” block, then you can early escape when you find it. If structures are always convex you can make the root the most -ve block, only checking the 3 directions which haven’t yet failed to backtrack. Once all fail you’re at the root.

@bnut oh that's an interesting way of doing it. might be worth it as an optimization for small/simple structures

don't really need 3 bits either, 2 bits would do since you only need a single direction

@eniko yeah I just thought of the 2 bit thing too, but good thinking
@bnut with only 2 bits lost (13 left for the type) that's probably worth doing since most things would be like, 2 blocks wide or 2 blocks tall
@eniko by an overwhelming majority I expect most things are going to be 1x1x1, so that’d be the case I’d optimise for
@eniko I wouldn’t be surprised if the direction encoding is faster for quite large structures when compared to the overhead on all other block operations of storing a full offset to the root. I assume structures aren’t going to be the common case. The path length is O(n^(1/3)) for an n block structure. It’s also going to be smaller in memory so it’ll cache better.
@eniko if you want to get really tricky pack a full chunk’s structure bits together in 4x4x4 chunks with 2 x 64-bit integers. Then you can do simd via bit-twiddling for the root finding and flood filling (see bitboards). Although the complexity is likely not worth it (although the packing may be, as you’ll only fetch the structure data to traverse it, not the rest of the block data).

@bnut wouldn't having to loop up to 45 times to find the parent block be worse though?

every time the engine gets a block from the data structure the packed 4 byte value is inflated to the 16 byte block structure anyway

@eniko I meant the structure data would be stored contiguously, not interleaved with the rest of the block data. Although “worse” only matters in amortised terms. If almost every block is 1x1x1, and most multi-block structures are 2x1 then a representation causing a worst-case 45 step check happening on one frame with a 0.001% probability that doesn’t impact every other block operation (like building the render data, collision detection, etc) is still likely better, I expect.
@eniko if it’s convex you can probably even make it only 2 bits if you just encode which of 3 faces (-x/-y/-z) is closest to the parent (or none). Finding every block would require checking all 3 neighbors, but finding the root wouldn’t need that, it’s one less bit, and you can still flood fill to find the whole struct from the parent easily enough.

@eniko if you have 3 bits to spare (or 6 block types really), you could make mime-blocks that just point to one of 6 directions. A door would be a base block and a mime-block pointing down. A 3 block tall door would be the same with 2 mime blocks instead.

Problem is you'd need to loop to figure out the type.

@eniko what are your constraints saying every block needs to know the structure it's part of?
Do you need to interact with arbitrary blocks of the structure? (no big deal interactions can be slow)
Is this identity referenced in some update tick? (I'm thinking something like furnace progress, though you haven't indicated you've added anything like that, this might be middling)
Are they rendered differently when in a structure? (this is a big one because identity now impinges on your render loop)
@kevingranade if you break a block that is part of the structure, the entire structure needs to be broken
@eniko is that it? Can that trigger an update on blocks in sufficient range to include the "main block" that is complex and knows the locations of all the other blocks?
@kevingranade there's other stuff that might depend on the structure, for example doors will want to switch all blocks involved when interacted with

@eniko again "when interacted with" implies the lowest tier of update rate, so "when state is changed scan for the central block" might be reasonable?

Not trying to push for a particular implementation, Personally I do like the "two bits of direction to build a tree rooted in the core block" solution but it sounds like you have some issues with that as well.

@eniko

you could slap a top face on there, call it a gate or window and do something else before returning to a full door

@eniko IIRC the way minecraft does it (or used to do it) is by having separate 'upper' and 'lower' door blocks, where the interaction with one also changes the state of the other one? There were a lot of bugs that allowed you to get "half a door" at one point or another.

But also, "fence gate" is a thing too, so single-height doors still have a place (or single-height with a 1.5-high collider like MC does)

@eniko I am sure this is nothing short of infuriating to work on, BUT the feature is looking good and I very much think it will be better once you’ve figured out the quirks
@thatgalsilver yeah and it's helped me create a lot of new systems that will be important for all sorts of stuff later, so it's not wasted effort or anything
@eniko yooo almost there 

@eniko Looks fantastic.

Clearly the solution is to make the person less than one block tall and implement half height blocks instead.

@eniko Maybe spawn two interlinked blocks? Whenever you interact with one of them, send a signal/event to connected one to change the state.
@eniko you know, it's always kind of bothered me in other block-based games that the door is the ONLY thing that's a single object that takes up two blocks. Maybe instead you could just place multiple single-block door pieces on top of each other and have them all open or close together?
@eniko Will it support gates of NxM size as well? I want some giant ass town gates for my block game.
@hendric I'd like to add big gates somehow eventually but that's not really an early development thing