Build with MUD and React - Kooshaba
ETHGlobal·Mon, Oct 9, 2023, 12:00 AM
Join Kooshaba and Kooshaza from Lattice for a workshop titled "Build with MUD and React". We invite you to join the first virtual Autonomous Worlds hackathon, where participants will explore the potential of multi-author Worlds by developing onchain games, worlds, and art projects. Leverage the power of MUD, a new framework designed for ambitious Ethereum applications, and follow in the footsteps of dozens of teams that have already built unique projects with it, including OPCraft — an onchain voxel world, EVM Factorio, real-time strategy games, and more. By working with the MUD framework, participants will not only contribute to the growth of these worlds but also deepen the understanding of the concept of Autonomous Worlds and its implications in technology and digital collaboration. ----------------- Follow us: https://twitter.com/ETHGlobal Check us out: https://ethglobal.com Email us at: hello@ethglobal.com
Transcript
foreign [Music] hello everyone and welcome to the lattice Workshop build with mud and react joining us today is kushaba who will be taking us through this session and with that I'll pass it over to kashaba to get this session started all right short and sweet dope um I'm kushaba I work at uh lettuce I'm a mud contributor but also mainly a game developer at lattice working on our at our internal game Studio on internal projects my brother is here with me today kushaza uh he's going to be facilitating and collecting questions in chat uh he's just gonna let me know if there's like some burning question but like I can't be looking I'm just going to be doing a live demo today um since it is a live demo please bear with me I'm actually going to be for real coding this I'm going to try not to cheat and like look at the final product and just like go through the experience of like what using mud is like for real also I'm gonna be focusing on just like very practical tips on like just how to get done and react um I assume you know a little bit about react and I assume you know typescript I assume you know like a little bit about mud but I'm going to be going through like the fundamentals of mud as I'm doing this um the API is still in flux like it is like we just released mud 2 like today so please let us know if the API seems strange there are some like edge cases we haven't thought of um we are we're all stress testing together um let's get going today we're going to do the classic react to-do list um this is probably not a great idea to put on chain but it's a great example to like show data modeling in mud and have something a little bit more Interactive so I'm going to start sharing let's do it I can't share my screen can I get permission from uh someone Rory it's like it ah there you should be able to know okay thank you and uh let me know if this size is good for everyone I think I can bump this up a little bit okay all right so I made a starter kit here on GitHub uh feel free to clone it and try to follow along I'm gonna be going pretty fast I don't think you should expect to follow along but I'll Stick Around afterwards for questions and like we can try to get as far as we can together and I even have some like bonus things I want to add like later on that I think are really like really really cool but they're probably not going to fit into the now 25 minutes that we have so I've cloned the to do start what do we do first um we just run pmpm Deb this is like the the hot reloading that's going to start your Dev client it's going to compile your your contracts to deploy your contracts and you can just go to localhost 3000 and everything is hooked up um we have the mod Dev tools set up it's hooked up to the um to the local chain you see the block number ticking we're good to go great um I don't want this to become like a how to write CSS and react components tutorial so I basically did all of that beforehand I'm just gonna like blast those into the app we're going to be focusing on like how to hook up chain data into your react app and make it Interactive so we want to make a to-do list what's the first thing you have to add to Do's right um let's go with like how we are going to data model this to do structure and the first thing you do is you open up your mud config this is um if you if you went to Mud 101 it's like the brains of the entire application it's a really easy way to go into a mod app and just see okay what is going on what am I dealing with here uh first what maybe you need to do zoom in on the vs code a little bit yes I can thank you how's that I think that's a lot better chat looking good oh I forgot thank you um cool so technically there is a there's a key and a table um I usually just use the default key default key is bytes 32 works for anything you don't need composite keys with like basic structures um each to do is going to have an auto-generated ID I'll show you how to auto generate that ID layer the scheme what does the schema to do the basics of it is like there's a body to the to do so let's just do a body and uh make it a string right cool done one little Quirk of mud Dynamic Fields need to go last in the schema so we're going to add one more field which is like whether or not it's done and that needs to go before the body cool cool this is all done okay so I mean hey sorry but could you actually just zoom in a little more on both BS code and the uh and the localhost real quick we got some other people say it's it's too small yes yes I have a really pick monitor I apologize also I am I am bragging yeah I have a huge monitor I'm so very cool um okay so we we modified our mug config mud Dev automatically redeployed our uh tables it auto-generated a table and we can see in our Dev tools that that table it was registered somewhere I can't see it because the zoom thing is behind it but okay regardless it exists trust me so now we're going to make a system to interact with this table once again I created the scaffold beforehand for the system but a system is just a contract that inherits from the system interface and we're going to just declare I am going to turn off copilot for this you're probably going to be wrong copilot okay so we're gonna add one normal function which is just add to do um butter string memory body I'm gonna make it public as long as you make the function public it'll be available in the client um now the first thing we need to do here is we need to like actually get an ID to assign to this to do because every every Row in our table needs an individual ID if you were paying a close attention to the mud config before I had this unique entity module loaded um quick background modules are just like little composable pieces of code that we have built into mud they're not like strictly necessary in every World which is why they're not Auto loaded but they're very helpful in certain circumstances in this case unique entities will just generate it basically stores a nonce and it'll generate incrementing IDs for you so you don't have to do that you know that busy work yourself so I had it loaded here I imported it over here so I'm going to be able to say bytes32 ID equals get unique entity great okay so we have the ID now let's import that to-do table that we created before so what's important to do and then also it will auto-generate a struct that is the same schema as the to do that we created and that'll be helpful when setting this this data um all the auto-generated files live in a code gen folder just so you know hey you probably should not touch these uh these files that is pretty helpful for me okay and then let's do to do dot sets first argument is the ID second our second argument is the content of it let's do this uh body is body and done is false seeing as if you if you're putting the to-do in brand new you probably have not done the to-do yet okay once again let's go back to Dev okay it picked up our new system it picked up our new function the local localhost should be up to date and now let's get something on screen make it look good I have the entry point is app.tsx this is like where I set up this little structure here um I want like I said I made these forms beforehand so let's just add this form blam we have just a basic react component that you know stores needed an input and this plus sign does nothing right now cool great the the next step after you make a system function on chain is to actually link that system function up on the client this is kind of a convenience thing you could just use this world send function manually um world send is this it it has types inside of it and it will know about all your system functions that you just created because it auto generates typescript definitions inside of Worlds and to match all of your contracts but just for cleanliness it's like way easier to do let's make a a function here to wrap that now World send and to do and the next argument is an uh array of arguments to provide to the contract and we just want to put a body in there and we add this to do great now let's go over to our to-do form right now it does nothing right now all there is is an on-change book here that is changing the local state we want this on form button to actually submit it when it is pressed now uh here's the first bit of magic with react like you can use this this hook uh use mud use mud we'll just grab all of the mud Auto generated code all the mud State put it into one hook and you can um access everything here so we have our system called available and we have that to do available as well so now we can just add to do the new to do that we were just typing and just so that this is not really annoying let's clear the the current to do so you don't have to keep backspacing every time you want to add something um all right let's add our first shoot do great so the the transaction executed we see that it was successful and we can check here what tables were actually set this one's obvious it's like the to-do table it has a key of one this is the first um key that we generated from that get unique entity um here's one that might not make sense unless you remember like yeah we have that unique entity module um it's setting its own storage this is like not super helpful for you but if you're installing a bunch of modules it's it's nice to know hey what are these modules doing secretly in the background is it like accessing too much storage do I need to clean this out maybe the dev tools a little bit more too so people can get a good look at the magic going on there okay there you go all right I need to like do some in Tetris with Windows here because now I can't really see uh okay is this is that good I think that's probably the biggest I can make it yeah this is good okay so the transaction is successful and technically the state is in our client right now it's just not available here so okay let's let's go grab our or use mud hook again grab that magic context and then I will grab the to do component okay huge disclaimer we we mix the usage of components and tables everywhere right now mud started as a pure ECS framework it is now based on tables and ECS is a subset of this table structure I still use ECS during game development that's why components are like everywhere in the API um so this really means tables take my word for it but this to do matches the to-do table that we just defined in our config and there's another uh Magic query or magic hook that you can use to grab all of the things that have to do's and that is use entity query this is like kind of a DSL of describing a query given like certain tables that it's composed of in this case we have has to do very simple it's going to grab all the IDS locally that we know about that have to Do's associated with them and if we render those right here to do IDs blam one shows up here not the information we wanted it's just the ID but we can for sure know hey there is a to do and if I add another one another one will pop up so there are two to do's okay so now let's actually render these things uh I'm going to iterate through the to do IDs now the first step here is to get the actual data from these to do's and then with that you use this method called get component value strict um there's two versions of the method strict means hey I for sure know that this this ID has this table please just get it for me it is not possible that is edit is null um if it is null if you were wrong uh it will crash it will throw an error there's also a a not strict version of this just get component value which will give you know value or undefined that's if hey you don't know if this ID actually has the value it's just a little more difficult to work with because then you have to do not in all checks everywhere um okay so we have the to do data which is the same schema this is okay this is not giving type hints right now but I made a to-do item before we can throw this to do item this to do data into the to do item I believe this also requires the ID and let's give it a key also because this is reacts what are you complaining about property content okay I named a Content before I'm going to change all that to body now all right here we go the things I've showed up that another one just to prove that this is real this is not not fake uh I don't know uh when hackathon by yacht right we are adding to do's but the check box here is not done right and we can't click it to make them done because we didn't write that system yet let's now add a system for actually changing that so we're going to add a new function toggle done now this one's going to take just the ID that we generated before let's just make this explicit to do ID public again and simple okay here's another fun thing about the the auto generated tables we generate some utility functions for you so you could just say set done instead of reconstructing the struct in memory and shoving it back into the to do you could just do this and it will handle that in the background for you um and we're going to say instead we're going to toggle it so not to do got dot get done to do ID and I that is the wrong name okay so that is toggle done I think that should work all right okay so the to-do's just disappeared that is because we just modified a System Mod picked that up it redeployed the contracts we are now using a new world address in our client technically that old world exists there is a folder somewhere we have all your Old Worlds if you want to go back to them you can hard code that world into your url parameter but generally if you've if you've just modified your systems you probably want to use those systems immediately we push you onto a new world and you have new storage to go along with it let's just add to do again because we want something to interact with to add this check mark we're going to go add the local assistant call again and worldsend should have picked up our toggle done now one more thing that is a bit annoying right now where I'm going to add an API function for this or if or fix this soon but you need to um re-pad the ID when it goes back into the contract right now I added a utility function for you here though um and we have to do that and then we toggle done okay now to hook that back up we go back to our to-do item we have this check box here I already have the on change registered let's grab our use mud book one more time and we are going to yeah what is it e dot Target dot value right so is it checked this is a real question I forgot forget HTML I think so okay let's see no it's not what is checked please someone send help what is this oh I guess I just used done all right nobody panic I'm not panicking oh wait I'm so dumb this we have to give it the ID so the matter okay cool we've set the transaction toggle done it then comes through from the contract that's client storage the checkbox checkbox is checked now okay here's one thing that we just did um technically this is a multiplayer to-do list and if we open up localhost 3000 in incognito window we can see someone else's to Do's right and I can check this as done and that's a it's a horrible a horrible thing you can just add to do's and then you know check off other people's to Do's we can't allow this this is this is a crime against humanity so let's add some permission to deduce just one extra thing let's remodify a a an existing table so I'm going to add an owner field to this bytes 32. so now we are going to when we added to do we're going to set who owns it based on the address of the person owning it to do system [Music] and I once again um I made a utility function for this address to entity it's just casting an address into a bytes 32 in this fancy way it's really nothing but it is annoying so I gave that to people um now okay here's one other important thing you cannot please do not use message dot sender raw in a mud system um you can it's just not going to return what you expected since the world is this single entry point of mud message.sender is going to be the world address and that's probably not what you were going to uh what you were expecting when you called it instead we have our own internal message.cender which stores the address that entered the mud world in this case that is like the actual uh wallet address that we used and okay we can see our to-do data is now false because we have no owner associated with it now let's set the owner to owner and then now with toggle done we can grab here bytes 32 sender is this and let's require that the sender equals to do dot get owner to do ID and otherwise it is an unauthorized action well I think this all checks out once again it redeployed so it cleared our storage do this one more time okay yep yep everything's looking good I'm going to check it it is done now let's try to check it here does not work authorized I believe you could go into your console and you can actually see the error here yeah execution averted unauthorized um but I can make my own to-do I can check that off here but I cannot check it here okay that is the the at the end of the scheduled features I have some bonus features that I want to do but I'll maybe I'll do one more after after questions um are there any pressing questions that people have yeah if you have any questions please feel free to take yourself off mute and ask or if you don't want to ask feel free to type in the chat just just straight to bonus feature all right I mean I'll do it it's it's fun I I like this um this is more of like a a purely user experience thing that we have built into mud that I think makes it uh like the clients are Snappy so obviously when you're clicking done here um there's that little delay like you're clicking the transaction is being sent you're waiting for confirmation in this case there's like a zero percent likelihood that this transaction is going to fail other than like you know a reorg or or like some like gas error so let's make our client just optimistically say hey this is probably going to succeed and let's tell the mud client that it's going to succeed before the confirmation even comes through we have a built-in way of doing this with mud so we have this concept of client components so we've auto-generated these components here and we're setting that into client components but we can override those components with our own components where we can create purely client components just for client-side state in this case we're going to override the to do component with uh an overrideable component now what this means is we have now um like injected some methods onto to do that say Hey I'm going to set your value before I actually know the real value and just pretend that that's real and then all of the all those like overridden or overrides will get wiped this again real chain State comes through um this is going to make it so that when we check this checkbox it immediately happens and they don't really need to worry about the transaction in the background and now really all we need to do here is Okay so we've we've toggled done like actually let's go into our uh actually let's just do it here we can now like set the component manually um with the to do the ID and okay I guess this yeah we have to just grab the actual component from um here we do need to grab the should you data you I yeah hey kushaba we have one participant who is not sure like what exactly we're overriding could you elaborate on like uh like where they generate exponents are Mobile World providing exactly so we are overriding the the done State locally because we know that once this transaction goes through the done state is going to be true if it was false but we have to wait for that entire flow we have to wait for the transaction to get sent to the chain we have to wait for confirmation and then it gets sent down and then we know oh you know it's true um we can short circuit that whole process and just set into the client done is true does that does that make sense also I think I was doing this wrong yeah it's add override yep and then we have to set the entity here which is this ID and value which is to do igna ah this is possibly undefined I mean we probably don't want to render anything if we have no data so that's fine okay so if you remember before when we clicked this there was a slight delay now it happens immediately um but the transactions are well where the transactions are family right because that was unauthorized there's a little more complicated because of the unauthorized methods but if I click the one that I own the transaction goes through otherwise you see what happened it's instant now that's that's the whole thing this is not super impressive with a to-do list but I promise you if you're making a world with players in it and you want to move around attack things pick things up um this is like gonna make the difference between someone like closing out of your app and like being engaged and feeling like they're a part of the world um yes that was the bonus feature that was the secret hidden feature and it's still 3 30.
so I guess it's fine awesome we did have a question um from Albert could you explain when a new world automatically gets generated is this relevant to the test net or the main net um this is all right this is purely for development like if you're on mainnet you're not going to be running like mud Dev because that's going to be like constantly redeploying your contracts which would be you know costing you money um this is purely for local development if you change a system file or your convenience it is going to automatically redeploy your contracts yes so in this override scenario if the transaction does fail it will cleanly like remove that override and revert back to the original like the the correct value um it knows to listen for that transaction and to say like hey like something messed up it looks like all the other questions have been answered by alvarius or Shazam uh oh yeah so setup is yeah setup is a promise yes technically set up as a promise um setup is really fast and we also have this concept of a loading State table like a purely local table that you can hook into that says like the actual percentage of the loading State and if you come to my phaser Workshop I'm going to go into that a little bit where you can like make a proper loading screen and like even have the the app like progressively load as as loading changes um but generally setup is like pretty fast because setup doesn't wait for loading to be complete it just starts the loading process Bruno that is a fantastic question about migrating tables in production we have no great way to do that right now I would love to talk more about it and you should make a live world and get into this situation and we can work through it together that's my answer um yeah and polish how difficult it stays here to pick up okay I'm a big fan of phaser it's not as powerful as Unity your game is not going to look as great as Unity but it is an incredibly uh good prototyping tool and it's also incredibly easy to get it in front of people because it's just browser native like Unity can technically compile to browser code but I don't know if anyone's ever done this before it is like not the intended purpose of unity and they did not make it super easy phaser on the other hand has like really tight integration with the browser it is it was made for browser first um we have really good Integrations for it and we even have this uh we basically have a built-in infinite canvas in our phaser integration where it's like you can just scroll through this infinite World and set the positions on objects and it will overload the browser by rendering every single object in this infinite World which if we're creating autonomous worlds is pretty important um so once again during the workshop I'll explain this but like we have an object pool that you have access to where you can dynamically set Sprites and then if they go off screen they will just get not rendered um that didn't even answer your original question which is it easy to pick up yeah it's easy to pick up it's like a really simple API um it's like it basically is one of those things where it's you can use as much as you want like you could you could use the bare minimum of it and like not even know what phaser does and then progressively pick it up more and more as you go along so I think that's why it's easy to pick up awesome I think yeah everything else was covered so if there are no other questions uh thank you all for attending and thank you uh kushaba and kushaza or uh demoing this as well um and uh yeah there are a few more workshops for us today so uh we'll hope to see you again in a few minutes few hours cheers thank y'all peace thanks for coming thanks everyone
Automatic transcript — names and jargon may be misspelled.