Logic World Wednesdays: The Edition With Precisely 1264 Words

by @MouseHatGamesDeveloper 2 months ago (edited 2 months ago)

Variable peg counts - Jimmy

For a long time, there’s been a strict rule hardcoded into Logic World: a component cannot gain or lose pegs after it has been created. Each component is initialized with some number of inputs and outputs, and it will always have that number of inputs and outputs.

This rule limited what was possible with the game’s components, and necessitated some awkward workarounds. For example, we needed to have six separate Panel Display components, each with a different number of inputs.

This simplification helped keep the codebase manageable when I was a much greener programmer, but today I am battle-hardened and I know how to effectively manage complexity. Building on all my refactoring work from recent weeks, this week I finally lifted the limitation. Components can now dynamically gain and lose pegs while placed in the world. Here’s a quick demo:

I’m planning to use variable peg counts to condense Displays down into two component types (Standing Display and Panel Display). I might also condense AND gates down into one component type (currently we have AND Gates, Three-Way AND Gates, and Four-Way AND Gates). But the main reason I’m excited about variable peg counts is because I need them for a couple brand-new components I’m working on.

Website settings - Felipe

I always love it when websites and other apps allow me to customize how they look and behave, and this week I decided to add this feature to the logicworld.net website. Now, if you go to the website settings link on the navbar dropdown you will be able to change a few settings like the website theme (including a new automatic option!), time label format, etc.

site settings.png

Little misc website improvements - Felipe

There are a few more fun little improvements I made to logicworld.net this week. First, comment replies are now auto-saved in local browser storage if you don’t submit them. If you type up a comment, but the page is closed, your comment draft will still be there when you come back to the page later. This can be handy if the page gets closed accidentally, for example if the browser crashes. There will also be a browser popup now if you try to close a logicworld.net tab with an unsubmitted comment typed up, to confirm that you really do want to exit the page.

Additionally, I’ve added a nice little box at the bottom of each post on the site with a shortened link to it, for easy post sharing.

url box.png

I’m having fun with all these incremental improvements to logicworld.net. Hopefully when the game launches, the site will be supremely pleasant to use, and an ideal place for the community to share creations.

Custom data improvements - Jimmy

This week I’ve been improving the game’s Custom Data system! As a quick refresher in case you’re not a dedicated scholar of this blog, custom data is additional data associated with a component that is specific to that component type. For example, a circuit board stores three values in custom data: length, width, and color. A Singer also stores three values: instrument, note, and volume. Custom data is stored internally as raw binary, but the code has utility functions for working with the data as if it were standard numbers/colors/booleans/etc.

I started out with a medium-sized refactor to the custom data system, cleaning some cruft and making the code more streamlined. I then added two new features to custom data:

Partial data updates

Previously, when a component’s custom data changed, that change was passed around as a complete replacement for all the custom data. So if you changed a circuit board’s color, you would also be sending around data about the board’s width and height. This was pretty much fine because in almost every scenario a component’s custom data is very small, less than 16 bytes. However, I’m planning to add some big ROM components soon. These will have much bigger custom datas, probably in the hundreds of bytes. We need a more reasonable system for propagating custom data changes to ROM components, as well as any other large-data components that might be added in the future, by us or by mods.

So, I’ve implemented a system for updating just a small part of a component’s custom data. You can now send around nice small efficient packets that say, for example, “starting at index 52, replace the next five bytes with 36 39 6c 6f 6c”. That small and specific change will be propagated throughout the server and all connected clients, and code running on that component will be notified of the update.

Partial data updates work but are currently unused. I might implement it on Labels, though, as Labels can contain a lot of data if you type a lot of words into them. I’m really looking forwards to implementing this system on the ROM components, but that probably won’t be for a couple of weeks.

Better nonsynchronous data

Not all component data is stored in custom data and synchronized between server and client. Some component data is tightly related to logic, often updating each simulation tick, and the client does not need to know about it because the client does not do any logic calculations. The term I made up for this data is “nonsynchronous data”. Currently, nonsynchronous data is used only in Delayers, to store the count of how many ticks they’ve been powered or unpowered for. However, there are many other potential use cases. If you had a RAM component, storing arbitrary values that can be read and written by circuitry, you wouldn’t want to synchronize those values with connected clients; that would just be wasteful.

The main issue with nonsynchronous data is that there are instances where we really do need the most up-to-date values for a component to be stored in CustomData. The first instance of this is when the game world is saved. Nonsynchronous data is not saved, only custom data is, so the nonsynchronous data must be copied into custom data in order for it to be saved. I implemented this a while ago, and it’s been working nicely for Delayers: when the game is saved, all Delayers serialize their current timing value and store it in their custom data.

The second instance is when the client saves a group of components so that they can be loaded later. Ever since I originally implemented nonsynchronous data, there has been a bug here: if you save a group of components that includes Delayers, their timing values will be inaccurate when that group is loaded again. If you set up a clock with precise timing, saved it, and loaded it, the loaded version would be broken.

This week I did a refactoring pass on nonsynchronous data, and I also finally implemented a solution for that second issue. There’s now a system for canonizing the custom data of a tree of components: you can say “I need up-to-date custom data for this component and all its children” and any components in that tree with nonsynchronous data will serialize it to custom data. I’ll be able to call this function before saving a group of components, ensuring that they are saved with the most up-to-date values.


We’ll keep releasing these weekly updates right up until the game comes out. To make sure you don’t miss them, you can sign up for our newsletter. Be sure also to wishlist Logic World on Steam and join the official Discord.

See you next Wednesday!

More Logic World Wednesdays


5 comments
@Ecconia 2 months ago (edited 2 months ago)

Nice a big LWW since a while :)

Dynamic peg count

Connector amount change only makes sense on user interaction.
But would your code now also support to change it on a special trigger, such as a logic state (does not make much sense, but am curious anyway)?
I do not see any usecase for that, but yeah.
But technically one could just replace the component and restore all values - yeah I can tell why you prefer that to be native :P
But the complexity of this change should be pretty much on the same level as actually resizing a component, which you already can do.

But yes! Its a great improvement to have this also for AND gates, I like it a lot.

Website settings

Already liked expressed my liking. Opinion stays the same :)
Many good changes are currently happening to the website.
Always keep the change-log up to date, for us to provide better feedback.

Custom data improvements

Actually not much to say.
But I am a bit confused here, are you when data changes always and instantly recreating the binary custom data? Or just the internal fields? But yes, if its not being sent, one does not need to create the serialized representation of it.

“new”/ROM components

This one is pretty much a bomb…
I wonder which other components you have in your mind, besides a ROM component.
What changed your mind? I thought you love/like big builds with many wires?
What happened to the default answer: “A mod can add that…”
But yes I see the point, building a ROM can be a hurdle for inexperienced players, while at the same time its also a black-box.
To be straight I would probably not use it, but for some it might be nice.
Big memory is just more fancy and takes a lot of design work. Also takes a lot of CPU/GPU power I assume.
So I am a bit confused and would like to know the details about this change of mind. And maybe if you also see future of other “complex” components.


While you are having a refactor strike, when is it time to take care of the relays? :P
(The BUT YES edition…)

 3
@JimmyDeveloper 2 months ago

But would your code now also support to change it on a special trigger, such as a logic state (does not make much sense, but am curious anyway)?

Yes, this is supported :)

But the complexity of this change should be pretty much on the same level as actually resizing a component, which you already can do.

It was significantly more complex, actually. Component size is just a client-side, aesthetic thing. Inputs and outputs however are also part of the server-side simulation, so there are a lot more systems they interact with.

But I am a bit confused here, are you when data changes always and instantly recreating the binary custom data? Or just the internal fields? But yes, if its not being sent, one does not need to create the serialized representation of it.

For most components, any time any part of their data changes, the changes are instantly serialized and then synchronized between client and server. However for some components (currently just delayers), changed data is only serialized and then synchronized between client and server at the times when that is necessary. Hopefully that clears things up for you?

I wonder which other components you have in your mind, besides a ROM component.

;)

What changed your mind? I thought you love/like big builds with many wires?

I love big complex builds with many wires when that complexity is interesting. However, with the current game systems, building ROM is not interesting at all. It’s boring, messy, awkward, and difficult. And it’s particularly difficult to edit ROM after you’ve created it. There’s also one single objective best way to do it, so after you’ve done it once there’s nothing new to discover or innovate on.

The gameplay of building ROM by hand sucks, and I want to streamline it so that you can spend more time with the actually interesting and fun parts of the game.

And maybe if you also see future of other “complex” components.

I think ROMs will be the only components of significant complexity in vanilla LW. In contrast to ROMs, other big logic systems – like RAM or FPGAs – are extremely interesting and fun to build. There are many different ways to build them, each with advantages and disadvantages; there’s tons of room for innovation and novel solutions; and there’s nothing about the functionality of these systems that necessitates an unpleasant messy wire jungle. Other big systems have good gameplay, and I want to preserve and highlight that gameplay rather than remove it.

That said, if you want to play with prefab RAM or FPGAs or whatever, our extensive modding system will be there for you :) it’s just not the experience I want to highlight in vanilla.

While you are having a refactor strike, when is it time to take care of the relays? :P

Hopefully this week!

 3
@Ecconia 2 months ago

Oha, actually totally missed your answer here.
Yes it did clear up all questions - thank you very much.

 1
@JimmyDeveloper 2 months ago

I’m really happy about the auto-saved comment drafts we have now! I’ve had a couple of very bad experiences on websites without auto-saved comment drafts, where I spent minutes typing up some comment, but I accidentally closed the page or clicked the back button on my mouse or something, and all my hard work was erased.

Go ahead, try it out – start typing a reply to this comment, then close the page, then come back here. Go to reply to this comment again, and your auto-saved draft will be waiting for you :D

 3
@Vykori 2 months ago

Welp it doesn’t seem to work on mobile lol

 2