Hacking JSX: Building in Minecraft with React

Rate this content
Bookmark
SlidesGithub
The video discusses how to create builds in Minecraft using JSX, a syntax extension for JavaScript that looks like HTML. It highlights the benefits of using JSX for building a custom DSL, noting its familiarity and the ability to leverage existing tooling. The apply build function converts JSX builds into game elements, similar to mounting a React tree to an HTML DOM element. JSX can be used outside of React by creating custom handlers to replace React.createElement(). The video also explains how bun supports real-time rendering of builds defined in JSX. It concludes by encouraging viewers to share their JSX creations and provides a link to the source code on GitHub. Key topics include JSX syntax, JSX transpilation, custom DSLs, JSX in Minecraft, and bun tool usage.

From Author:

When combined with a custom rendering function, JSX can be used to quickly build a custom domain-specific markup language. I will show you how to approach this using the example of creating builds in Minecraft.

This talk has been presented at React Day Berlin 2023, check out the latest edition of this React Conference.

Watch video on a separate page

FAQ

JSX is a way of writing pseudo-HTML code within JavaScript code. It needs to be transpiled into something the browser can understand, typically a call to React's react.createElement() function.

A domain specific language (DSL) is a programming language designed to do one thing particularly well, unlike general-purpose languages like JavaScript that can solve any problem. Examples include SQL for databases and HTML for web page structure.

JSX can be used to create builds in Minecraft by converting JSX syntax into game commands. This involves creating a custom JSX handler function that converts the JSX into an array of objects or commands understood by the game.

There are two main reasons: 1) Familiarity with JSX means there is no steep learning curve, and 2) Existing tooling for JSX, such as parsers, linters, and IDE support, can be leveraged, eliminating the need to write custom tools.

The react.createElement() function is what JSX is transpiled into when using React. It converts JSX syntax into React elements that the browser can understand.

Yes, JSX can be used outside of React by using a custom function that has the same signature as react.createElement(). This allows for custom behavior and use cases.

The intermediary representation is a way to convert JSX syntax into a different format, such as an array of objects or classes. This format can vary depending on the problem being solved.

In Minecraft, blocks are placed using three coordinates: x, y, and z. Each block also has a type, defined by an ID value.

Using JSX for creating custom languages offers advantages like familiarity, reducing the learning curve, and leveraging existing tooling for parsing, linting, and IDE support.

The source code for the JSX Minecraft build project is available on GitHub.

Felix Wotschofsky
Felix Wotschofsky
7 min
12 Dec, 2023

Comments

Sign in or register to post your comment.

Video Transcription

1. Using JSX for Minecraft Builds

Short description:

Hello React Day, I will be talking about how we can use JSX to create builds in Minecraft. JSX is a way of writing pseudo-HTML code within JavaScript code. It can be transpiled into something that the browser can understand. JSX is not limited to React and can be used with other functions. It allows for the creation of an intermediary representation that can be converted into commands for Minecraft. Using JSX for building a custom DSL is beneficial because it is familiar to developers and has a low learning curve.

Hello React Day, my name is Felix and I will be talking about how we can use JSX to create builds in Minecraft. Furthermore, I will also be exploring the idea of using JSX as domain specific language in general.

So first of all, what even is a domain specific language? A domain specific language or DSL for short, it's a programming language that is designed to do one thing particularly well. And that is in contrast to a general purpose programming language such as for example JavaScript, which in theory is able to solve every problem.

So take for example SQL. SQL is very good at interacting with databases in a very concise manner, but it is overall limited in functionality and isn't able to solve every problem. Or in other words, SQL isn't Turing complete. Another very famous example for a domain specific language is HTML. HTML is designed to define the structure of a web page. But since we are talking about JavaScript and React here, we aren't able to use HTML directly. Instead, we use something called JSX.

JSX is a way of writing pseudo-HTML code within JavaScript code. But since browsers don't natively support JSX, this JSX syntax needs to be first transpiled into something that the browser can in fact understand. And this is, in the case of React, a call to a function called react.createElement() which then, in the end, represents the same content as our JSX does. But the great part about JSX is that we aren't limited to using it with React. Instead, we can use whatever function instead of React.createElement() to then use JSX and add custom behavior to it.

So in this case, I first of all create a custom block component which then gets fed into my custom JSX handler function, in this case a minecraft JSX function. And this works because my function has the exact same function signature as react.createElement() Therefore, I can take my function as target for transpolation from JSX. In this example here, I've expanded this example and also wrapped it in a fragment. And now the idea is that with my custom JSX handler, I'm able to convert this JSX syntax into an array consisting of plain objects. But now that's the important part. Depending on the use case or the problem that you're trying to solve, this intermediary representation may look completely different. You may want to use classes instead or possibly preserve the nesting that was created by JSX. This intermediary representation will greatly depend on the problem you're trying to solve.

I'm able to convert this array into a set of commands which are understood by the game and then turned into an actual build within Minecraft. In case you don't know, Minecraft is a 3D sandbox game where you can place blocks wherever as defined by three coordinates, x, y and z. And each block of course has a type, in this case it's defined by this ID value.

So therefore in general, the question why would you use JSX for building a custom DSL. The first reason is that you and your colleagues are already familiar with JSX. Therefore there isn't a great learning curve and it's easy to adopt.

2. Using JSX for Minecraft Builds - Part 2

Short description:

You can rely on existing tooling when using JSX, eliminating the need for custom parsers and enabling linting and IDE support. The apply build function converts JSX builds into game elements, similar to mounting a React tree to an HTML DOM element. Building with JSX is easy and familiar, as demonstrated by the readable house component. Running the app with bun allows for real-time rendering of the build. If you create something using JSX, please share it with me. The source code for this project is available on GitHub.

And probably, number two, way more important, you can rely on existing tooling. So for example you don't need to write a custom parser for transforming your JSX markup into the final result. Instead, you can just write that JSX handler and be done. You don't need to write a language parser. And also you can rely on existing tooling for linting or also for IDE support, because JSX is widely supported across tooling.

So, what does this look like in a greater picture? Here I've created an apply build function which in the end is what converts my build, as defined here in JSX, into something that's actually in the game. And you can think of this similarly to mounting your React tree to an HTML DOM element when using React regularly. And now with this village component, this is just plain JSX, as I told you. It is very easy to get into the idea of building something with JSX, because you already are familiar with it. Like here, this house component is just a collection of other components, that is, as I think, very readable overall.

So now if I run this app with bun, because bun has built-in JSX support, I can effectively watch as my build sort of gets rendered to the game. Ok, that's it. I hope I could give you a little insight of an idea of how you can use JSX for whatever purpose you want. If you end up building something, or building a custom language effectively on JSX, I'd love to see what you are creating. So please reach out to me, I'd love to see it. And the source code for this project that I just showed you is available on github.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

A Framework for Managing Technical Debt
TechLead Conference 2023TechLead Conference 2023
35 min
A Framework for Managing Technical Debt
Top Content
Today's Talk discusses the importance of managing technical debt through refactoring practices, prioritization, and planning. Successful refactoring requires establishing guidelines, maintaining an inventory, and implementing a process. Celebrating success and ensuring resilience are key to building a strong refactoring culture. Visibility, support, and transparent communication are crucial for addressing technical debt effectively. The team's responsibilities, operating style, and availability should be transparent to product managers.
Fighting Technical Debt With Continuous Refactoring
React Day Berlin 2022React Day Berlin 2022
29 min
Fighting Technical Debt With Continuous Refactoring
Top Content
This Talk discusses the importance of refactoring in software development and engineering. It introduces a framework called the three pillars of refactoring: practices, inventory, and process. The Talk emphasizes the need for clear practices, understanding of technical debt, and a well-defined process for successful refactoring. It also highlights the importance of visibility, reward, and resilience in the refactoring process. The Talk concludes by discussing the role of ownership, management, and prioritization in managing technical debt and refactoring efforts.
Monolith to Micro-Frontends
React Advanced Conference 2022React Advanced Conference 2022
22 min
Monolith to Micro-Frontends
Top Content
Microfrontends are considered as a solution to the problems of exponential growth, code duplication, and unclear ownership in older applications. Transitioning from a monolith to microfrontends involves decoupling the system and exploring options like a modular monolith. Microfrontends enable independent deployments and runtime composition, but there is a discussion about the alternative of keeping an integrated application composed at runtime. Choosing a composition model and a router are crucial decisions in the technical plan. The Strangler pattern and the reverse Strangler pattern are used to gradually replace parts of the monolith with the new application.
Advanced Patterns for API Management in Large-Scale React Applications
React Advanced Conference 2021React Advanced Conference 2021
20 min
Advanced Patterns for API Management in Large-Scale React Applications
Top Content
This Talk covers advanced patterns for API management in large-scale React applications. It introduces the concept of an API layer to manage API requests in a more organized and maintainable way. The benefits of using an API layer include improved maintainability, scalability, flexibility, and code reusability. The Talk also explores how to handle API states and statuses in React, and provides examples of canceling requests with Axios and React Query. Additionally, it explains how to use the API layer with React Query for simplified API management.
Run Games Within Your React Native Apps
React Day Berlin 2022React Day Berlin 2022
28 min
Run Games Within Your React Native Apps
Top Content
Today's Talk discusses integrating Unity into React Native apps for game development. Unity provides a wide range of capabilities and can be seamlessly integrated with React Native. The integration involves using the Unity View component and the Unity Message callback to enable communication between the two platforms. Native plugins are created to facilitate communication between Unity and React Native. The performance of Unity in React Native apps is comparable to regular React Native apps, and the decision to use Unity or React Native depends on the app's use case and need for advanced UI and gaming capabilities.
How to Share Code between React Web App and React Native Mobile App in Monorepo
React Summit 2022React Summit 2022
7 min
How to Share Code between React Web App and React Native Mobile App in Monorepo
This presentation focuses on sharing code between React web and React native mobile apps. The speaker demonstrates how to achieve feature parity using a Monorepo with NX. They highlight the importance of sharing non-UI code, such as business logic and state management, through shared libraries. This approach allows the apps to focus on UI code while keeping non-UI code separate. For more details, refer to the speaker's blog post.