Placing Furniture

So I need to write the actual furniture placement code in the client, making the object follow the mouse pointer, flipping it and sending it to the server, where we check if the player has said item and it is available and make sure they don't have too many items already placed, etc.

Still not doing great, if I am honest. Not sure I will be for some time, just going to muscle through it and hope things improve. Working on this project makes me happy. I am grateful I even have the ability to do so. I hope someone else gets something from it too.

Right, so starting from the client I will need to figure out how placing furniture works. I want to have it collide so I think what I should do is have a node that holds the furniture item and has an area2d that checks for collisions and looks to see if the furniture item is within placement bounds. This node should follow the mouse position and also use modulation to show if the item it's holding can be placed where it is.

I guess one way to do the collision check would be to have the Area2D clone the object's collision to itself. I would have to turn off collision on the object as well otherwise it would be bumping into stuff and that would mean you might have to navigate a maze just to place the thing.

I should specify in the furniture items what layer they should be placed on, we don't want rugs with Y-Sort for instance.

Today's music is...

Mm, good times...

Welp, I guess I should get started by adding the layer variable to the furniture items. (I should probably make tools for adding furniture later, like how I made all them tools for Geruterra's slimes, jobs, tools, etc. It will cut down on the amount of bugs. I'ma make a task for that.)

Side note: I made the login screen focus the username field when it starts and made the input look for a press of enter so you can login without the mouse. This was bothering me and I really should have sorted it sooner.

A place to start.

Now I need the node that will hold furniture for placement and follow the mouse cursor. Then add a function to the inventory to spawn the object in the scene.

It's showing up in the world and following the mouse.

Having some issues with the collision, but it's starting to come together. Anyway, starving... lunch time.

Can't place here.
Can place here.

Got the checks in for collision, also made collision disable and enable functions, turns out there's not one built in. Strange, right? Would have expected such a thing considering all the other stuff Godot comes with. But hey, I ain't complaining. Already able to be very productive with it, whatever isn't built in I can just add.

Lunch is over, dog is walked, cat is eating. Back to work.

So the next thing to do is write the code that plops the furniture down in the apartment and destroys the placement node. To do this I need to start on my input handler singleton (Yep, I am using a lot of those.) which will make sure we don't accidentally INTERACT when we want to PLACE, or any other number of weird things.

For now it's basically just a state machine we check/change to determine what the mouse can do in a given situation.

It's fine.

I originally was going to use enumerations and match statements but I just want to use strings so I can easily write if INPUTMGR.get_state() == "Move" instead of having to write ... == INPUTMGR.STATES.MOVE. I'll probably find a reason to change this later, when I write the input manager proper but for now I just need it to prevent accidental interactions when placing furniture.

Right click to flip.

Now right clicking while placing will flip the item. Also middle clicking will exit. I did find an inventory bug, I forgot to clear inventory before displaying so it will just keep stacking items up every time you open and close it. Gonna fix that.

The client side of this is now done? Maybe.

Plopped down that table there.

Now that I can place a table on the client side I need to do the server side, making sure to get the data correct.

You wish you were Two Tables Testiclese Jr. 

Collision is not getting enabled correctly for... some... raisin. I'll worry about that once I get the data over to the server. I know that it will be enabled after the client reconnects, it's just a problem with my collision off/on functions or where the enabling happens.

There is also a funny bug that happens when I flip and un-flip the table, it seems to drift from it's origin. It doesn't show visibly, but when I click and place it is now quite a distance from where I click. So that's TWO bugs for the price of ONE. What a steal.

And while debugging those two bugs I find another one.

Good, I thought this was too easy. I would have been worried if I didn't find some things wrong.

So, above you can see the collision of the table and the area2d of the furniture placement which copies the collider from the table. It seems that the table is floating above the placement node.

This is problem.

One thing at a time... I will start with our table hovering. For some reason the table's origin is not the same as the placement node's origin. I'll just change the position of the Area2D to match the position of the furniture item's StaticBody2D, right? Let's find out!

Nej!

So I am going to have to dig a little more...

Ah, of course. As I have the collider set as the child of the Sprite it's position is going to return 0,0. I should be using the Sprite offset.

That's got it.

Now, then... I need to figure out why it is when I click the placed furniture always goes to the same spot. I think it is going to 0,0...

Yep.

So that can be fixed by figuring out the position of the furniture placement node and sending it over to the furniture item when placing it... I think.

Indeed.

Two bugs down, one to go.

Why does collision not get enabled? Let's look at the collision layers/masks and find out.

Uh huh.

So as I understand it the layer and mask are 32 bits (bits being either 1 or 0). And I just copied the current collision to a pair of vars, then disabled it by setting it to 0... then when I renable it on placement I restore the vars.

I'll start out by writing some debug prints and opening the documentation on collision.

Ah, duplicate() is not a deep copy. That'll do it. [[IT'S ME, FROM THE FUTURE! This was not the problem.]]

I need to write wrapper that will copy all the modified variables OR find a way to reparent the furniture node without it bugging out. I have had some issues reparenting nodes in the past.

Not pretty, does the job.

Huh. I guess the issue wasn't duplication, I just can't assign the bits as easily as that. There was a function that would allow you to copy the bits and replace them once, it appears to have gone.

Looks like I may have to write a more complex collision copier? Gonna have a look around docs and whatnot first.

It's funny, the very first thing I tried was this:

how can i enable and disable collisions from script - Godot Engine - Q&A
how can i enable and disable collisions from script

No dice.

So I ended up writing code to copy collision masks and layers and then restore them. As it happens; Neither work.

Fuck yo physics.
U wot.

So uh... what?

I've tried all the things people say to try.
AH HAH!

So it was a combination of things. What I ended up doing was calling my collision enable function at the end of my copy function and using a very specific(but hidden from auto-complete) method.

VERY specific.

So if anyone else has this issue, you NEED to use get_node() and you NEED to use set_disabled() the hidden function... yes. Fuck.

This however, does break my collision check for placement.

I wrote a copy function for the collision node, fine now. Collision is acting as it should... until it breaks later, right? Anyway, looks like I will be leaving the server-side for tomorrow as it's 4:10...

But I will do a little test with something I wanted to try for a little midi player jukebox furniture item, that shouldn't take more than 10 minutes.

Some kind person wrote a midi plugin for Godot, some other kind person had a SF2 file that is exactly what I needed for my midi to sound like it did back in the day. Another thing I lifted from EO was the midi files for now, I always really liked the music, so I am using it to test my midi radio/jukebox furniture. I have no sprite for it yet but I will write some code to play random files from the folder.

I can't show you audio in a screenshot, but it's working. I still need to create a streaming radio system but this is pretty nice, I think.

Bitbucket
The Midi Player
Default Windows MIDI Soundfont | Musical Artifacts

I now have another furniture item I can place. It just needs a sprite and a DB entry and I am good to go. I'll make it so when you click it it toggles on and off.

Anyway, time to make dinner. Gonna make my commits and get out of here.